Подавление не максимума в Python дает плохой результат: что не так?

Я сам реализую 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.

С уважением.


person Katie    schedule 12.05.2020    source источник
comment
Gx = transformv выглядит неправильно. v для вертикального, нет? И x горизонтальный, нет? Ваш результат согласуется с поворотом направлений на 90 градусов. Я рекомендую вам построить и изучить изображение направления и сравнить его с вашими ожиданиями в соответствии с краями изображения.   -  person Cris Luengo    schedule 12.05.2020
comment
Спасибо что подметил это! Я даже не заметил. Однако, что любопытно, я также поменял местами фильтры Собеля, так что filterv на самом деле был фильтром, используемым для вычисления Gx, так что он устраняет ошибку, ха-ха! Я изменю это в своем вопросе :)   -  person Katie    schedule 12.05.2020
comment
Тем не менее, посмотрите на значения direct, чтобы убедиться, что они соответствуют вашим ожиданиям. Возможно, вам придется использовать -direct, direct+90 или 90-direct или какое-либо подобное преобразование, чтобы углы соответствовали направлению поперек краев.   -  person Cris Luengo    schedule 12.05.2020


Ответы (1)


Порядок 45 и 135 неверен (изменен), потому что вы рассматриваете систему координат xy, когда вы должны работать с системами координат yx (45 градусов в yx эквивалентен 315 градусам в плоскости xy). Исходя из моей реализации, это должно быть:

#for 45
elif 22.5<=direct[i,j]<67.5 or 202.5<=direct[i,j]<247.5:
   before=magn[i-1,j-1]
   after=magn[i+1,j+1]

#for 135
else:
   before=magn[i+1,j-1]
   after=magn[i-1,j+1]
person Nursultan Makhanov    schedule 11.09.2020