Opencv python распознавание номеров автомобилей
Распознавание номеров. Практическое пособие. Часть 1
Все начиналось банально — моя компания уже год платила ежемесячно плату за сервис, который умел находить регион с номерными знаками на фото. Эта функция применяется для автоматической зарисовки номера у некоторых клиентов.
И в один прекрасный день МВД Украины открыло доступ к реестру транспортных средств. Теперь по номерному знаку стало возможным проверять некоторую информацию про автомобиль (марку, модель, год выпуска, цвет и т.д. )! Скучная рутина линейного программирования померкла перед новой свехзадачей — считывать номера по всей базе фото и валидировать эти данные с теми, что указывал пользователь. Сами знаете как это бывает «глаза загорелись» — вызов принят, все остальные задачи на время стали скучны и монотонны… Мы принялись за работу и получили неплохие результаты, чем, собственно и решили поделиться с сообществом.
Для справки: на сайт AUTO.RIA.com, в день добавляется около 100 000 фото.
Кто еще распознает
Год назад я изучил этот рынок и оказалось, что работать с номерами стран exUSSR умеет не так уж много сервисов и ПО. Ниже представлен список компаний с которыми мы работали:
Automatic License Plate Recognition
Recognitor
Какие инструменты нужны для распознавания номеров
Нахождение объектов на изображении или в видео-потоке это задача из области компьютерного зрения, которая решается разными подходами, но чаще всего с помощью, так-называемых, сверточных нейронных сетей. Нам нужно найти не просто область на фото в которой встречается искомый объект, но и отделить все его точки от других объектов или фона. Эта разновидность задач называется «Instance Segmentation». На иллюстрации ниже визуализированы разные типы задач компьютерного зрения.
Я не буду сейчас писать много теории о том как работает сверточная сеть, этой информации достаточно в сети и докладов на youtube.
Из современных архитектур сверточных серей для задач сегментации часто используют: U-Net или Mask R-CNN. Мы выбрали Mask R-CNN.
Второй инструмент, который нам понадобится — это библиотека по распознаванию текстов, которая бы могла работать с разными языками и которую можно легко настраивать под специфику текстов, которые мы будем распознавать. Тут выбор не так уж велик, самой продвинутой является tesseract от Google.
Так же есть ряд менее «глобальных» инструментов, с помощью которых нам нужно будет нормализовать область с номерным знаком (привести его в такой вид, при котором распознавание текста будет возможным). Обычно для таких преобразований используют opencv.
Так же, можно будет попробовать определить страну и тип, к которой относится найденный номерной знак, чтоб в постобработке применить уточняющий шаблон, характерный для этой страны и этого типа номера. Например, украинский номерной знак, начиная с 2015 года оформлен в сине-желтом оформлении состоит из шаблона «две буквы черыре цифры две буквы».
Кроме того, имея статистику частоты «встречания» в номерных знаках того или иного сочетания букв или цифр можно улучшить качество постобработки в «спорных» ситуациях. «
Nomeroff Net
Все материалы для нашего проекта: размеченные датасеты и натренированные модели, мы выложили в открытый доступ с разрешения RIA.com под лицензией Creative Commons CC BY 4.0
Что нам понадобится
Для того, чтобы ускорить установку планируем создать dockerfile — ожидайте в ближайших апдейтах проекта.
Nomeroff Net «Hello world»
Давайте уже что-то попробуем распознать. Клонируем с github-а репозиторий с кодом. Качаем в папку models, натренированные модели для поиска и классификации номеров, немного подправим под себя переменные с расположением папок.
UPD: Этот код является устаревшим, он будет работать только в ветке 0.1.0, свежие примеры смотрите здесь:
Все, можно распознавать:
Онлайн демка
Набросали простенькую демку для тех кому не хочется все это ставить и запускать у себя :). Будьте снисходительны и терпеливы к скорости работы скрипта.
Если нужны примеры украинских номеров (для проверки работы алгоритмов коррекции), возьмите пример из этой папки.
Что дальше
Я понимаю, что тема очень нишевая и вряд ли вызовет большой интерес у широкого круга программистов, кроме того, код и модели еще достаточно «сыроваты» в плане качества распознавания, быстродействия, потребления памяти и пр. Но все же есть надежда, что найдутся энтузиасты, которым будет интересно натренировать модели под свои нужды, свою страну, которые помогут и подскажут, где есть проблемы и вместе с нами сделают проект не хуже, чем коммерческие аналоги.
Известные проблемы
Анонс
Если это будет кому-то интересно, во второй части собираемся рассказать о том как и чем размечать свой датасет и как тренировать свои модели, которые могут работать лучше для вашего контента (вашей страны, вашего размера фото). Также поговорим о том как создать свой классификатор, который, например, поможет определять не зарисован ли номер на фото.
Разработка библиотеки распознавания российских автомобильных номеров
В настоящее время в различных областях человеческой деятельности все шире применяются технологии компьютерного зрения. Например, распознавание изображений используется в автоматизированных системах контроля производственных процессов, при проверке электронных документов, в информационных и управляющих системах различного назначения. В данной работе рассматривается распознавание автомобильных номеров, которое актуально для автоматизации работы государственных органов безопасности дорожного движения, полиции, охранных организаций. Распознавание выполняется с помощью библиотеки OpenCV
Объект исследования: методы распознавания изображений.
Предмет исследования: процесс обнаружения и распознавания автомобильного номера на цифровых изображениях с использованием метода Виолы-Джонса
Цель: разработка библиотеки, реализующей автоматическое распознавание российских автомобильных номеров.
Задачи:
1. Поиск области автомобильного номера
1.1 Метод Виолы-Джонса
В настоящее время метод Виолы–Джонса является популярным методом для поиска объекта на изображении в силу своей высокой скорости и эффективности. В основу метода Виолы–Джонса положены: интегральное представление изображения по признакам Хаара, построение классификатора на основе алгоритма адаптивного бустинга и способ комбинирования классификаторов в каскадную структуру. Эти идеи позволяют осуществлять поиск объекта в режиме реального времени. Рассмотрим их более подробно.
Интегральное представление изображения – это матрица, одинаковая по размерам с исходным изображением. В каждом элементе матрицы хранится сумма интенсивностей всех пикселов, находящихся левее и выше данного элемента – правого нижнего угла прямоугольной области (0,0) до (x,y). Элементы матрицы L можно рассчитать по формуле:
Расчёт значений элементов матрицы проходит за время, пропорциональное числу пикселов в исходном изображении, поэтому интегральное изображение просчитывается за один проход.
Элементы матрицы рассчитываются по формуле:
С помощью интегрального представления изображения можно быстро рассчитать суммарную яркость произвольной прямоугольной области на изображении. Пример вычисления приведен в приложении «А».
На этапе обнаружения объекта в методе Виолы-Джонса используется окно определенного размера, которое движется по изображению. Для каждой области изображения, над которой проходит окно, рассчитывается признак Хаара, с помощью которого происходит поиск нужного объекта.
Признак-отображение, где Df —множество допустимых значений признака. Если заданы признаки f1,…, fn, то вектор признаков x=(f1(x),…,fn(x)) называется признаковым описанием объекта x. Признаковые описания допустимо сопоставлять с самими объектами. При этом множество X=Df1*…*Dfn называют признаковым пространством.
Признаки делятся на следующие типы в зависимости от множества Df:
Признак Хаара вычисляется по смежным прямоугольным областям. В стандартном методе Виолы–Джонса используются прямоугольные примитивы, изображенные на рисунке 1.
Вычисляемым значением F признака Хаара будет где X – сумма значений яркостей точек, закрываемых светлой частью примитива, Y –сумма значений яркостей точек, закрываемых темной частью. Для вычисления используется понятие интегрального изображения, рассмотренное выше, и признаки Хаара могут вычисляться быстро, за постоянное время. Использование признаков Хаара дает точечное значение перепада яркости по оси X и Y соответственно.
Поскольку признаки Хаара мало подходят для обучения или классификации, для описания объекта с достаточной точностью необходимо большее число признаков. Поэтому признаки Хаара поступают в каскадный классификатор, служащий для быстрого отбрасывания окон, где не найден требуемый объект, и выдачи результата «истина» или «ложь» относительно нахождения объекта.
Классификатор строится на основе алгоритма бустинга (от англ. boost–улучшение, усиление) для выбора наиболее подходящих признаков для искомого объекта на данной части изображения. В общем случае бустинг — это комплекс методов, способствующих повышению точности аналитических моделей. Эффективная модель, допускающая мало ошибок классификации, называется «сильной». «Слабая» же, напротив, не позволяет надежно разделять классы или давать точные предсказания, делает большое количество ошибок. Поэтому бустинг означает «усиление» «слабых» моделей и является процедурой последовательного построения композиции алгоритмов машинного обучения, когда каждый следующий алгоритм стремится компенсировать недостатки композиции всех предыдущих алгоритмов.
В результате работы алгоритма бустинга на каждой итерации формируется простой классификатор вида:
– направление знака неравенства, — значение порога,– вычисленное значение признака,– окно изображения размером 24×24 пикселов.
Полученный классификатор имеет минимальную ошибку по отношению к текущим значениям весов, задействованным в процедуре обучения для определения ошибки.
Поиск автомобильного номера на цифровом изображении
Для поиска объекта на цифровом изображении используется обученный классификатор, представленный в формате xml. Классификатор формируется на примитивах Хаара.
Рисунок 2 – Структура классификатора
где maxWeakCount – количество слабых классификаторов;
stageThereshold – максимальный порог яркости;
weakClassifiers – набор слабых классификаторов, на основе которых выносится решение о том, находится объект на изображении или нет;
internalNodes и leafValues – параметры конкретного слабого классификатора.
Первые два значения в internalNodes не используются, третье — номер признака в общей таблице признаков (она располагается в XML-файле под тегом features), четвертое — пороговое значение слабого классификатора. Если значение признака Хаара меньше порога слабого классификатора, выбирается первое значение leafValues, если больше — второе.
На рисунке 3 продемонстрированы результаты работы классификаторов первого каскада. Белые пятна обозначают предполагаемый участок для дальнейшего поиска.
На основе этого базиса строится каскад классификаторов, принимающих решение о том, распознан объект на изображении или нет. Наличие или отсутствие предмета в окне определяется разницей между значением признака и порогом, полученным в результате обучения.
На рисунке 3.1 продемонстрированы результаты поиска с использованием классификатора.
Рисунок 3 – Результат работы классификаторов первого каскада
Рисунок 3 – Результат работы классификаторов первого каскада
Рисунок 3 – Результат работы классификаторов первого каскада
Рисунок 3 – Результат работы классификаторов первого каскада
Рисунок 3.1 – Результат работы поиска автомобильного номера
Ознакомиться с процессом обучения каскада Хаара можно по ссылки на статью в моём личном блоге: https://kostyakulakov.ru/2015/07/04/opencv-обучение-каскада-хаара/ или в приложении «Б».
2. Подготовка к распознаванию автомобильного номера
2.1 Алгоритм нормализации угла наклона
После того как мы нашли автомобильный номер (Рисунок 3), нам нужно подготовить его к распознаванию, для этого мы должны нормализировать угол наклона автомобильного номера.
Рисунок 5 – результат работы алгоритма. Угол 1.4°
2.2 Алгоритм поиска нижней границы автомобильного номера
После того как мы нашли угол наклона автомобильного номера, нам нужно найти его границы. Поиск нижней границы автомобильного номера строится на анализе гистограммы яркости.
Рисунок 6 – принцип построения гистограммы
Для начала изображение обрабатывается с помощью определенного правила, которое задаёт условие разделение пикселей на чёрные и белые. Данная операция называется бинаризация изображения. После бинаризации мы считаем в каждой колонке кол-во чёрных пикселей и на основе полученной информации строим гистограмму изображения. Принцип построения гистограммы отображён на рисунке 6. Пример бинаризированного автомобильного номера и его гистограммы приведён на рисунке 7.
Рисунок 7 – бинаризация автомобильного номера и гистограмма
Из рисунка видно, что имеются резкие возрастания уровня гистограммы в начале и конце автомобильного номера. В алгоритме анализируются данные возрастания.
На их основе строится гипотеза о нижней границе автомобильного номера.
Полная блок-схема алгоритма поиска нижней границы приведена в приложении «Г».
2.3 Алгоритм поиска верхней границы автомобильного номера
Во время тестов опытным путём установлено, что гипотеза с использованием гистограммы яркости для поиска верхней границы, а/н [1] работает в 50% случаев, что не приемлемо для нашей системы. В связи с этим было решено обучить каскад Хаара на каждую букву и проанализировать верхние границы букв, тем самым мы сможем получить верхнюю границу автомобильного номера. Подробнее про процесс обучения каскада Хаара для поиска букв автомобильного номера можно ознакомиться в моём личном блоге: https://kostyakulakov.ru/2015/07/04/opencv-обучение-каскада-хаара или в приложении «Б». Пример работы алгоритма приведён на рисунке 8. Полная блок-схема алгоритма поиска верхней границы приведена в приложении «Д».
В некоторых случаях, алгоритм с использованием каскада Хаара может не дать результата, это характерно для изображений с очень низким разрешением. Для таких изображений мы применяем как альтернативный алгоритм поиск границы с использованием гистограммы яркости.
2.4 Алгоритм поиска боковых границ автомобильного номера
На данном этапе мы уже обрезали автомобильный номер по верхней и нижней границе, остаётся определить боковые границы автомобильного номера. В данном случае, мы будем применять метод построения гистограммы яркости, но у нас появляется проблема: цвет автомобиля. Если автомобиль белого цвета, то после бинаризации изображение по краям будет иметь белый цвет, а если автомобиль чёрного цвета, то края будут чёрные, а сам номер белым. Отсюда следует вывод, что нам следует использовать две гипотезы на каждый бок, одна для поиска границы на белой машине и вторая для поиска на чёрной границе. Выигрывает та гипотеза результатом исследования, которой является результат ближайший к центру автомобильного номера. Для улучшения качества поиска боковых границ автомобильного номера, перед построением гистограммы яркости мы проводим основные морфологические преобразования:
Пример бинаризации кадра белой и чёрной машины приведён на рисунке 9. Полная блок-схема алгоритма поиска боковых границ приведена в приложении «Е».
3. Сегментации автомобильного номера на символы
Результатом работы алгоритма поиска боковых границ автомобильного номера, является изображение номера, для которого применим алгоритма сегментации на символы. Пример полученного автомобильного номера после выполнения алгоритма поиска боковых границ приведён на рисунке 10.
Для поиска символов автомобильного номера мы используем стандартные методы библиотеки OpenCV. Вначале нам необходимо перевести изображение в чёрно-белый формат и бинаризировать его. После бинаризации мы обрабатываем изображения фильтром средних частот, чтобы убрать помеховую составляющую. Следующим действием будет процесс размытие изображения с использованием метода Гаусса. Размытие необходимо для сглаживания краёв символов как показали тесты, данное преобразование существенно увеличивает вероятность успешного поиска символа. В следующем шаге мы воспользуемся самым популярным методом для выделения границ – детектором границ Кенни. Алгоритм детектора достаточно тривиален и заключается в следующем:
Результаты и шаги преобразования автомобильного номера отображены на рисунке 11. После выделения границ мы используем стандартную функцию для поиска связанных областей. Окончательным этапом поиска связанных областей является сравнения найденной области с шаблоном символа автомобильного номера и отбрасыванием некорректных областей. Результат выделения символов приведён на рисунке 12. К тому же, данный способ позволяет корректно определять символы автомобильного номера на изображении с повышенной помеховой составляющей, пример приведён на рисунке 13. Блок схема алгоритма приведена в приложении «Ё».
4. Распознавание символов автомобильного номера
Распознавание символов является заключительным этапом работы библиотеки, на текущий момент мы имеем массив с выделенными символами автомобильного номера. Для распознавания символов было принято решение использовать готовый, проверенный временем, продукт от компании Google – Tesseract OCR. Библиотека для распознавания символов Tesseract OCR использует нейронную сеть, которую нам пришлось обучить с учётом шаблона символа автомобильного номера. Во время сборки Tesseract OCR под компилятор mingw32 мы столкнулись с определенными проблемами. Мы просмотрели множество it ресурсов и не обнаружили подробной инструкции для сборки под mingw, поэтому мы решили написать статью и опубликовали её на habrahabr, ссылка на статью и сама статья расположена в приложении «Ж». Блок-схема алгоритма распознавания символов автомобильного номера приведена в приложении «З».
5. Основные методы библиотеки
В данном пункте описаны основные методы библиотеки распознавания автомобильных номеров.
Имя метода | Входные данные | Выходные данные | Описание |
recognize | Изображение | Текст | Распознавание изображения |
getLicenseText | — | Текст | Возвращение распознанного автомобильного номера |
getFrames | — | Изображение | Возвращение найденной области с автомобильным номером |
findLetters | Изображение | Координаты | Выделение связанных областей и нормализация изображения |
setImage | Изображение | — | Установка изображения для распознавания |
showSymbol | — | — | демонстрация на экран изображений с найденными символами на автомобильном номере |
saveSymbols | — | — | Сохраняет на диск пользователя найденные символы на области автомобильного номера |
saveFrame | — | — | Сохраняет на диск пользователя найденные области на автомобильном номере |
recognizeLetters | Координаты | Текст | Распознание найденных символов |
showNormalImage | — | — | Демонстрация изображения для распознавания |
6. Практическое применение разработанной библиотеки: тестовый запуск программы на охраняемом объекте
В рамках проекта была разработана открытая библиотека распознавания автомобильных номеров. Программа, написанная с использованием функций библиотеки, была апробирована в частном охранном предприятии. Для проверки был записан на видео въезд машины на территорию; программа осуществила выделение автомобильного номера, текстовое представление которого может быть подвергнуто дальнейшей обработке. Для демонстрации представляю несколько кадров из видеозаписи. На рисунке 10 приведено изображение и результат работы программы по идентификации номера.
Результаты работы программы по распознаванию номера приведены на рисунке 11.
Рисунок 11 – Демонстрация работы программы на примере входных данных в виде видео
Заключение
Дальнейшее развитие проекта включает улучшение работы алгоритма отсечения помеховой составляющей изображения.
Список использованных источников
Приложение «А»
Пример расчёта интегральной матрицы
У нас есть прямоугольник ABCD с интересующим объектом D (рисунок А.1):
Рисунок А.1
На рисунке видно, что сумму внутри прямоугольника можно выразить через суммы и разности смежных прямоугольников по следующей формуле:
Примерный подсчёт показан на рисунке А.2:
Рисунок А.2
Читаем номерной знак с 10 линиями кода на Python
Любое компьютерное зрение не является тривиальной задачей, и обнаружение номерного знака не является исключением.
Если вы подумаете об этом, нам, людям, будет легко классифицировать то, что на изображениях, — но проблема возникает, когда вы хотите автоматизировать этот процесс. Компьютеры не могут «видеть» так, как мы можем, поскольку они могут только понимать числа, и определение правил для массивов чисел — это, в основном, то, к чему сводятся любые задачи компьютерного зрения (в значительной степени упрощенно).
Итак, в сегодняшней статье я быстро продемонстрирую возможности OpenALPR API для следующих действий:
Опять же, нам так легко взглянуть на изображение автомобиля, и через секунду у нас будет информация по всем вышеперечисленным пунктам. Для компьютеров эта задача намного сложнее — я позволю себе установить OpenCV и попытаться реализовать логику самостоятельно, если вы не согласны со мной.
Немного установки
Для начала вам понадобится учетная запись OpenALPR, для которой вы можете зарегистрироваться здесь. У меня бесплатный тарифный план, и если я не ошибаюсь, он позволит вам делать 50 запросов в месяц. Этого недостаточно для коммерческих целей, но оно точно подойдет вам для исследования.
Если в какой-то момент вам понадобится больше, вот планы, из которых вы можете выбрать:
Это ни в коем случае не дешево, но если у вас есть стоянка, которая обслуживает 1 млн. Автомобилей в месяц, то я предполагаю, что 2 тысячи не так уж много для современной системы считывания номерных знаков.
В любом случае, после регистрации вы получите доступ к своей панели инструментов, и в ней вы можете перейти в раздел API CarCheck, чтобы получить ключ API:
Нам это понадобится позже при отправке запросов, но об этом чуть позже.
Круто, давайте теперь посмотрим на изображение, которое мы будем использовать для тестирования API.
Давайте получим изображение
Я искал в Интернете изображения автомобилей с номерным знаком, которые бесплатны для некоммерческого использования (на самом деле довольно сложно найти то, где номер не размыт). Через некоторое время я нашел довольно приличное изображение приличного автомобиля, и вы можете скачать его по этой ссылке:
Чтение номерных знаков (Читаем номерной знак)
Когда дело доходит до импорта, нам понадобятся только две библиотеки:
Да, вы правильно прочитали. Вам не нужно устанавливать какие-либо библиотеки для использования OpenALPR, что значительно упрощает потенциальное развертывание в будущем.
И теперь приходит та часть, которую мы так долго ждали. Вот шаги, которые мы должны предпринять, чтобы прочитать номерной знак с данного изображения:
В итоге мы получили Цвет, Номер авто, Регион, Брэнд, Год авто, естественно можно было больше указать критериев.
Помните, что я разделил переменную url на две строки, чтобы изображение было более читабельным для вас. Также обратите внимание, как можно указать параметр страны внутри URL-адреса, чтобы получить лучшие результаты, если вы заранее знаете, к какой стране принадлежит номерной знак.
Как видите, с помощью всего лишь нескольких строк кода нам удалось получить столько полезной информации из изображения. Для тех, кто не знаком с компьютерным зрением, для разработки такого решения могут потребоваться месяцы и месяцы работы, и сомнительно, насколько вы были бы удовлетворены результатами в итоге. Читаем номерной знак.
Прежде чем ты уйдешь
И вот, у вас это есть — всего за несколько строк кода нам удалось выполнить современную работу по компьютерному зрению (ну, вроде, мы только что обратились к API).
Бесплатный план подойдет вам для изучения, но подумайте над разработкой полного решения самостоятельно, просто для удовольствия. Может быть, это будет темой для другого времени, так что дайте мне знать, если вас это заинтересует.
А если вам лень кодить то загрузите изображение прям к ним на сайт:
На мой взгляд мы добились неплохих результатов, но если присмотритесь то на номере регистрационного знака автомобиля отсутствует цифра 1, хотя номера просматриваются хорошо. Но это может баг сайта так как точность составила 91.82%.
Но если проанализировать точность распознание номера, то она очень высока, с точность 91.82% система распознала правильный номер.