Я сам реализую Canny edgedetection на Python, и я застрял в части подавления максимумов. Я думал, что у меня правильный код, но я получаю очень плохой результат без каких-либо красивых строк. Для сравнения я использовал обнаружение края Канни с помощью Skimage, и ниже приведен результат (слева: величина градиента с помощью фильтров Собеля, посередине: после подавления немаксимумов, справа: результат Skimage Canny (и я знаю, что это после пороговой обработки и гистерезиса). , но я ожидаю, что результаты после подавления не максимумов должны быть сопоставимы с исходом Canny skimage)).
Вот код, который я использовал для подавления не максимума:
def non_max_sup8(magn,direct):
size=magn.shape
out=np.zeros_like(magn)
direct=np.rad2deg(direct)+180 # direction is now between 0 and 360
for i in range(1,size[0]-1):
for j in range(1,size[1]-1):
if 0<=direct[i,j]<22.5 or 337.5<=direct[i,j]<=360 or 157.5<=direct[i,j]<202.5:
before=magn[i,j-1] # compare to left and right
after=magn[i,j+1]
elif 22.5<=direct[i,j]<67.5 or 202.5<=direct[i,j]<247.5:
before=magn[i+1,j-1] # compare diagonally
after=magn[i-1,j+1]
elif 67.5<=direct[i,j]<112.5 or 247.5<=direct[i,j]<292.5:
before=magn[i+1,j] # compare above and under
after=magn[i-1,j]
else:
before=magn[i-1,j-1] # compare diagonally
after=magn[i+1,j+1]
if magn[i,j]>=before and magn[i,j]>=after:
out[i,j]=magn[i,j]
return out
Градиенты рассчитываются следующим образом и должны быть правильными. (Направление указано в радианах между -pi и pi и в приведенном выше коде преобразовано в диапазон от 0 до 360 градусов)
def edges(img,filterv=vSobel,filterh=hSobel):
height,width = img.shape
magn=np.zeros_like(img)
direc=np.zeros_like(img)
X=np.zeros_like(img)
Y=np.zeros_like(img)
for y in range(3,height-2):
for x in range(3,width-2):
box = img[x-1:x+2,y-1:y+2]
transformv = filterv * box
Gy = transformv.sum()/4
transformh = filterh * box
Gx = transformh.sum()/4
X[x,y] = Gx
Y[x,y] = Gy
magn[x,y]=np.sqrt(Gx**2+Gy**2)
direc[x,y]=np.arctan2(Gy,Gx)
return X,Y,magn,direc
Итак, мой вопрос: что я делаю неправильно? Я думаю о следующем, но я хотел бы услышать ваши мысли: предположим, что направление составляет 90 градусов (то есть вверх), тогда я подумал, что вы на самом деле хотите сравнить с пикселем справа и слева, а не снизу и сверху (как я делал до сейчас), с тех пор вы получаете край одного пикселя. Однако я основывал свой код на вещах, которые нашел в Интернете, и, кажется, все они делают что-то вроде вышеприведенного: сравнивают пиксели в направлении градиента, а не в нормальном направлении. Что Вы думаете об этом? Я что-то не понимаю, или моя идея не так уж и плоха?
РЕДАКТИРОВАТЬ: попытка вышеизложенного (сравнение пикселя с двумя пикселями в нормальном направлении, а не в направлении пикселя) дает результат, аналогичный обнаружению хитрых краев skimage.
С уважением.
Gx = transformv
выглядит неправильно. v для вертикального, нет? И x горизонтальный, нет? Ваш результат согласуется с поворотом направлений на 90 градусов. Я рекомендую вам построить и изучить изображение направления и сравнить его с вашими ожиданиями в соответствии с краями изображения. - person Cris Luengo   schedule 12.05.2020filterv
на самом деле был фильтром, используемым для вычисления Gx, так что он устраняет ошибку, ха-ха! Я изменю это в своем вопросе :) - person Katie   schedule 12.05.2020direct
, чтобы убедиться, что они соответствуют вашим ожиданиям. Возможно, вам придется использовать-direct
,direct+90
или90-direct
или какое-либо подобное преобразование, чтобы углы соответствовали направлению поперек краев. - person Cris Luengo   schedule 12.05.2020