10

Ich implementiere einen Harris-Eckendetektor für Bildungszwecke, aber ich stecke im Harris-Response-Teil fest. Im Grunde genommen, was ich tue, ist:Implementierung eines Harris-Eckendetektors

  1. Compute Bild Intensitätsgradienten in x- und y-Richtung
  2. Blur Ausgang (1)
  3. Compute Harris Antwort über Ausgang (2)
  4. Unterdrücken von nicht Maximas in Ausgang (3) in einer 3x3-Nachbarschaft und Schwellenausgabe

1 und 2 scheinen gut zu funktionieren; Allerdings erhalte ich sehr kleine Werte als Harris-Antwort und kein Punkt erreicht den Schwellenwert. Input ist eine Standard-Outdoor-Fotografie.

Für das Beispielbild endet max 6.4163e-018, die viel zu niedrig scheint.

Antwort

7

Eine Ecke in Harris Corner Detection ist definiert als "der höchste Wert Pixel in einer Region" (in der Regel 3X3 oder 5x5), so dass Ihr Kommentar über keinen Punkt erreicht eine "Schwelle" scheint mir seltsam. Sammeln Sie einfach alle Pixel, die einen höheren Wert haben als alle anderen Pixel in der Umgebung von 5x5.

Abgesehen davon: Ich bin nicht 100% sicher, aber ich denke, Sie haben sollten:

K(j,i) = det(H) - lambda*(trace(H)^2) Wo Lambda eine positive Konstante ist, die in Ihrem Fall funktioniert (und Harris vorgeschlagene Wert ist 0,04).

Im Allgemeinen ist die einzig sinnvolle Moment Ihre Eingabe zu filtern, ist vor diesem Punkt:

[Ix, Iy] = intensityGradients(img);

Filtering Ix2, Iy2 und Ixy nicht viel Sinn für mich macht.

Des Weiteren denke ich, Ihr Beispielcode falsch ist hier (nicht Funktion harrisResponse haben zwei oder drei Eingangsgrößen?):

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

function K = harrisResponse(Ix, Iy) 
+0

Ich habe mich dazu entschieden, Ix2 nicht mehr zu filtern, daher gab es einen Bug in der Kopie auf Stackoverflow. – Etan

+0

Das Problem war, dass ich nicht alle Pixel im 3x3-Quadrat zusammenfasste, um den Ix2 usw. herauszufinden; stattdessen habe ich gerade das entsprechende Pixel verwendet. Nachdem H so geändert wurde, dass es alle Ix2, Ixy und Iy2 für alle 9 Pixel zusammenfasst, sieht es sehr gut aus. – Etan

+1

det (H)/Spur (H) ist eine häufig verwendete Näherung für den Fall, dass Sie kein Lambda haben. – Etan

3

vorgeschlagene Umsetzung 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 Schleifen hasst.

+2

Aber warum berechnen Sie 'C = (Ix. * Iy).^4' anstatt einfach' C = (Ix. * Iy) '? –

0

Es gibt eine Funktion dafür in der Computer Vision System Toolbox mit der Bezeichnung detectHarrisFeatures.

3

Grundsätzlich wird Harris Eckendetektion 5 Schritte haben:

  1. Gradientenberechnung
  2. Gaussian
  3. Harris Maß Berechnung
  4. nicht maximalen Unterdrückung
  5. Thresholding
Glättungs

Wenn Sie in implementieren MATLAB, wird es einfach sein, den Algorithmus zu verstehen und die Ergebnisse zu erhalten.

Der folgende Code von MATLAB Sie Ihre Zweifel lösen helfen können:

für mich
% 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); 
1

Die Lösung, die ich mit Python implementiert, es funktioniert 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)