- Предварительные условия
- Этапы распознавания номерных знаков с помощью Raspberry Pi
- 1. Обнаружение номерных знаков
- 2. Сегментация персонажей
- 3. Распознавание персонажей
- Случаи отказа в распознавании номерных знаков
- Другие успешные примеры
Безопасность всегда была главной заботой человечества. Сегодня у нас есть камеры видеонаблюдения в школах, больницах и других общественных местах, чтобы мы чувствовали себя в безопасности. Согласно опросу, проведенному HIS, в 2014 году было установлено и функционировало около 245 миллионов камер видеонаблюдения, то есть на каждые 30 человек на этой планете приходится одна камера видеонаблюдения. С развитием технологий, особенно в области обработки изображений и машинного обучения, можно сделать эти камеры умнее, обучив их обрабатывать информацию из видеопотока.
Видеопоток с этих камер может использоваться для распознавания лиц, анализа образов, анализа эмоций и многого другого, что действительно приближает его к чему-то вроде «Глаза Бога», показанного в фильме FF7. Фактически, компании по видеонаблюдению, такие как Hikvision и многие другие, уже начали внедрять эти функции в свои продукты. Ранее мы использовали обработку изображений MATLAB для чтения номерного знака, сегодня в этой статье мы узнаем, как распознать и прочитать номерной знак с автомобилей с помощью Raspberry Pi и OpenCV. Мы воспользуемся случайными изображениями автомобилей из Google и напишем программу для распознавания номерного знака с помощью OpenCV Contour Detection, а затем прочитаем номер с номера с помощью Tesseract OCR. Звучит интересно! Итак, приступим.
Предварительные условия
Как было сказано ранее, мы будем использовать библиотеку OpenCV для обнаружения и распознавания лиц. Поэтому не забудьте установить библиотеку OpenCV на Raspberry Pi, прежде чем переходить к этому руководству. Также подключите Pi к адаптеру 2А и подключите его к монитору для облегчения отладки.
В этом руководстве не объясняется, как именно работает OpenCV. Если вы заинтересованы в изучении обработки изображений, ознакомьтесь с основами OpenCV и учебниками по расширенной обработке изображений. Вы также можете узнать о контурах, обнаружении BLOB-объектов и т. Д. В этом руководстве по сегментации изображений с использованием OpenCV. Мы сделаем что-то подобное, чтобы обнаружить номерной знак автомобиля по изображению.
Этапы распознавания номерных знаков с помощью Raspberry Pi
Распознавание номерных знаков или сокращенно LPR включает три основных этапа. Шаги следующие
1. Обнаружение номерного знака : Первый шаг - обнаружить номерной знак автомобиля. Мы будем использовать опцию контура в OpenCV для обнаружения прямоугольных объектов, чтобы найти номерной знак. Точность можно повысить, зная точный размер, цвет и примерное расположение номерного знака. Обычно алгоритм обнаружения обучается на основе положения камеры и типа номерного знака, используемого в данной конкретной стране. Это становится сложнее, если на изображении даже нет автомобиля, в этом случае мы сделаем дополнительный шаг, чтобы обнаружить автомобиль, а затем номерной знак.
2. Сегментация персонажей: как только мы обнаружили номерной знак, мы должны обрезать его и сохранить как новое изображение. Опять же, это можно легко сделать с помощью OpenCV.
3. Распознавание символов. Теперь на новом изображении, которое мы получили на предыдущем шаге, обязательно есть символы (числа / алфавиты), написанные на нем. Итак, мы можем выполнить на нем OCR (оптическое распознавание символов), чтобы определить число. Мы уже объясняли оптическое распознавание символов (OCR) с помощью Raspberry Pi.
1. Обнаружение номерных знаков
Первым шагом в этом считывателе номерных знаков Raspberry Pi является обнаружение номерного знака. Давайте возьмем образец изображения автомобиля и начнем с определения номерного знака на нем. Затем мы будем использовать то же изображение для сегментации и распознавания символов. Если вы хотите сразу перейти к коду без объяснения причин, вы можете прокрутить вниз до конца этой страницы, где предоставляется полный код. Тестовое изображение, которое я использую для этого урока, показано ниже.
Шаг 1. Измените размер изображения до необходимого размера, а затем отрегулируйте его в оттенках серого. Код для того же приведен ниже
img = cv2.resize (img, (620,480)) gray = cv2.cvtColor (img, cv2.COLOR_BGR2GRAY) # преобразовать в шкалу серого
Изменение размера помогает избежать проблем с изображениями с большим разрешением. Убедитесь, что номерной знак остается в кадре после изменения размера. Шкала серого используется на всех этапах обработки изображения. Это ускоряет другие последующие процессы, так как нам больше не нужно иметь дело с деталями цвета при обработке изображения. Изображение будет преобразовано примерно так, когда этот шаг будет выполнен
Шаг 2: Каждое изображение будет содержать полезную и бесполезную информацию, в этом случае для нас полезной информацией является только номерной знак, все остальное практически бесполезно для нашей программы. Эта бесполезная информация называется шумом. Обычно использование двустороннего фильтра (размытие) удаляет нежелательные детали с изображения. Код для того же:
серый = cv2.bilateralFilter (серый, 11, 17, 17)
Синтаксис: destination_image = cv2.bilateralFilter (source_image, диаметр пикселя, sigmaColor, sigmaSpace). Вы можете увеличить цвет сигмы и пространство сигмы с 17 до более высоких значений, чтобы размыть больше фоновой информации, но будьте осторожны, чтобы полезная часть не размылась. Выходное изображение показано ниже, поскольку вы можете видеть, что детали фона (дерево и здание) размыты на этом изображении. Таким образом, мы сможем избежать сосредоточения программы на этих регионах позже.
Шаг 3: Следующий шаг интересен, где мы выполняем обнаружение края. Есть много способов сделать это, самый простой и популярный - использовать метод canny edge из OpenCV. Строка, делающая то же самое, показана ниже.
edged = cv2.Canny (gray, 30, 200) # Выполнить определение края
Синтаксис будет следующим: destination_image = cv2.Canny (source_image, thresholdValue 1, thresholdValue 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) приблизительно = cv2.approxPolyDP (c, 0.018 * peri, True) # если наш аппроксимированный контур имеет четыре точки, то # мы можно предположить, что мы нашли наш экран, если len (приблизительно) == 4: screenCnt = приблизительно перерыв
Значение 0,018 - экспериментальное значение; вы можете поэкспериментировать, чтобы проверить, что лучше всего подходит для вас. Или перейдите на следующий уровень, используя машинное обучение для обучения на основе изображений автомобилей, а затем используйте там правильное значение. Найдя правильный счетчик, мы сохраняем его в переменной screenCnt, а затем обводим его прямоугольником, чтобы убедиться, что номерной знак был обнаружен правильно.
Шаг 5: Теперь, когда мы знаем, где находится номерной знак, оставшаяся информация для нас практически бесполезна. Таким образом, мы можем приступить к маскировке всего изображения, кроме места, где находится номерной знак. Код, который делает то же самое, показан ниже.
# Маскирование части, отличной от номерного знака mask = np.zeros (gray.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.where (mask == 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 (Cropped, config = '- psm 11') print ("Обнаруженный номер:", текст)
Мы уже объяснили, как настроить механизм Tesseract, поэтому и здесь, если необходимо, мы можем настроить Tesseract OCR для получения лучших результатов, если это необходимо. Обнаруженный символ затем печатается на консоли. После компиляции результат показан ниже.
Как вы можете видеть, исходное изображение имело номер «HR 25 BR9044», и наша программа обнаружила, что оно напечатало то же значение на экране.
Случаи отказа в распознавании номерных знаков
Полный файл проекта « Распознавание номерных знаков Raspberry Pi» можно скачать отсюда, он содержит программу и тестовые изображения, которые мы использовали для проверки нашей программы. Не говоря уже о том, что следует помнить, что результаты этого метода не будут точными . Точность зависит от четкости изображения, ориентации, освещенности и т. Д. Чтобы получить лучшие результаты, вы можете попробовать реализовать алгоритмы машинного обучения вместе с этим.
Чтобы получить представление, давайте рассмотрим другой пример, когда автомобиль не смотрит прямо в камеру.
Как видите, наша программа смогла правильно определить номерной знак и обрезать его. Но библиотека Tesseract не смогла правильно распознать персонажей. Вместо фактического «TS 08 UE 3396» OCR распознало это как «1508 ye 3396». Подобные проблемы можно исправить либо с помощью изображений с улучшенной ориентацией, либо путем настройки движка Tesseract .
Другой наихудший сценарий - это когда контур не может правильно определить номерной знак. На изображении ниже слишком много фоновой информации и плохое освещение, поэтому программе даже не удалось определить номерной знак по номеру. В этом случае мы должны снова обратиться к машинному обучению или улучшить качество изображения.
Другие успешные примеры
В большинстве случаев качество изображения и ориентация были правильными, программа могла определить номерной знак и прочитать номер с него. На приведенных ниже снимках показаны некоторые из полученных успешных результатов. Опять же, все тестовые изображения и код, использованные здесь, будут доступны в ZIP-файле, предоставленном здесь.
Надеюсь, вы поняли, что такое автоматическое распознавание номерных знаков с помощью Raspberry Pi, и вам понравилось создавать что-то классное самостоятельно. Как вы думаете, что еще можно сделать с OpenCV и Tesseract ?, Дайте мне знать свои мысли в разделе комментариев. Если у вас есть какие-либо вопросы по этой статье, пожалуйста, оставьте их в разделе комментариев ниже или используйте форумы для других технических вопросов.