No está buscando bordes (= bordes entre áreas extendidas de alto y bajo valor de gris), está buscando aristas (líneas finas más oscuras o más brillantes que su vecindario), por lo que los filtros de borde pueden no ser ideales: un filtro de borde será darle dos flancos (uno a cada lado de la línea) y una respuesta baja en el medio de la línea:
AGREGAR : Si se le ha pedido que explique la diferencia entre un detector de borde y un detector de cresta más claramente. Pido disculpas de antemano si esta respuesta es muy larga.
Un detector de bordes es (generalmente) un primer operador derivado: si imagina la imagen de entrada como un paisaje 3D, un detector de bordes mide la inclinación de la pendiente en cada punto de ese paisaje:
Si desea detectar el borde de una región brillante u oscura extendida, esto está bien. Pero para las venas en la imagen del OP, le dará lo mismo: los contornos a la izquierda y a la derecha de cada vena:
Eso también explica el "patrón de doble línea" en los resultados del detector de bordes Canny:
Entonces, ¿cómo se detectan estas líneas finas (es decir, crestas)? La idea es que los valores de píxel se puedan aproximar (localmente) por un polinomio de segundo orden, es decir, si la función de imagen es , entonces para valores pequeños de e :gxy
g(x,y)≈12x2∂2g∂x2+xy∂2g∂x∂y+12y2∂2g∂y2+x∂g∂x+y∂g∂y+g(0,0)
o, en 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)
La matriz derivada de segundo orden se llama " Matriz Hessiana". Describe la estructura de segundo orden que nos interesa.⎛⎝⎜∂2g∂x2∂2g∂x∂y∂2g∂x∂y∂2g∂y2⎞⎠⎟
La parte de segundo orden de esta función se puede transformar en la suma de dos parábolas rotadas por algún ángulo, descomponiendo la matriz de Hesse en una rotación multiplicada por una matriz diagonal de sus valores propios ( Descomposición matricial ). No nos importa la rotación (queremos detectar crestas en cualquier orientación), por lo que solo estamos interesados en yλ1x2+λ2y2λ1λ2
¿Qué tipo de formas puede tener esta aproximación de función? En realidad, no tantos:
Para detectar crestas, queremos encontrar áreas en la imagen que se vean como la última de las parcelas de arriba, por lo que estamos buscando áreas donde el valor propio mayor del Hessian sea grande (en comparación con el valor propio menor). La forma más sencilla de detectar eso es simplemente calcular el valor propio principal en cada píxel, y eso es lo que hace el filtro de cresta a continuación.
Un filtro de cresta probablemente dará mejores resultados. He intentado con Mathematica incorporado RidgeFilter
(que calcula el valor propio principal de la matriz de Hesse en cada píxel) en su imagen:
Como puede ver, solo hay un pico para cada línea oscura delgada. Rendimientos binarizantes y esqueletizantes:
Después de podar el esqueleto y eliminar pequeños componentes (ruido) de la imagen, obtengo este esqueleto final:
Código completo de Mathematica:
ridges = RidgeFilter[ColorNegate@src];
skeleton = SkeletonTransform[Binarize[ridges, 0.007]];
DeleteSmallComponents[Pruning[skeleton, 50], 50]
AÑADIR:
No soy un experto en Matlab, no sé si tiene un filtro de cresta incorporado, pero puedo mostrarle cómo implementarlo "a mano" (nuevamente, usando Matematica). Como dije, el filtro de cresta es el principal valor propio de la matriz de Hesse. Puedo calcular ese valor propio simbólicamente en Mathematica:
eigenvalue=Last[Eigenvalues[(HxxHxyHxyHyy)]]
=>12(Hxx+Hyy+H2xx+4H2xy−2HxxHyy+H2yy−−−−−−−−−−−−−−−−−−−−−−−√)
Entonces, lo que tiene que hacer es calcular las segundas derivadas , , (usando un sobel o derivado del filtro gaussiano) e insertarlas en la expresión anterior, y tienes tu filtro de cresta. H xy H yyHxxHxyHyy