2009-02-25 6 views
6

Sto provando a scrivere un algoritmo di rilevamento della cresta e tutte le fonti che ho trovato sembrano confondere il rilevamento dei bordi con il rilevamento delle creste. Al momento, ho implementato l'algoritmo di rilevamento dei bordi di Canny, ma non è quello che voglio: ad esempio, data una singola riga nell'immagine, la tradurrà efficacemente in una doppia linea di bordi (poiché registrerà sia lati della linea) - Voglio solo che legga la prima riga.Rilevamento cresta implementazione

wikipedia article Il rilevamento di cresta ha un po 'di matematica, ma questo tipo di questo non mi aiuta come programmatore (non che io sia contrario alla matematica, ma non è il mio campo, e non capisco come tradurre le loro equazioni differenziali in codice). C'è una buona fonte per l'implementazione effettiva di questo? O, del resto, esiste una buona implementazione open source?

Modifica: ecco il semplice esempio. Si comincia con una semplice linea:

http://img24.imageshack.us/img24/8112/linez.th.png

e eseguire l'algoritmo Canny per ottenere:

http://img12.imageshack.us/img12/1317/canny.th.png

(si può vedere che è più spesso qui - se si fa clic su l'immagine, vedrai che in realtà sono due righe adiacenti con uno spazio vuoto intermedio)

Inoltre, sto scrivendo g in C++, ma non dovrebbe essere importante. Ma voglio codificare l'algoritmo , non solo scrivere SomePackage::findRidges() e farlo.

+0

in che lingua stai scrivendo? Matlab ha funzioni che gestiscono proprio questo. Sarei sorpreso se anche R non lo fosse. –

+0

C++, ma sto cercando l'algoritmo! –

+0

Penso che tu abbia un problema di soglia, piuttosto che un problema di ricerca della cresta. –

risposta

5

Forse hai bisogno di pensare in termini di pulizia della linea che hai già, piuttosto che un rilevamento di bordo tipo Canny. Sembra che tu debba essere in grado di fare qualcosa con image morphology, in particolare sto pensando alle operazioni di tipo skeletonize e ultimate eroded points. Usati appropriatamente, questi dovrebbero rimuovere dall'immagine qualsiasi funzionalità che non sia 'linee' - credo che siano implementate nella libreria Intel OpenCV.

È possibile recuperare una singola linea dalla doppia linea generata utilizzando il filtro Canny utilizzando un'operazione di dilatazione seguita da 3 erodi (l'ho provata in ImageJ), questo dovrebbe rimuovere anche eventuali spigoli.

2

Stavo per suggerire di ripulire le tue battute come ha detto Ian, ma se non vuoi farlo, potresti anche cercare di fare qualche variante di una trasformazione del cuore.

http://en.wikipedia.org/wiki/Hough_transform

Si dovrebbe essere in grado di ottenere l'equazione attuale per la linea da questo, in modo da poter rendere il più sottile o spesso come ti piace. L'unica parte difficile è capire dove finisce la linea.

Ecco il codice che ho scritto per un hif trasformato alcuni anni fa, scritto in MATLAB. Non sono sicuro di quanto funzioni bene, ma dovrebbe darti un'idea generale. Troverà tutte le linee (non i segmenti) in un'immagine

im = imread('cube.tif'); 
[bin1,bin2,bin3] = canny(im); 

%% define constants 
binary = bin1; 
distStep = 10; % in pixels 
angStep = 6; % in degrees 
thresh = 50; 

%% vote 
maxDist = sqrt((size(binary,1))^2+(size(binary,2))^2); 
angLoop = 0:angStep*pi/180:pi; 
origin = size(binary)/2; 
accum = zeros(ceil(maxDist/distStep)+1,ceil(360/angStep)+1); 

for y=1:size(binary,2) 
    for x=1:size(binary,1) 
    if binary(x,y) 
     for t = angLoop 
     dx = x-origin(1); 
     dy = y-origin(2); 
     r = x*cos(t)+y*sin(t); 
     if r < 0 
      r = -r; 
      t = t + pi; 
     end 
     ri = round(r/distStep)+1; 
     ti = round(t*180/pi/angStep)+1; 
     accum(ri,ti) = accum(ri,ti)+1; 
     end 
    end 
    end 
end 
imagesc(accum); 

%% find local maxima in accumulator 
accumThresh = accum - thresh; 
accumThresh(logical(accumThresh<0)) = 0; 
accumMax = imregionalmax(accumThresh); 
imagesc(accumMax); 

%% calculate radius & angle of lines 
dist = []; 
ang = []; 
for t=1:size(accumMax,2) 
    for r=1:size(accumMax,1) 
    if accumMax(r,t) 
     ang = [ang;(t-1)*angStep/180*pi]; 
     dist = [dist;(r-1)*distStep]; 
    end 
    end 
end 
scatter(ang,dist); 
+0

Lo sto già facendo - il problema è che l'algoritmo Canny dà i doppi spigoli, come ho descritto. Quindi ho bisogno di un passaggio migliore n. 1) –

+0

Bene, se tutte le immagini sono simili, puoi saltare il passaggio 1. Altrimenti, se stai usando un'immagine reale, non dovresti avere linee sottili come quella, e canny non dovresti darti problemi, no? Solo un pensiero. – mpen

+0

Credo che il problema di Jesse sia come * contrassegnare * la linea di cresta, dopo che ovviamente è possibile applicare la trasformazione di Hough per ottenere i parametri della linea, ma non è questo il suo punto qui. – jasxun