Когато става въпрос за класифициране на изображения, човешкото око има невероятната способност да обработва изображение за няколко милисекунди и да определя за какво става въпрос (етикет). Толкова е невероятно, че може да го направи, независимо дали е рисунка или снимка.

Идеята днес е да се изгради алгоритъм, който може да скицира краищата на всеки обект, присъстващ на картина, използвайки алгоритъма за откриване на ръбове на Canny.

Първо, нека опишем какво представлява Canny Edge Detector:

Детекторът на ръбове Canny е оператор за „откриване на ръбове“, който използва многоетапен „алгоритъм“ за откриване на широк диапазон от ръбове в изображенията. Тя е разработена от John F. Canny през 1986 г. Canny също създава изчислителна теория за откриване на ръбове, обяснявайки защо техниката работи. (Уикипедия)

Алгоритъмът за откриване на ръба на Canny се състои от 5 стъпки:

  1. Намаляване на шума;
  2. Изчисляване на градиента;
  3. Не-максимално потискане;
  4. Двоен праг;
  5. Проследяване на ръба чрез хистерезис.

След като приложите тези стъпки, ще можете да получите следния резултат:

Едно последно важно нещо, което трябва да споменем, е, че алгоритъмът е базиран на изображения в сива скала. Следователно, предварителното условие е да конвертирате изображението в нива на сивото, преди да следвате гореспоменатите стъпки.

Намаляване на шума

Тъй като математиката, използвана зад сцената, се основава главно на производни (вж. Стъпка 2: Изчисление на градиента), резултатите от откриването на ръбове са силно чувствителни към шума в изображението.

Един от начините да се отървете от шума в изображението е чрез прилагане на размазване по Гаус, за да го изгладите. За да направите това, техниката за навиване на изображението се прилага с гаусово ядро ​​(3x3, 5x5, 7x7 и т.н.). Размерът на ядрото зависи от очаквания ефект на размазване. По принцип, колкото по-малко е ядрото, толкова по-малко видимо е размазването. В нашия пример ще използваме гаусово ядро ​​5 на 5.

Уравнението за гаусово филтърно ядро ​​с размер (2k+1)×(2k+1) се дава от:

Код на Python за генериране на ядрото Gaussian 5x5:

След прилагане на Gaussian blur получаваме следния резултат:

Изчисляване на градиента

Стъпката за изчисляване на градиента открива интензитета и посоката на ръба чрез изчисляване на градиента на изображението с помощта на оператори за откриване на ръба.

Ръбовете съответстват на промяна в интензитета на пикселите. За да го откриете, най-лесният начин е да приложите филтри, които подчертават тази промяна на интензитета и в двете посоки: хоризонтална (x) и вертикална (y)

Когато изображението е изгладено, производните Ix и Iy w.r.t. x и y се изчисляват. Може да се реализира чрез конволюция на I с ядра SobelKx и Ky съответно:

След това големината G и наклонът θ на градиента се изчисляват, както следва:

По-долу е показано как филтрите на Sobel се прилагат към изображението и как да получите матрици за интензитет и посока на ръба:

Резултатът е почти очакваният, но виждаме, че някои от ръбовете са дебели, а други тънки. Стъпката на немаксимално потискане ще ни помогне да смекчим дебелите.

Освен това нивото на интензитета на градиента е между 0 и 255, което не е еднакво. Ръбовете на крайния резултат трябва да имат еднакъв интензитет (т.е. бял пиксел = 255).

Не-максимално потискане

В идеалния случай крайното изображение трябва да има тънки ръбове. Следователно трябва да извършим не-максимално потискане, за да изтъним ръбовете.

Принципът е прост: алгоритъмът преминава през всички точки на матрицата на градиентния интензитет и намира пикселите с максимална стойност в посоките на ръбовете.

Да вземем лесен пример:

Червеното поле в горния ляв ъгъл на изображението по-горе представлява пиксел за интензитет на обработваната матрица за интензитет на градиента. Съответната посока на ръба е представена от оранжевата стрелка с ъгъл от -pi радиана (+/-180 градуса).

Посоката на ръба е оранжевата пунктирана линия (хоризонтална отляво надясно). Целта на алгоритъма е да провери дали пикселите в една и съща посока са повече или по-малко интензивни от тези, които се обработват. В примера по-горе пикселът (i, j)се обработва и пикселите в същата посока са маркирани в синьо (i, j-1) и (i, j+1). Ако един от тези два пиксела е по-интензивен от този, който се обработва, тогава се запазва само по-интензивният. Пикселът (i, j-1)изглежда по-интензивен, защото е бял (стойност 255). Следователно стойността на интензитета на текущия пиксел (i, j) е зададена на 0. Ако няма пиксели в посоката на ръба с по-интензивни стойности, тогава стойността от текущия пиксел се запазва.

Нека сега се съсредоточим върху друг пример:

В този случай посоката е оранжевата пунктирана диагонална линия. Следователно най-интензивният пиксел в тази посока е пикселът (i-1, j+1).

Нека обобщим това. Всеки пиксел има 2 основни критерия (посока на ръба в радиани и интензитет на пиксела (между 0–255)). Въз основа на тези входни данни стъпките за немаксимално потискане са:

  • Създайте матрица, инициализирана на 0, със същия размер на оригиналната матрица за интензитет на градиента;
  • Идентифицирайте посоката на ръба въз основа на стойността на ъгъла от ъгловата матрица;
  • Проверете дали пикселът в същата посока има по-висок интензитет от пиксела, който се обработва в момента;
  • Връща изображението, обработено с алгоритъма за немаксимално потискане.

Резултатът е същото изображение с по-тънки ръбове. Все пак можем да забележим някои вариации по отношение на интензитета на ръбовете: някои пиксели изглеждат по-ярки от други и ние ще се опитаме да покрием този недостатък с двете последни стъпки.

Двоен праг

Стъпката с двоен праг има за цел да идентифицира 3 вида пиксели: силни, слаби и неуместни:

  • Силните пиксели са пиксели, които имат толкова висок интензитет, че сме сигурни, че допринасят за крайния ръб.
  • Слабите пиксели са пиксели, които имат стойност на интензитет, която не е достатъчна, за да се считат за силни, но все пак не са достатъчно малки, за да се считат за нерелевантни за откриване на ръбове.
  • Други пиксели се считат за нерелевантни за ръба.

Сега можете да видите какво означават двойните прагове:

  • Високият праг се използва за идентифициране на силните пиксели (интензитет по-висок от високия праг)
  • Ниският праг се използва за идентифициране на неподходящите пиксели (интензитет по-нисък от долния праг)
  • Всички пиксели с интензитет между двата прага са маркирани като слаби и механизмът на хистерезис (следваща стъпка) ще ни помогне да идентифицираме тези, които могат да се считат за силни, и тези, които се считат за неуместни.

Резултатът от тази стъпка е изображение само с 2 стойности на интензитета на пиксела (силна и слаба):

Проследяване на ръба чрез хистерезис

Въз основа на праговите резултати хистерезисът се състои от трансформиране на слаби пиксели в силни, ако и само ако поне един от пикселите около този, който се обработва, е силен, както е описано по-долу:

Целият използван код е наличен в следното хранилище на Git



Библиография