Mastering OpenCV with Practical Computer Vision Projects / Опановуюємо OpenCV через практичні проекти комп'ютерного зору: Розділ 5. Розпізнавання номерних пластин з використанням SVM та нейронних мереж
| Английский оригинал | Перевод на украинский | |
|---|---|---|
Сожалеем, но текст оригинала доступен только зарегистрированным пользователям. |
У цьому розділі ми познайомимось з процесом створення застосунку автоматичного розпізнавання номерних пластин (ANPR). Існують різноманітні підходи та техніки, що підходять для певних ситуацій, наприклад, інфрачервоних камер, фіксованих позицій автомобілів, умов освітлення і так далі. Можна зробити так, аби застосунок ANPR розпізнавав номерні знаки на фотографіях, знятих за 2-3 метри відстані до машини, у звичайних умовах освітлення, з непаралельно розміщеною землею та мінімальними викривленнями перспективи на пластині. Atronax 27.02.21 в 08:55 |
|
|
Найважливішою метою розділу є пояснення сегментації зображення та виокремлення особливих точок, основи розпізнавання шаблонів, а також два важливі алгоритми, метод опорних векторів та штучні нейронні мережі. Далі покриємо такі теми: Atronax 27.02.21 в 09:07 |
||
|
Автоматичне розпізнавання номерних пластин (ANPR), також відоме як визначення дозвільних знаків (ALPR), ідентифікація транспорту (AVI) чи пошук автомобільних пластин (CPR), - це спосіб спостереження, в основі якого лежить оптичне розпізнавання символів (OCR) та інші методи, наприклад сегментація та виявлення, метою яких є зчитування пластин реєстрації транспорту. Atronax 27.02.21 в 09:22 |
||
|
Найкращі результати від застосування системи ANPR можна отримати для інфрачервоної камери, адже кроки сегментування, необхідні для виявлення та розпізнавання символів, у цьому випадку прямі та мінімізують похибки. Так відбувається завдяки законам поширення світла, основний серед яких вказує на рівність кута падіння та відбиття; таке просте відображення можна побачити на гладкій поверхні, подібній до плоского дзеркала. Відбиття світла від грубих поверхонь, таких як папір, формує інший тип, відомий як дифузне чи розсіяне відображення. Більш номерних пластин мають особливу характеристику з назвою ретрорефлектор - поверхня пластини зроблена із матеріалу, покритого тисячами крихітних напівсфер, що змушують світло відбиватися у напрямі джерела, як показано далі: Atronax 27.02.21 в 09:57 |
||
|
Що ж до камери з фільтром, пов'язаним зі вбудованим проєктором інфрачервоного світла, то в цьому випадку отримаємо досить високоякісне зображення, яке можна сегментувати та поступово знайти потрібні об'єкти, а також виконати не залежний від умов освітлення процес розпізнавання, як показано на наступному малюнку: Atronax 27.02.21 в 10:05 |
||
|
У цьому розділі ми не використовуємо інфрачервоні фотографії, винятково звичайні. Робимо це для того, щоб отримати не найкращі результати, а вищий рівень виявлення похибок розпізнавання та хибних появ, на відміну від результатів застосування інфрачервоної камери; однак, послідовність кроків для підходів однакова. Atronax 27.02.21 в 10:31 |
||
|
Кожна країна має власні розміри номерних пластин та специфікації; щоб здобути кращі результати та знизити рівень похибок, варто розумітися на цьому. Алгоритми даного розділу мають пояснити основи ANPR та специфікації для номерних пластин Іспанії, але результати викладок можна поширити на будь-яку іншу країну. Atronax 27.02.21 в 10:41 |
||
|
Далі працюватимемо з дозвільними пластинами Іспанії. У цій країні існує три різні розміри та форми номерних знаків; розглянемо найпоширеніші (великі), з розмірами 520x110 мм. Дві групи символів розділені вільним простором довжиною 41 мм, а між собою вони розміщені на відстані 14 мм. Перша частина включає 4 числа, а друга - три літери за винятком голосних A, E, I, O, U, а також Ñ і Q; усі символи мають розміри 45x77 мм. Atronax 27.02.21 в 11:19 |
||
|
Ці дані важливі для процесу сегментації символів, адже ми маємо змогу перевірити символ разом із пустим простором, щоб впевнитися у тому, що ми знайшли саме символ, а не інший сегмент зображення. Далі зображено подібну пластину: Atronax 27.02.21 в 11:40 |
||
|
Алгоритм ANPR Atronax 27.02.21 в 11:40 |
||
|
До пояснення коду ANPR маємо визначити головні кроки та завдання алгоритму. Процес складається з двох головних кроків: пошуку та розпізнавання. Метою першого є виявлення положення пластини на всьому кадрі камери. Коли її знайдено, відповідний сегмент передається на другий крок (розпізнавання), який застосовує алгоритм OCR для визначення літер та цифр на пластині. Atronax 27.02.21 в 11:51 |
||
|
На наступному малюнку бачимо два головні кроки алгоритму, виявлення та розпізнавання номерного знака. Після виконання цих кроків програма зображає виявлені символи пластини на поверхні кадрів. Ці алгоритми можуть повернути неякісні або взагалі жодних результатів. Atronax 27.02.21 в 11:54 |
||
|
На кожному етапі з попереднього малюнка визначаємо три додаткові кроки, які зазвичай використовуються в алгоритмах розпізнавання шаблона: Atronax 27.02.21 в 12:30 |
||
|
Далі зображено відповідні етапи розпізнавання шаблона: Atronax 27.02.21 в 12:36 |
||
|
Разом з тим, ці питання можуть виявитися значно важливішими за програму, адже якщо ми не натренуємо систему розпізнавання шаблона коректно, вона може не справитися із задачею; до того ж, різні шаблони потребують різних способів тренування та оцінки. Щоб досягнути кращих результатів, маємо протестувати наявну систему в інших середовищах та за відмінних умов, з інакшими наборами особливих точок. Іноді дві задачі об'єднуються в одну, адже ключові точки можуть продукувати різні результати, як побачимо на етапі оцінки. Atronax 27.02.21 в 12:57 |
||
|
Виявлення пластини Atronax 27.02.21 в 13:00 |
||
|
На цьому етапі маємо знайти всі пластини на поточному кадрі. Щоб виконати завдання, виділимо два кроки: сегментацію та класифікацію сегментів. Етап пошуку особливих точок не пояснений, адже ми використовуємо фрагмент зображення як відповідний вектор. Atronax 27.02.21 в 13:03 |
||
|
На першому етапі (сегментація) застосуємо різні фільтри, морфологічні операції, алгоритми пошуку контурів та перевірки, щоб виокремити ті частини зображення, які можуть включати пластину. Atronax 27.02.21 в 13:11 |
||
|
Далі зображені всі процеси, які використовуються для розпізнавання пластин: Atronax 27.02.21 в 13:14 |
||
|
Сегментація Atronax 27.02.21 в 13:14 |
||
|
Сегментація - це процес поділу зображення на декілька сегментів, призначений для спрощення аналізу та виокремлення особливих точок. Atronax 27.02.21 в 13:22 |
||
|
До пошуку вертикальних меж маємо конвертувати кольорове зображення у відтінки сірого, бо колір не допоможе вирішити цю задачу, та видаляємо можливий шум, згенерований камерою. З цією метою застосуємо розмиття Гауса розмірності 5х5. Інакше отримаємо безліч вертикальних меж, які завадять розпізнаванню. Atronax 27.02.21 в 13:24 |
||
|
Далі використаємо фільтр Собеля та вирахуємо першу похідну по горизонталі. Це математична функція, яка дозволить знайти вертикальні межі на зображенні. Оголошення відповідної функції в бібліотеці OpenCV має такий вигляд: Atronax 27.02.21 в 13:26 |
||
|
void Sobel(InputArray src, OutputArray dst, int ddepth, int xorder, Atronax 27.02.21 в 13:27 |
||
|
У цьому випадку ddepth відповідає глибині зображення, xorder - це порядок похідної по x, yorder - порядок похідної по y, ksize - розмір ядра, що рівний 1, 3, 5 або 7, scale - опціональний множник для знайдених значень, delta - опціональне значення, що додається до результату, borderType - метод інтерполяції пікселів. Atronax 27.02.21 в 13:34 |
||
|
У нашому випадку використаємо такі значення: xorder = 1, yorder = 0, ksize = 3. Atronax 27.02.21 в 13:37 |
||
|
Після застосування фільтра Собеля, активуємо поріг зі значенням, визначеним за методом Отсу, щоб в результаті здобути необхідне бінарне зображення. Алгоритм для вхідного 8-бітного кадру автоматично визначає оптимальне значення порогу: Atronax 27.02.21 в 13:39 |
||
|
//зображення із застосованим порогом Atronax 27.02.21 в 13:44 |
||
|
Підказка Atronax 27.02.21 в 13:50 |
||
|
Застосувавши морфологічну операцію закриття, ми видалимо незаповнений простір між вертикальними межами та об'єднаємо фрагменти з великою кількістю вертикальних ліній. В результаті отримаємо сегменти зображення з можливими пластинами. Atronax 27.02.21 в 13:56 |
||
|
Спершу опишемо структурний елемент, необхідний для використанння морфологічної операції. Скористаємось функцією getStructuringElement, щоб визначити прямокутний фрагмент з розмірами 17x3 пікселів; в інших випадках це значення може відрізнятися: Atronax 27.02.21 в 14:00 |
||
|
Та використаємо його для морфологічної операції закриття, шляхом виклику фукнції morphologyEx: Atronax 27.02.21 в 14:02 |
||
|
В результаті застосування цих функцій отримаємо частини зображення з можливими пластинами; більшість з них не матимуть номерних знаків. Ці фрагменти можна розбити на дві групи шляхом аналізу поєднаних компонентів або за рахунок функції findContours. Остання застосовує різні методи та значення, щоб виокремлювати контури бінарного зображення. Ми маємо лише отримати зовнішні, з відношеннями ієрархії, та будь-які результати апроксимації полігонів: Atronax 27.02.21 в 14:14 |
||
|
// Знаходимо контури можливих пластин Atronax 27.02.21 в 14:16 |
||
|
Для кожного контура вирахуємо обмежувальний прямокутник мінімальної площі. Для цього бібліотека OpenCV постачає функцію minAreaRect. Вона знаходить об'єкт RotatedRect, що описує прямокутник з можливістю повороту. Потім, скориставшись ітератором для кожного вектора контура, проаналізуємо утворені фігури та зробимо попередні перевірки, перш ніж класифікувати фрагмент: Atronax 27.02.21 в 14:24 |
||
|
//Починаємо ітерацію над кожним знайденим контуром Atronax 27.02.21 в 14:26 |
||
|
Далі підтверджуємо коректність знайдених зображень залежно від площі та відношення сторін. Вважаємо, що фрагмент відповідає пластині, якщо значення відношення близьке до 520/110 = 4.727272 (ширина поділена на висоту) з похибкою, що складає 40 відсотків, та площею прямокутника, що відповідає висоті від 15 до 125 пікселів. ЦІ параметри залежать від розмірів зображення та позиції камери: Atronax 27.02.21 в 14:34 |
||
|
bool DetectRegions::verifySizes(RotatedRect candidate ){ Atronax 27.02.21 в 14:37 |
||
|
Можна вдосконалити алгоритм, скориставшись властивістю білого фону пластини. Усі вони мають однаковий колір фону, тому можна використати заповнення кольором, щоб отримати більш точний обмежувальний прямокутник. Atronax 27.02.21 в 14:46 |
||
|
Ми бажаємо виділити білий фрагмент, для цього потрібно, щоб серед декількох вихідних точок був як мінімум один піксель потрібного кольору. Щоб сформувати зображення маски для зберігання найближчого регіону для виокремлення, скористаємося функцією floodFill: Atronax 27.02.21 в 14:51 |
||
|
for(int i=0; i< rects.size(); i++){ Atronax 27.02.21 в 14:54 |
||
|
//налаштовуємо параметри floodfill та інші змінні Atronax 27.02.21 в 14:55 |
||
|
Починаючи з вихідної точки, функція floodFill заповнює об'єднані частини зображення певним кольором, зберігає результат у вигляді маски, а також встановлює нижні й верхні межі різниці між яскравістю / кольором пікселя для заповнення та його сусідами чи вихідною точкою: Atronax 27.02.21 в 15:01 |
||
|
int floodFill(InputOutputArray image, InputOutputArray mask, Point Atronax 27.02.21 в 15:03 |
||
|
Параметр newVal визначає новий колір, яким ми бажаємо заповнити визначені фрагменти зображення. Значення loDiff та upDiff позначають максимальні нижні та верхні межі різниці між яскравістю / кольором пікселя для заповнення та його сусідами чи вихідною точкоою. Atronax 27.02.21 в 15:06 |
||
|
Молодші біти - зберігають значення спорідненості, 4 (за замовчуванням) або 8, використувається функцією. Спорідненість визначає, які сусіди пікселя враховані. Atronax 27.02.21 в 15:10 |
||
|
Отримавши маску відсічення, на основі маски знайдемо прямокутник мінімальної площі та перевіримо коректність розмірів. Для кожного з них шукаємо положення білого пікселя та використовуємо функцію minAreaRect, щоб виокремити найближчий потрібний фрагмент: Atronax 27.02.21 в 15:17 |
||
|
//Перевіряємо нову маску заповнення на коректність. Atronax 27.02.21 в 15:20 |
||
|
Завершивши процес сегментації та здобувши важливі частини зображення, можна виокремити кожен виявлений фрагмент, анулювати можливі повороти, знайти необхідні прямокутники, змінити їх розміри та вирівняти значення світла на фрагментах. Atronax 27.02.21 в 15:27 |
||
|
Для початку маємо згенерувати матрицю перетворень за допомогою функції getRotationMatrix2D, щоб видалити можливі повороти. Особливу увагу слід приділити висоті, адже клас RotatedRect здатний повертати аналогічні прямокутники, але з поворотом 90 градусів. Варто перевірити відношення сторін. Якщо його значення менше одиниці, здійснюємо поворот: Atronax 27.02.21 в 15:33 |
