La mise en œuvre d'un détecteur d'angle Harris
-
27-09-2019 - |
Question
Je suis un détecteur de mise en œuvre de coin Harris à des fins éducatives, mais je suis coincé dans la partie de la réponse harris. En gros, ce que je fais, est:
- Calculer les gradients d'intensité de l'image dans la direction x et y
- sortie flou de (1)
- Calculer réponse Harris sur la sortie de (2)
- Suppress non maximas en sortie (3) dans une sortie 3x3-quartier et le seuil
1 et 2 semblent fonctionner correctement; cependant, je reçois des valeurs très petites comme la réponse Harris, et aucun point n'atteint le seuil. L'entrée est une norme photographie en plein air.
[...]
[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
Pour l'image échantillon, les extrémités max étant jusqu'à 6.4163e-018 qui semble beaucoup trop faible.
La solution
Un coin dans la détection d'angle Harris est défini comme « le pixel le plus de valeur dans une région » (généralement 3X3
ou 5x5
) donc vos commentaires sur aucun point d'atteindre un « seuil » me paraît étrange. Il suffit de recueillir tous les pixels qui ont une valeur supérieure à tous les autres pixels dans le quartier de 5x5
autour d'eux.
En dehors de cela: Je ne suis pas sûr à 100%, mais je pense que vous devriez avoir:
K(j,i) = det(H) - lambda*(trace(H)^2)
Où lambda est une constante positive qui fonctionne dans votre cas (et Harris ont suggéré la valeur est de 0,04).
En général, le seul moment raisonnable pour filtrer vos commentaires est avant ce point:
[Ix, Iy] = intensityGradients(img);
Filtrage Ix2
, Iy2
et Ixy
ne fait pas de sens pour moi.
De plus, je pense que votre exemple de code est erroné ici (fonctionne-t harrisResponse
deux ou trois variables d'entrée?):
H = harrisResponse(Ix2, Ixy, Iy2);
[...]
function K = harrisResponse(Ix, Iy)
Autres conseils
La solution que je python Mis en œuvre avec, ça marche pour moi, j'espère que vous trouverez ce que vous cherchez
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)
mise en œuvre proposée est terriblement inefficace. Permet de démarrage après avoir calculé gradients (qui peuvent être optimisés trop):
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(:))
Pas de boucles nécessaire, parce que Matlab déteste les boucles.
En gros, la détection d'angle Harris aura 5 étapes:
- calcul gradient
- lissage gaussien
- calcul de mesure Harris
- suppression non maximale
- Thresholding
Si vous implémentez dans Matlab, il sera facile de comprendre l'algorithme et obtenir les résultats.
Le code suivant de Matlab peut vous aider à résoudre vos doutes:
% 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);
Il y a une fonction pour que, dans le système de vision par ordinateur Boîte à outils appelé detectHarrisFeatures
.