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:

  1. Calculer les gradients d'intensité de l'image dans la direction x et y
  2. sortie flou de (1)
  3. Calculer réponse Harris sur la sortie de (2)
  4. 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.

Était-ce utile?

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:

  1. calcul gradient
  2. lissage gaussien
  3. calcul de mesure Harris
  4. suppression non maximale
  5. 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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top