Реализация детектора углов Harris
Я внедряю детектор углов Harris в образовательных целях, но я застрял в части ответа Харриса. В основном то, что я делаю, это:
- Вычислить градиенты интенсивности изображения в x- и y-направлении
- Размытие выхода (1)
- Вычислить ответ Харриса по выходу (2)
- Подавить немаксимумы на выходе (3) в 3х3-окрестности и пороговом выходе
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
Для примера изображения max в конечном итоге составляет 6,4163e-018, что кажется слишком низким.
6 ответов
Угол в определении угла Харриса определяется как "пиксель с самым высоким значением в регионе" (обычно 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)
Решение, которое я реализовал с помощью 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)
В основном, обнаружение угла Харриса будет иметь 5 шагов:
- Вычисление градиента
- Гауссово сглаживание
- Вычисление меры Харриса
- Не максимальное подавление
- Thresholding
Если вы внедряете в 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);
Предлагаемая реализация ужасно неэффективна. Давайте начнем после вычисления градиентов (которые также могут быть оптимизированы):
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 ненавидит петли.
Определитель H, как у вас есть, равен нулю
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)];
det(H) = (Ix(j,i)^2) * (Iy(j,i)^2) - (Ix(j,i) * Iy(j,i)) * (Ix(j,i) * Iy(j,i))
= 0
Для этого в Computer Vision System Toolbox есть функция, которая называется detectHarrisFeatures
,