Pergunta

Estou implementando um detector de canto Harris para fins educacionais, mas estou preso na parte da resposta de Harris.Basicamente, o que estou fazendo é:

  1. Calcular gradientes de intensidade de imagem nas direções x e y
  2. Saída de desfoque de (1)
  3. Calcule a resposta de Harris sobre a saída de (2)
  4. Suprimir não máximos na saída de (3) em uma vizinhança 3x3 e saída limite

1 e 2 parecem funcionar bem;no entanto, obtenho valores muito pequenos como resposta de Harris e nenhum ponto atinge o limite.A entrada é uma fotografia externa padrão.

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

Para a imagem de exemplo, o máximo acaba sendo 6.4163e-018, o que parece muito baixo.

Foi útil?

Solução

Um canto na detecção de canto Harris é definido como "o pixel de maior valor em uma região" (geralmente 3X3 ou 5x5), então seu comentário sobre nenhum ponto em atingir um "limiar" parece estranho para mim.Basta coletar todos os pixels que possuem um valor maior que todos os outros pixels no 5x5 vizinhança ao seu redor.

Além disso:Não tenho 100% de certeza, mas acho que você deveria ter:

K(j,i) = det(H) - lambda*(trace(H)^2)Onde lambda é uma constante positiva que funciona no seu caso (e o valor sugerido por Harris é 0,04).

Em geral, o único momento sensato para filtrar sua entrada é antes deste ponto:

[Ix, Iy] = intensityGradients(img);

Filtragem Ix2, Iy2 e Ixy não faz muito sentido para mim.

Além disso, acho que seu código de exemplo está errado aqui (funciona harrisResponse tem duas ou três variáveis ​​de entrada?):

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

function K = harrisResponse(Ix, Iy)

Outras dicas

A solução que eu implementei com Python, funciona para mim, espero que você encontre o que está procurando

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)

A implementação proposta é terrivelmente ineficiente. Vamos começar após o cálculo de gradientes (que também podem ser otimizados):

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

Não são necessários loops, porque o Matlab odeia loops.

Basicamente, a detecção de canto de Harris terá 5 etapas:

  1. Computação de gradiente
  2. Suavização gaussiana
  3. Harris medem a computação
  4. Supressão não maximum
  5. Limiar

Se você estiver implementando no MATLAB, será fácil entender o algoritmo e obter os resultados.

O seguinte código do MATLAB pode ajudá -lo a resolver suas dúvidas:

% 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);

Há uma função para a caixa de ferramentas do sistema de visão computacional chamada detectHarrisFeatures.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top