Implementieren eines Harris Eckendetektor
-
27-09-2019 - |
Frage
Ich bin der Umsetzung einer Ecke Harris Detektor für pädagogische Zwecke, aber ich bin an der harris Antwort Teil stecken. Im Grunde, was ich tue, ist:
- Compute Bild Intensitätsgradienten in x- und y-Richtung
- Blur Ausgabe von (1)
- Compute Harris Antwort über Ausgabe von (2)
- Suppress nicht-Maximas in Ausgang (3) in einem 3x3-Nachbarschaft und Schwellenausgang
1 und 2 scheinen zu funktionieren; Allerdings bekomme ich sehr kleine Werte wie die Harris Antwort und keinen Punkt hat die Schwelle zu erreichen. Eingang ist eine Standard-Outdoor-Fotografie.
[...]
[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
Für das Beispielbild, max endet als 6.4163e-018, die viel zu niedrig erscheint.
Lösung
Eine Ecke in Harris Eckendetektion wird als „der höchste Pixelwert in einem Bereich“ (in der Regel 3X3
oder 5x5
) definiert, um Ihr Kommentar zu keinem Zeitpunkt eine „Schwelle“ erreicht mich fremd zu sein scheint. Sammeln Sie einfach alle Pixel, die einen höheren Wert als alle anderen Pixel in der 5x5
Nachbarschaft um sie herum haben.
Ansonsten: Ich bin nicht 100% sicher, aber ich denke, Sie sollten haben:
K(j,i) = det(H) - lambda*(trace(H)^2)
Wo Lambda eine positive Konstante ist, dass die Arbeiten in Ihrem Fall (und Harris vorgeschlagene Wert ist 0,04).
Im Allgemeinen ist der einzige vernünftige Moment Ihre Eingabe zu filtern, ist vor diesem Punkt:
[Ix, Iy] = intensityGradients(img);
Das Filtern Ix2
, Iy2
und Ixy
nicht viel Sinn für mich macht.
Außerdem denke ich, Ihr Beispielcode hier falsch ist (tut Funktion harrisResponse
haben zwei oder drei Eingangsgrößen?):
H = harrisResponse(Ix2, Ixy, Iy2);
[...]
function K = harrisResponse(Ix, Iy)
Andere Tipps
Die Lösung, dass ich mit Python implementiert, es funktioniert für mich Ich hoffe, Sie finden, was Sie suchen
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)
Vorgeschlagene Implementierung ist schrecklich ineffizient. Lets' starten, nachdem Gradienten Berechnung (die auch optimiert werden kann):
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(:))
keine Schleifen erforderlich, da Matlab hasst Schleifen.
Im Grunde Erkennung Harris Ecke wird 5 Stufen hat:
- Gradient Berechnung
- Gaußglättung
- Harris Maß Berechnung
- Nicht maximale Unterdrückung
- Thresholding
Wenn Sie in MATLAB implementieren, wird es leicht sein, den Algorithmus zu verstehen und die Ergebnisse erhalten.
Der folgende Code von MATLAB kann Ihnen helfen, Ihre Zweifel zu lösen:
% 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);
Es gibt eine Funktion für den in der Computer Vision System Toolbox namens detectHarrisFeatures
.