Non stai cercando bordi (= bordi tra aree estese di valore alto e basso grigio), stai cercando creste (linee sottili più scure o più luminose del loro vicinato), quindi i filtri dei bordi potrebbero non essere l'ideale: un filtro per bordi ti dà due fianchi (uno su ciascun lato della linea) e una risposta bassa nel mezzo della linea:
AGGIUNGI : se è stato chiesto di spiegare più chiaramente la differenza tra un rilevatore di bordi e un rilevatore di cresta. Mi scuso in anticipo se questa risposta sta diventando molto lunga.
Un rilevatore di bordi è (di solito) un primo operatore derivato: se immagini l'immagine di input come un paesaggio 3D, un rilevatore di bordi misura la pendenza della pendenza in ciascun punto di quel paesaggio:
Se vuoi rilevare il bordo di una regione chiara o scura estesa, va bene. Ma per le vene nell'immagine dell'OP ti darà lo stesso: i contorni sinistro e destro di ogni vena:
Ciò spiega anche il "modello a doppia linea" nei risultati del rilevatore di bordi Canny:
Quindi, come si rilevano queste linee sottili (es. Creste), allora? L'idea è che i valori dei pixel possono essere (localmente) approssimata da una 2a polinomio ordine, cioè se la funzione di immagine è , quindi per piccoli valori di ed :gxy
g(x,y)≈12x2∂2g∂x2+xy∂2g∂x∂y+12y2∂2g∂y2+x∂g∂x+y∂g∂y+g(0,0)
o, sotto forma di matrice:
g(x,y)≈12(xy).⎛⎝⎜∂2g∂x2∂2g∂x∂y∂2g∂x∂y∂2g∂y2⎞⎠⎟.(xy)+(xy).(∂g∂x∂g∂y)+g(0,0)
Matrice derivata del secondo ordine è chiamato " Matrice dell'Assia ". Descrive la struttura del 2 ° ordine a cui siamo interessati.⎛⎝⎜∂2g∂x2∂2g∂x∂y∂2g∂x∂y∂2g∂y2⎞⎠⎟
La parte del 2 ° ordine di questa funzione può essere trasformata nella somma di due parabole ruotate di un angolo, decomprimendo la matrice hessiana sopra a una rotazione per una matrice diagonale dei suoi autovalori ( Decomposizione della matrice ). Non ci interessa la rotazione (vogliamo rilevare le creste in qualsiasi orientamento), quindi siamo interessati solo a eλ1x2+λ2y2λ1λ2
Che tipo di forme può avere questa approssimazione di funzione? In realtà, non così tanti:
Per rilevare le creste, vogliamo trovare aree nell'immagine che assomiglino all'ultima delle trame sopra, quindi stiamo cercando aree in cui l'autovalore principale dell'Assia è grande (rispetto all'autovalore minore). Il modo più semplice per rilevare ciò è solo calcolare l'autovalore principale per ogni pixel - ed è quello che fa il filtro di cresta sottostante.
Un filtro di cresta probabilmente darà risultati migliori. Ho provato il built-in di Mathematica RidgeFilter
(che calcola il principale autovalore della matrice hessiana su ciascun pixel) sulla tua immagine:
Come puoi vedere, c'è un solo picco per ogni sottile linea scura. Rendimenti binarizzanti e scheletrici:
Dopo aver potato lo scheletro e rimosso i piccoli componenti (rumore) dall'immagine, ottengo questo scheletro finale:
Codice Mathematica completo:
ridges = RidgeFilter[ColorNegate@src];
skeleton = SkeletonTransform[Binarize[ridges, 0.007]];
DeleteSmallComponents[Pruning[skeleton, 50], 50]
INSERISCI:
Non sono un esperto di Matlab, non so se abbia un filtro di cresta integrato, ma posso mostrarti come implementarlo "a mano" (di nuovo, usando Matematica). Come ho detto, il filtro di cresta è il principale autovalore della matrice dell'Assia. Posso calcolare quell'autovalore simbolicamente in Mathematica:
eigenvalue=Last[Eigenvalues[(HxxHxyHxyHyy)]]
=>12(Hxx+Hyy+H2xx+4H2xy−2HxxHyy+H2yy−−−−−−−−−−−−−−−−−−−−−−−√)
Quindi, quello che devi fare è calcolare le seconde derivate , , (usando una sobel o una derivata del filtro gaussiano) e inserirle nell'espressione sopra e hai il tuo filtro cresta. H xy H yyHxxHxyHyy