- Передумови
- Етапи розпізнавання номерних знаків за допомогою Raspberry Pi
- 1. Виявлення номерного знака
- 2. Сегментація персонажа
- 3. Розпізнавання символів
- Випадки помилок у розпізнаванні номерної таблички
- Інші успішні приклади
Безпека завжди була головною проблемою людства. Сьогодні у нас є камери відеоспостереження в школах, лікарнях та будь-якому іншому громадському місці, щоб ми почувались захищеними. Згідно з опитуванням HIS, підраховано, що в 2014 році було встановлено і функціонувало близько 245 мільйонів камер безпеки, що все одно, що мати одну камеру безпеки на кожних 30 людей на цій планеті. З розвитком технологій, особливо в обробці зображень та машинному навчанні, можна зробити ці камери розумнішими, навчивши їх обробляти інформацію із відеопотоку.
Відеопотік з цих камер може бути використаний для розпізнавання обличчя, аналізу малюнків, аналізу емоцій та багато іншого, що дійсно могло б наблизити його до чогось на зразок "Божого ока", показаного у фільмі FF7. Насправді компанії з нагляду, такі як Hikvision та багато інших, вже почали впроваджувати ці функції у свої продукти. Раніше ми використовували обробку зображень MATLAB для зчитування номерного знака, сьогодні в цій статті ми дізнаємося, як розпізнавати та зчитувати номерний знак номерного знаку з автомобілів за допомогою Raspberry Pi та OpenCV. Ми використаємо кілька випадкових зображень автомобіля від Google і напишемо програму для розпізнавання номерного знака за допомогою виявлення контуру OpenCV, а потім зчитуємо номер із таблички за допомогою Tesseract OCR. Звучить цікаво правильно !, так що давайте почнемо.
Передумови
Як вже говорилося раніше, ми будемо використовувати бібліотеку OpenCV для виявлення та розпізнавання облич. Тож обов’язково встановіть бібліотеку OpenCV на Raspberry Pi, перш ніж продовжувати цей підручник. Також увімкніть ваш Pi за допомогою адаптера 2A та підключіть його до монітора дисплея для полегшення налагодження.
У цьому підручнику не буде пояснено, як саме працює OpenCV, якщо ви зацікавлені в навчанні обробці зображень, ознайомтесь із цими основами OpenCV та розширеними підручниками з обробки зображень. Ви також можете дізнатись про контури, виявлення крапок тощо у цьому посібнику з сегментації зображень за допомогою OpenCV. Ми зробимо щось подібне до цього, щоб виявити номерний знак автомобіля на зображенні.
Етапи розпізнавання номерних знаків за допомогою Raspberry Pi
Розпізнавання номерного знаку або, коротше, LPR, передбачає три основні етапи. Дії наступні
1. Виявлення номерного знака : Першим кроком є виявлення номерного знака з автомобіля. Ми будемо використовувати опцію контуру в OpenCV для виявлення прямокутних об’єктів для пошуку номерного знака. Точність можна покращити, якщо ми знаємо точний розмір, колір та приблизне розташування номерного знака. Зазвичай алгоритм виявлення тренується на основі положення камери та типу номерного знака, що використовується у цій конкретній країні. Це стає складніше, якщо на зображенні навіть немає автомобіля, у цьому випадку ми зробимо додатковий крок для виявлення автомобіля, а потім номерного знаку.
2. Сегментація символів: Щойно ми виявили номерний знак, ми повинні його вирізати та зберегти як нове зображення. Знову це легко зробити за допомогою OpenCV.
3. Розпізнавання символів: Тепер на новому зображенні, яке ми отримали на попередньому кроці, обов’язково будуть записані деякі символи (цифри / алфавіти). Отже, ми можемо виконати на ньому OCR (оптичне розпізнавання символів) для виявлення числа. Ми вже пояснювали оптичне розпізнавання символів (OCR) за допомогою Raspberry Pi.
1. Виявлення номерного знака
Першим кроком у цій програмі зчитування номерних знаків Raspberry Pi є виявлення номерного знака. Давайте візьмемо зразок зображення автомобіля і почнемо з виявлення номерного знака на цьому автомобілі. Потім ми будемо використовувати те саме зображення для сегментації символів та розпізнавання символів. Якщо ви хочете перейти прямо до коду без пояснень, ви можете прокрутити вниз до кінця цієї сторінки, де надається повний код. Тестове зображення, яке я використовую для цього підручника, показано нижче.
Крок 1: Змініть розмір зображення до необхідного розміру, а потім відшліфуйте його в градаціях сірого. Код для цього наведено нижче
img = cv2.resize (img, (620,480)) сірий = cv2.cvtColor (img, cv2.COLOR_BGR2GREY) # перетворити на шкалу сірого
Змінюючи розмір, ми допомагаємо уникнути будь-яких проблем із зображеннями більшої роздільної здатності, переконайтесь, що номерна табличка все ще залишається у кадрі після зміни розміру. Масштабування сірого є загальним для всіх етапів обробки зображень. Це прискорює інші наступні процеси, тому нам більше не доведеться мати справу з кольоровими деталями під час обробки зображення. Коли цей крок буде зроблено, зображення буде трансформуватися приблизно так
Крок 2: Кожне зображення матиме корисну та марну інформацію, у цьому випадку для нас корисним є лише номерний знак, а решта для нашої програми майже марні. Цю марну інформацію називають шумом. Зазвичай використання двостороннього фільтра (Розмиття) видаляє непотрібні деталі із зображення. Код того ж є
сірий = cv2.bilateralFilter (сірий, 11, 17, 17)
Синтаксис - це призначення_ізображення = cv2.bilateralFilter (джерело_зображення, діаметр пікселя, sigmaColor, sigmaSpace). Ви можете збільшити колір сигми та простір сигми з 17 до вищих значень, щоб розмити більше довідкової інформації, але будьте обережні, щоб корисна частина не розмилася. Вихідне зображення показано нижче, оскільки ви можете бачити, що деталі фону (дерево та будівля) на цьому зображенні розмиті. Таким чином ми можемо уникнути зосередження уваги програми на цих регіонах пізніше.
Крок 3: Наступний крок цікавий, де ми виконуємо виявлення країв. Є багато способів зробити це, найпростіший і популярний спосіб - це використання методу canny edge з OpenCV. Рядок, щоб зробити те саме, показано нижче
edged = cv2.Canny (сірий, 30, 200) # Виконати виявлення краю
Синтаксис буде призначення_ізображення = cv2.Canny (джерело_зображення, порогове значення 1, порогове значення 2). Порогова величина 1 і Порогове значення 2 є мінімальним і максимальним пороговими значеннями. Відображатимуться лише краї, що мають градієнт інтенсивності, що перевищує мінімальне порогове значення і менше максимального порогового значення. Отримане зображення показано нижче
Крок 4: Тепер ми можемо почати шукати контури на нашому зображенні, ми вже дізналися про те, як знаходити контури за допомогою OpenCV у нашому попередньому уроці, тому ми просто продовжуємо аналогічно.
nts = cv2.findContours (edged.copy (), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours (cnts) cnts = sorted (cnts, key = cv2.contourArea, reverse = True) screenCnt = None
Після виявлення лічильників ми сортуємо їх від великого до малого і враховуємо лише перші 10 результатів, ігноруючи інші. На нашому зображенні лічильником може бути все, що має закриту поверхню, але з усіх отриманих результатів номерний знак також буде там, оскільки це також закрита поверхня.
Щоб відфільтрувати зображення номерного знака серед отриманих результатів, ми прокрутимо всі результати та перевіримо, який має контур форми прямокутника з чотирма сторонами та закритою фігурою. Оскільки номерний знак однозначно був би чотиригранною фігурою прямокутника.
# петля над нашими контурами для c в cnts: # приблизний контур peri = cv2.arcLength (c, True) approx = cv2.approxPolyDP (c, 0,018 * peri, True) # якщо наш апроксимований контур має чотири точки, тоді # ми можна припустити, що ми знайшли наш екран, якщо len (приблизно) == 4: screenCnt = приблизно перерва
Значення 0,018 - експериментальне значення; Ви можете пограти навколо, щоб перевірити, що найкраще вам підходить. Або підніміть його на наступний рівень, використовуючи машинне навчання для навчання на основі зображень автомобіля, а потім використовуйте правильне значення там. Після того, як ми знайшли правильний лічильник, ми зберігаємо його у змінну, яка називається screenCnt, а потім намалюємо прямокутник навколо нього, щоб переконатися, що ми правильно виявили номерний знак.
Крок 5: Тепер, коли ми знаємо, де знаходиться номерний знак, решта інформації для нас майже марна. Тож ми можемо продовжувати маскування всієї картинки, за винятком місця, де знаходиться номерний знак. Код, щоб зробити те ж саме, показано нижче
# Маскування частини, крім номерної таблички mask = np.zeros (grey.shape, np.uint8) new_image = cv2.drawContours (mask,, 0,255, -1,) new_image = cv2.bitwise_and (img, img, mask = маска)
Замасковане нове зображення з’явиться приблизно так, як показано нижче
2. Сегментація персонажа
Наступним кроком у розпізнаванні номерних знаків Raspberry Pi є сегментація номерного знака поза зображенням, обрізавши його та зберігаючи як нове зображення. Потім ми можемо використовувати це зображення для виявлення персонажа в ньому. Код для обрізання зображення roi (регіону, що цікавить) з основного зображення показаний нижче
# Тепер обрізати (x, y) = np. Де (маска == 255) (topx, topy) = (np.min (x), np.min (y)) (bottomx, bottomy) = (np.max (x), np.max (y)) Обрізане = сіре
Отримане зображення показано нижче. Зазвичай доданий до обрізання зображення, ми також можемо виділити його сірим кольором і, якщо потрібно, окантувати. Це робиться для покращення розпізнавання символів на наступному кроці. Однак я виявив, що це чудово працює навіть з оригінальним зображенням.
3. Розпізнавання символів
Заключним кроком цього розпізнавання номерних знаків Raspberry Pi є фактичне зчитування інформації про номерну табличку із сегментованого зображення. Ми використовуватимемо пакет pytesseract для зчитування символів із зображення, як це було зроблено в попередньому уроці. Код для цього наведено нижче
# Прочитайте номерну табличку text = pytesseract.image_to_string (Обрізано, config = '- psm 11') print ("Виявлений номер:", текст)
Ми вже пояснювали, як налаштувати движок Tesseract, тому тут знову, якщо потрібно, ми можемо налаштувати OCR Tesseract для отримання кращих результатів, якщо потрібно. Потім виявлений символ друкується на консолі. При компіляції результат відображається, як показано нижче
Як бачите, на оригінальному зображенні було вказано номер “HR 25 BR9044”, і наша програма виявила, що на екрані надруковано таке саме значення.
Випадки помилок у розпізнаванні номерної таблички
Повний файл проекту, який розпізнавання номерного знаку Raspberry Pi можна завантажити звідси, він містить програму та тестові зображення, які ми використовували для перевірки нашої програми. Не кажучи про це, слід пам’ятати, що результати цього методу будуть неточними . Точність залежить від чіткості зображення, орієнтації, експозиції світла тощо. Щоб отримати кращі результати, ви можете спробувати впровадити алгоритми машинного навчання разом із цим.
Щоб отримати уявлення, давайте розглянемо ще один приклад, коли машина не спрямована безпосередньо на камеру.
Як бачите, наша програма змогла правильно виявити номерний знак та обрізати його. Але бібліотека Tesseract не змогла правильно розпізнати символи. Замість фактичного “TS 08 UE 3396” OCR визнав його “1508 ye 3396”. Такі проблеми можна виправити, використовуючи зображення з кращою орієнтацією, або налаштувавши движок Tesseract .
Інший найгірший варіант - це те, коли контур не може правильно розпізнати номерний знак. На зображенні нижче занадто багато фонової інформації та погане освітлення, що програма навіть не змогла ідентифікувати номерний знак за номером. У цьому випадку нам доведеться знову передати машинне навчання або поліпшити якість зображення.
Інші успішні приклади
У більшості випадків якість зображення та орієнтація правильні, програма змогла ідентифікувати номерний знак та прочитати з нього номер. Наведені нижче знімки показують лише кілька успішних отриманих результатів. Знову ж усі тестові зображення та код, використані тут, будуть доступні у ZIP-файлі, наданому тут.
Сподіваюся, ви зрозуміли автоматичне розпізнавання номерних знаків за допомогою Raspberry Pi і насолоджувались створенням чогось крутого самостійно. Як ви думаєте, що ще можна зробити з OpenCV і Tesseract ?, Повідомте мені про свої думки в розділі коментарів. Якщо у вас виникли запитання щодо цієї статті, залиште їх у розділі коментарів нижче або використовуйте форуми для інших технічних запитань.