Ви не шукаєте ребер (= межі між розширеними ділянками високого та низького значення сірого кольору), ви шукаєте хребти (тонкі лінії темніші або яскравіші, ніж їх околиці), тому крайові фільтри можуть бути не ідеальними: крайовий фільтр буде дають вам два боки (по одному на кожній стороні лінії) та низьку відповідь у середині рядка:

ДОДАТИ : Якщо вас попросили пояснити різницю між крайовим детектором та рейнджером. Я заздалегідь вибачаюся, якщо ця відповідь стає дуже довгою.
Крайовий детектор є (як правило) першим похідним оператором: Якщо ви уявляєте вхідне зображення як 3D-пейзаж, то крайовий детектор вимірює крутизну схилу в кожній точці цього пейзажу:

Якщо ви хочете виявити межу розширеної яскравої або темної області, це просто чудово. Але щодо жил на зображенні ОП він надасть вам точно так само: контури ліворуч та праворуч від кожної жилки:

Це також пояснює "схему подвійної лінії" в результатах детектора ребра Кенні:

Отже, як ви виявите ці тонкі лінії (тобто пасма)? Ідея полягає в тому, що значення пікселів можуть бути (локально) наближені поліномом 2-го порядку, тобто якщо функцією зображення є , то для малих значень і :gxy
g(x,y)≈12x2∂2g∂x2+xy∂2g∂x∂y+12y2∂2g∂y2+x∂g∂x+y∂g∂y+g(0,0)
або, у матричній формі:
g(x,y)≈12(xy).⎛⎝⎜∂2g∂x2∂2g∂x∂y∂2g∂x∂y∂2g∂y2⎞⎠⎟.(xy)+(xy).(∂g∂x∂g∂y)+g(0,0)
Матриця похідного другого порядку називається " Гессіанська матриця ". Він описує структуру 2-го порядку, яка нас цікавить.⎛⎝⎜∂2g∂x2∂2g∂x∂y∂2g∂x∂y∂2g∂y2⎞⎠⎟
Частину 2-го порядку цієї функції можна перетворити на суму двох парабол повернутих на деякий кут, розклавши матрицю Гессі вгорі на обертання на діагональну матрицю її власних значень ( Розкладання матриці ). Нас не хвилює обертання (ми хочемо виявити гребені в будь-якій орієнтації), тому нас цікавлять лише таλ1x2+λ2y2λ1λ2
Які форми можуть мати наближення цієї функції? Насправді, не так багато:

Для виявлення хребтів ми хочемо знайти ділянки на зображенні, які виглядають як останній із сюжетів вище, тому ми шукаємо райони, де головне власне значення гессі є великим (порівняно з другорядним власним значенням). Найпростіший спосіб виявити це - просто обчислити основне власне значення кожного пікселя - і саме це робить гребінний фільтр нижче.
Хребет фільтр , ймовірно , дасть кращі результати. Я спробував вбудований Mathematica RidgeFilter
(який обчислює основне власне значення матриці Гессі на кожен піксель) на вашому зображенні:

Як бачите, для кожної тонкої темної лінії існує лише один пік. Урожай бінарнізації та скелетонізації:

Після обрізки скелета та видалення дрібних компонентів (шуму) із зображення я отримую цей остаточний скелет:

Повний код математики:
ridges = RidgeFilter[ColorNegate@src];
skeleton = SkeletonTransform[Binarize[ridges, 0.007]];
DeleteSmallComponents[Pruning[skeleton, 50], 50]
ДОДАТИ:
Я не експерт по Matlab, я не знаю, чи має він вбудований фільтр хребта, але я можу показати вам, як реалізувати його "вручну" (знову ж таки, використовуючи Matematica). Як я вже сказав, хребетний фільтр є основним власним значенням матриці Гессі. Я можу обчислити це власне значення символічно в Mathematica:
eigenvalue=Last[Eigenvalues[(HxxHxyHxyHyy)]]
=>12(Hxx+Hyy+H2xx+4H2xy−2HxxHyy+H2yy−−−−−−−−−−−−−−−−−−−−−−−√)
Отже, що вам потрібно зробити - це обчислити другі похідні , , (використовуючи звуковий чи похідний гауссовий фільтр) і вставити їх в вираз вище, і у вас є ваш хребет-фільтр. H xy H yyHxxHxyHyy