10

Io sono l'attuazione di un rilevatore di angolo di Harris per scopi didattici, ma mi sono bloccato in parte risposta harris. Fondamentalmente, quello che sto facendo, è:L'implementazione di un rilevatore di angolo Harris

  1. Calcola gradienti di intensità dell'immagine in xey direzione
  2. uscita
  3. sfocatura di (1)
  4. risposta
  5. Calcola Harris oltre uscita (2)
  6. Sopprimere i valori non massimi in uscita di (3) in un 3x3-soglia e uscita di soglia

1 e 2 sembrano funzionare correttamente; tuttavia, ottengo valori molto piccoli come la risposta Harris, e nessun punto raggiungere la soglia. Ingresso è una fotografia outdoor standard.

[...] 
[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 

Per l'immagine del campione, max finisce per essere 6.4163e-018 che sembra troppo bassa.

risposta

7

Un angolo nel rilevamento angolo Harris è definito come "il pixel del valore più alto in una regione" (in genere 3X3 o 5x5) quindi il tuo commento su nessun punto che raggiunge una "soglia" mi sembra strano. Basta raccogliere tutti i pixel che hanno un valore superiore a quello di tutti gli altri pixel nel 5x5 quartiere intorno a loro.

A parte questo: io non sono sicuro al 100%, ma penso che si dovrebbe avere:

K(j,i) = det(H) - lambda*(trace(H)^2) Dove lambda è una costante positiva che funziona nel tuo caso (e Harris ha suggerito valore è 0,04).

In generale, l'unico momento ragionevole per filtrare l'ingresso è prima di questo punto:

[Ix, Iy] = intensityGradients(img);

Filtering Ix2, Iy2 e Ixy non ha molto senso per me.

Inoltre, penso che il codice di esempio è sbagliato qui (non funzione harrisResponse avere due o tre variabili di ingresso?):

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

function K = harrisResponse(Ix, Iy) 
+0

Non sono più stato in grado di filtrare Ix2 etc, quindi nella copia su StackOverflow ci sono stati alcuni errori. – Etan

+0

Il problema era che non ho riassunto tutti i pixel nel quadrato 3x3 per scoprire l'Ix2 ecc; invece, ho appena usato il pixel corrispondente. Dopo aver cambiato H in un modo che riassume tutti i Ix2, Ixy e Iy2 per tutti i 9 pixel, sembra molto bello. – Etan

+1

det (H)/trace (H) è un'approssimazione spesso usata nel caso in cui non si abbia una lambda. – Etan

3

proposto è terribilmente inefficiente. Lets' start dopo aver calcolato i gradienti (che possono essere ottimizzati troppo):

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(:)) 

nessun cicli richiesti, perché Matlab odia loop.

+2

Ma perché calcolare 'C = (Ix. * Iy).^4' invece di semplice' C = (Ix. * Iy) '? –

0

Esiste una funzione per questo nella casella degli strumenti del sistema di visione artificiale denominata detectHarrisFeatures.

3

Fondamentalmente, riconoscimento di angoli Harris avrà 5 passi:

  1. calcolo Pendenza
  2. Gaussian smoothing
  3. Harris misura calcolo
  4. non massimo di soppressione
  5. Thresholding

Se stai implementando in MATLAB, sarà facile capire l'algoritmo e ottenere i risultati.

Il seguente codice di MATLAB può aiutare a risolvere i vostri dubbi:

% 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

La soluzione che ho implementato con Python, funziona per me Spero che trovi quello che stai cercando per

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)