Реализация углового детектора Харриса

Я внедряю угловой детектор Харриса в образовательных целях, но я застрял в ответной части Харриса. В основном, что я делаю, это:

  1. Вычислить градиенты интенсивности изображения в x- и y-направлении
  2. Размытие (1)
  3. Вычислите ответ Харриса по выходным данным (2)
  4. Подавить немаксимумы в выводе (3) в окрестности 3x3 и пороговом выводе

1 и 2 работают нормально; однако я получаю очень маленькие значения в качестве ответа Харриса, и ни одна точка не достигает порога. На входе стандартная фотосъемка на открытом воздухе.

[...]
[Ix, Iy] = intensityGradients(img);
g = fspecial('gaussian');
Ix = imfilter(Ix, g);
Iy = imfilter(Iy, g);
H = harrisResponse(Ix, Iy);
[...]

function K = harrisResponse(Ix, Iy)
    max = 0;
    [sy, sx] = size(Ix);
    K = zeros(sy, sx);
    for i = 1:sx,
        for j = 1:sy,
            H = [Ix(j,i) * Ix(j,i), Ix(j,i) * Iy(j,i)
                Ix(j,i) * Iy(j,i), Iy(j,i) * Iy(j,i)];
            K(j,i) = det(H) / trace(H);
            if K(j,i) > max,
                max = K(j,i);
            end
        end
    end
    max
end

Для образца изображения максимальное значение составляет 6,4163e-018, что кажется слишком низким.


person Etan    schedule 05.10.2010    source источник


Ответы (5)


Угол в обнаружении углов Харриса определяется как «пиксель с наивысшим значением в области» (обычно 3X3 или 5x5), поэтому ваш комментарий о том, что точка не достигает «порога», кажется мне странным. Просто соберите все пиксели, которые имеют более высокое значение, чем все остальные пиксели в окрестности 5x5 вокруг них.

Кроме того: я не уверен на 100%, но я думаю, что вы должны иметь:

K(j,i) = det(H) - lambda*(trace(H)^2) Где лямбда - положительная константа, которая работает в вашем случае (и предлагаемое значение Харриса равно 0,04).

В общем, единственный разумный момент для фильтрации вашего ввода - до этого момента:

[Ix, Iy] = intensityGradients(img);

Фильтрация Ix2, Iy2 и Ixy не имеет для меня особого смысла.

Кроме того, я думаю, что ваш пример кода здесь неверен (есть ли у функции harrisResponse две или три входные переменные?):

H = harrisResponse(Ix2, Ixy, Iy2);
[...]

function K = harrisResponse(Ix, Iy)
person jilles de wit    schedule 05.10.2010
comment
Я вернулся к тому, чтобы больше не фильтровать Ix2 и т. д., поэтому в копии на stackoverflow осталась некоторая ошибка. - person Etan; 05.10.2010
comment
Проблема заключалась в том, что я не суммировал все пиксели в квадрате 3x3, чтобы узнать Ix2 и т. д.; вместо этого я просто использовал соответствующий пиксель. После изменения H таким образом, что он суммирует все Ix2, Ixy и Iy2 для всех 9 пикселей, это выглядит очень красиво. - person Etan; 05.10.2010
comment
det(H)/trace(H) — часто используемое приближение в случае, когда у вас не будет лямбды. - person Etan; 05.10.2010
comment
Я не знал о последнем трюке. Хороший. Кажется, ты решил проблему сам, молодец! (и старый трюк все еще работает: простое объяснение проблемы кому-то поможет вам найти решение) это рабочий код? - person jilles de wit; 05.10.2010

Решение, которое я реализовал с помощью python, у меня работает, надеюсь, вы найдете то, что ищете.

import numpy as np
import matplotlib.pyplot as plt
from PIL.Image import *
from scipy import ndimage

def imap1(im):
    print('testing the picture . . .')
    a = Image.getpixel(im, (0, 0))
    if type(a) == int:
        return im
    else:
        c, l = im.size
        imarr = np.asarray(im)
        neim = np.zeros((l, c))
        for i in range(l):
            for j in range(c):
                t = imarr[i, j]
                ts = sum(t)/len(t)
                neim[i, j] = ts
        return neim

def Harris(im):
    neim = imap1(im)
    imarr = np.asarray(neim, dtype=np.float64)
    ix = ndimage.sobel(imarr, 0)
    iy = ndimage.sobel(imarr, 1)
    ix2 = ix * ix
    iy2 = iy * iy
    ixy = ix * iy
    ix2 = ndimage.gaussian_filter(ix2, sigma=2)
    iy2 = ndimage.gaussian_filter(iy2, sigma=2)
    ixy = ndimage.gaussian_filter(ixy, sigma=2)
    c, l = imarr.shape
    result = np.zeros((c, l))
    r = np.zeros((c, l))
    rmax = 0
    for i in range(c):
        print('loking for corner . . .')
        for j in range(l):
            print('test ',j)
            m = np.array([[ix2[i, j], ixy[i, j]], [ixy[i, j], iy2[i, j]]], dtype=np.float64)
            r[i, j] = np.linalg.det(m) - 0.04 * (np.power(np.trace(m), 2))
            if r[i, j] > rmax:
                rmax = r[i, j]
    for i in range(c - 1):
        print(". .")
        for j in range(l - 1):
            print('loking')
            if r[i, j] > 0.01 * rmax and r[i, j] > r[i-1, j-1] and r[i, j] > r[i-1, j+1]\
                                     and r[i, j] > r[i+1, j-1] and r[i, j] > r[i+1, j+1]:
                result[i, j] = 1

    pc, pr = np.where(result == 1)
    plt.plot(pr, pc, 'r+')
    plt.savefig('harris_test.png')
    plt.imshow(im, 'gray')
    plt.show()
    # plt.imsave('harris_test.png', im, 'gray')

im = open('chess.png')
Harris(im)
person Walid Bousseta    schedule 07.05.2017
comment
что такое пк, и пр что он дает? - person acoustic python; 16.11.2020
comment
@acousticpython pc и pr являются индексами, где result == 1, означает, что result[pc][pr] == 1, элементы в pc и pr в одной и той же позиции, где результат равен единице в массиве 2d - person Walid Bousseta; 16.11.2020

По сути, обнаружение угла Харриса будет состоять из 5 шагов:

  1. Вычисление градиента
  2. Гауссово сглаживание
  3. Вычисление меры Харриса
  4. Немаксимальное подавление
  5. Порог

Если вы реализуете в MATLAB, будет легко понять алгоритм и получить результаты.

Следующий код MATLAB может помочь вам решить ваши сомнения:

% Step 1: Compute derivatives of image
Ix = conv2(im, dx, 'same');
Iy = conv2(im, dy, 'same');

% Step 2: Smooth space image derivatives (gaussian filtering)
Ix2 = conv2(Ix .^ 2, g, 'same');
Iy2 = conv2(Iy .^ 2, g, 'same');
Ixy = conv2(Ix .* Iy, g, 'same');

% Step 3: Harris corner measure
harris = (Ix2 .* Iy2 - Ixy .^ 2) ./ (Ix2 + Iy2);

% Step 4: Find local maxima (non maximum suppression)
mx = ordfilt2(harris, size .^ 2, ones(size));

% Step 5: Thresholding
harris = (harris == mx) & (harris > threshold);
person Megha Billure    schedule 21.04.2016

Предлагаемая реализация ужасно неэффективна. Начнем с расчета градиентов (которые тоже можно оптимизировать):

A = Ix.^2;
B = Iy.^2;
C = (Ix.*Iy).^4;
lambda = 0.04;

H = (A.*B - C) - lambda*(A+B).^2;

% if you really need max:
max(H(:))

Никаких циклов не требуется, потому что Matlab ненавидит циклы.

person Piotr    schedule 17.09.2013
comment
Но зачем вычислять C = (Ix.*Iy).^4 вместо простого C = (Ix.*Iy)? - person Hilder Vitor Lima Pereira; 31.03.2015

Для этого в наборе инструментов системы компьютерного зрения есть функция detectHarrisFeatures.

person Dima    schedule 10.04.2014