Você não está procurando arestas (= bordas entre áreas estendidas de alto e baixo valor de cinza), está procurando arestas (linhas finas mais escuras ou mais brilhantes que a vizinhança); portanto, os filtros de arestas podem não ser o ideal: um filtro de aresta será dê a você dois flancos (um de cada lado da linha) e uma resposta baixa no meio da linha:
ADICIONAR : Se você foi solicitado a explicar a diferença entre um detector de borda e um detector de cume mais claramente. Peço desculpas antecipadamente se esta resposta estiver ficando muito longa.
Um detector de borda é (geralmente) o primeiro operador derivado: se você imaginar a imagem de entrada como uma paisagem 3D, um detector de borda mede a inclinação da inclinação em cada ponto da paisagem:
Se você deseja detectar a borda de uma região brilhante ou escura estendida, tudo bem. Mas, para as veias da imagem do OP, você fornecerá exatamente o mesmo: os contornos esquerdo e direito de cada veia:
Isso também explica o "padrão de linha dupla" nos resultados do detector de borda Canny:
gxy
g(x,y)≈12x2∂2g∂x2+xy∂2g∂x∂y+12y2∂2g∂y2+x∂g∂x+y∂g∂y+g(0,0)
ou, em forma de matriz:
g( x , y) ≈ 12( xy) . ⎛⎝⎜∂2g∂x2∂2g∂x∂y∂2g∂x∂y∂2g∂y2⎞⎠⎟. ( xy) + ( xy) . ( ∂g∂x∂g∂y) +g( 0 , 0 )
⎛⎝⎜∂2g∂x2∂2g∂x∂y∂2g∂x∂y∂2g∂y2⎞⎠⎟
λ1x2+ λ2y2λ1λ2
Que tipo de formas essa aproximação de função pode ter? Na verdade, não tantos:
Para detectar sulcos, queremos encontrar áreas na imagem que se pareçam com a última das plotagens acima, portanto, estamos procurando áreas em que o autovalor principal do Hessian seja grande (comparado ao autovalor menor). A maneira mais simples de detectar isso é apenas calcular o valor próprio principal em cada pixel - e é isso que o filtro de crista abaixo faz.
Um filtro de cume provavelmente dará melhores resultados. Eu tentei o Mathematica embutido RidgeFilter
(que calcula o principal autovalor da matriz Hessian em cada pixel) na sua imagem:
Como você pode ver, há apenas um pico para cada linha fina e escura. Rendimentos de binarização e esqueletização:
Depois de podar o esqueleto e remover pequenos componentes (ruído) da imagem, recebo este esqueleto final:
Código completo do Mathematica:
ridges = RidgeFilter[ColorNegate@src];
skeleton = SkeletonTransform[Binarize[ridges, 0.007]];
DeleteSmallComponents[Pruning[skeleton, 50], 50]
ADICIONAR, ACRESCENTAR:
Não sou especialista em Matlab, não sei se ele possui um filtro de cume interno, mas posso mostrar como implementá-lo "manualmente" (novamente, usando o Matematica). Como eu disse, o filtro de crista é o principal autovalor da matriz de Hessian. Eu posso calcular esse valor próprio simbolicamente no Mathematica:
autovalor = Último [ autovalores [ ( HxxHxyHxyHyy) ] ]
12( Hxx+ Hyy+ H2xx+ 4 H2xy- 2 HxxHyy+ H2yy-----------------------√)
HxxHxyHyy