- PVSM.RU - https://www.pvsm.ru -

Продолжаем рассказ о том как распознавать номерные знаки для тех кто умеет писать приложение «hello world» на python-е! В этой части научимся тренировать модели, которые ищут регион заданного объекта, а также узнаем как написать простенькую RNN-сеть, которая будет справляться с чтением номера лучше чем некоторые коммерческие аналоги.
В этой части я расскажу как тренировать Nomeroff Net под Ваши данные, как получить высокое качество распознавания, как настроить поддержку GPU и ускорить все на порядок…
Конечно же, находить можно не только номер, а любой другой объект, потребность в поиске которого у вас возникла. Например можно, по аналогии, поискать кредитную карту и считать ее реквизиты. В общем, нахождение маски, в которую вписан объект на изображении называют задачей «Instance Segmentation» (об этом я уже писал в первой части).
Сейчас мы разберемся как натренировать сеть для решения этой задачи. На самом деле тут программирования мало, все сводится к монотонной, нудной, однообразной разметке данных. Да-да, после того как вы разметите свою первую сотню вы поймете о чем я :)

Обратите внимание — мы не обучаем все «с нуля», мы дотренировываем модель, обученную на данных COCO dataset [10], которую Mask RCNN закачает при первом запуске
Чтоб опробовать натренированную модель в деле, в примерах проекта [12] замените MASK_RCNN_MODEL_PATH на путь к своей модели.
После того, как области с номерными знаками найдены, нужно попробовать определить какого государства/типа номер мы распознаем. Тут универсализация работает против качества распознавания. Поэтому, в идеале, нужно тренировать классификатор, который не просто определяет какой страны номер, но и разновидность оформления этого номера (расположение символов, варианты символов для заданной разновидности номера).
В нашем проекте мы реализовали поддержку распознавания номеров Украины, РФ и Европейские номера в целом. Качество распознавания европейских номеров немного хуже, так как там номера с разным дизайном и увеличенным количеством встречающихся символов. Возможно, со временем, будут отдельные модули распознавания для «eu-ee», «eu-pl», «eu-nl»,…
Перед классификацией номерного знака его нужно «вырезать» из изображения и нормализировать, другими словами по максимуму убрать все искажения и получить аккуратный прямоугольник, который будет подвергаться дальнейшему анализу. Эта задача оказалась достаточно нетривиальной, мне даже пришлось вспомнить школьную математику и написать специализированную реализацию алгоритма кластеризации k-means :). Модуль, который это все процессит называется RectDetector, вот как выглядят нормализованные номера, которые далее будем классифицировать и распознавать.

Чтоб как-то автоматизировать процесс создания датасета для классификации номеров мы разработали небольшую админку на nodejs [13]. С помощью этой админки вы можете разметить надпись на номерном знаке и класс к которому его относить.
Классификаторов может быть несколько. В нашем случае по типу номера и по тому зарисован/закрашен ли он на фото.

После того как разметили датасет, делим его на тренировочную, валидационную и тестовую выборки. В качестве примера скачайте наш датасет autoriaNumberplateOptionsDataset-2019-03-06.zip [14], чтоб посмотреть как там все устроено.
Так как выборка уже размечена (отмодерирована), то вам нужно в рандомных json-файлах поменять «isModerated»:1 на «isModerated»:0 и после этого запустить админку [13].
Скрипт тренировки train/options.ipynb [15] поможет получить Вам свой вариант модели. На нашем примере видно что для классификации регионов/типов номерных знаков мы получили точность 98.8%, для классификации «закрашен ли номер?» 99,4% на нашем датасете. Согласитесь, неплохо получилось.
Ну вот мы нашли область с номером и нормализировали ее в прямоугольник, который содержит надпись с номером. Как нам прочитать текст? Проще всего прогнать его через FineReader или Tesseract. Качество будет «не очень», но при хорошем разрешении области с номером сможете получить точность на уровне 80%. На самом деле это неплохая точность, но если я Вам скажу что можете получить 97% и при этом потратите значительно меньше компьютерных ресурсов? Звучит неплохо — попробуем. Для этих целей подойдет немного необычная архитектура, в которой используются как сверточные так и рекуррентные слои. Архитектура этой сети выглядит приблизительно так:

Реализация взята с сайта https://supervise.ly/ [16], мы ее немного модифицировали для тренировки на реальных фото (на сайте supervisely подан вариант для синтетической выборки)
Теперь начинается самая увлекательная часть, разметить хотя бы 5 000, номеров :). Мы разметили около ~15 000 Украинских [17], ~6500 Европейских [18] и ~5000 РФ [19]. Это была самая сложна часть разработки. Вы даже не представляете сколько раз я засыпал на стуле у компа модерируя по нескольку часов в день очередную порцию номеров. Но настоящий герой разметки dimabendera [20] — он разметил 2/3 всего контента, (поставьте ему плюс если понимаете как скучно было делать всю эту работу :) )
Можно попробовать этот процесс как-то автоматизировать, например, предварительно распознав каждое изображение Tesseract-ом, а потом уже поправить ошибки с помощью нашей админки [13].
Обратите внимание: для разметки классификатора и OCR на номере используется одна и та же админка. Одни и те же данные вы сможете загрузить и туда и туда, кроме зарисованных номеров, конечно.
Если вы разметите хотя бы 5000 номеров и сможете обучить свою OCR — смело оформляйте себе премию у начальства, уверен, это испытание не для слабаков!
Скрипт train/ocr-ru.ipynb [21] тренирует модель для номеров РФ, там же примеры для Украины [22] и Европы [23].
Обратите внимание, в настройках тренировки там только одна эпоха (один проход).
Особенностью тренировки такого датасета будет очень разный результат при каждой попытке, перед каждой тренировкой данные перемешиваются в случайном порядке, иногда более удачно для тренировки иногда «не очень». Я вам рекомендую пробовать хотя бы 5 раз, при этом контролировать точность на тестовых данных. При разных попытках запуска у нас точность могла «прыгать» от 87% до 97%.
Несколько рекомендаций:
Если вы счастливый обладатель GPU от NVIDIA, то вы можете в разы все ускорить: и тренировку моделей и инференс (режим распознавания) номеров. Проблема заключается в том чтоб корректно все установить и скомпилировать.
Мы на своих серверах ML используем Fedora Linux (так сложилось исторически).
Приблизительная последовательность действий для тех кто использует эту OS следующая:
Если собрать tensorflow с поддержкой gpu не получится, можно запустить все через docker, при этом кроме docker-а нужно доустановить пакет nvidia-docker2. Внутри docker-контейнера можно запустить jupyter notebook, и далее запускать все там.
jupyter notebook --ip=0.0.0.0 --port=8888 --allow-root
Также хочу поблагодарить читательов 2expres [29], glassofkvass [30] за предоставленные фото с номерами и dimabendera [20] за то что написал большую часть кода и разметил большую часть данных проекта Nomeroff Net.
Автор: Олег Черний
Источник [31]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/310927
Ссылки в тексте:
[1] Распознавание номеров. Практическое пособие. Часть 1: https://habr.com/ru/post/432444/
[2] VGG Image Annotator (VIA): http://www.robots.ox.ac.uk/~vgg/software/via/
[3] прямо онлайн: http://www.robots.ox.ac.uk/~vgg/software/via/via.html
[4] размеченных данных для проекта Nomeroff Net: https://nomeroff.net.ua/datasets/autoriaNumberplateDataset-2018-11-20.zip
[5] Nomeroff Net: https://github.com/ria-com/nomeroff-net
[6] Mask RCNN: https://github.com/matterport/Mask_RCNN
[7] train/mrcnn.ipynb: https://github.com/ria-com/nomeroff-net/blob/master/train/mrcnn.ipynb
[8] наших данных: https://nomeroff.net.ua/datasets/autoriaNumberplateDataset-2019-03-06.zip
[9] tensorflow с поддержкой GPU: #tensorflowGPU
[10] COCO dataset: http://cocodataset.org/
[11] нашу модель mask_rcnn_numberplate_0700.h5: https://nomeroff.net.ua/models/mask_rcnn_numberplate_0700.h5
[12] примерах проекта: https://github.com/ria-com/nomeroff-net/tree/master/examples
[13] небольшую админку на nodejs: https://github.com/ria-com/nomeroff-net/tree/master/moderation
[14] autoriaNumberplateOptionsDataset-2019-03-06.zip: https://nomeroff.net.ua/datasets/autoriaNumberplateOptionsDataset-2019-03-06.zip
[15] train/options.ipynb: https://github.com/ria-com/nomeroff-net/blob/master/train/options.ipynb
[16] https://supervise.ly/: https://supervise.ly/
[17] ~15 000 Украинских: https://nomeroff.net.ua/datasets/autoriaNumberplateOcrUa-2019-02-19.zip
[18] ~6500 Европейских: https://nomeroff.net.ua/datasets/autoriaNumberplateOcrEu-2019-02-19.zip
[19] ~5000 РФ: https://nomeroff.net.ua/datasets/autoriaNumberplateOcrRu-2019-03-06.zip
[20] dimabendera: https://habr.com/ru/users/dimabendera/
[21] train/ocr-ru.ipynb: https://github.com/ria-com/nomeroff-net/blob/master/train/ocr-ru.ipynb
[22] Украины: https://github.com/ria-com/nomeroff-net/blob/master/train/ocr-ua.ipynb
[23] Европы: https://github.com/ria-com/nomeroff-net/blob/master/train/ocr-eu.ipynb
[24] вот тут для Fedora: https://www.if-not-true-then-false.com/2015/fedora-nvidia-guide/#before-installation
[25] вот тут для CentOS/Fedora: https://negativo17.org/nvidia-driver/
[26] tensorflow из исходников по этой доке: https://www.tensorflow.org/install/source
[27] Домашняя страница Nomeroff Net: https://nomeroff.net.ua/
[28] Онлайн демка Nomeroff Net: https://nomeroff.net.ua/onlinedemo.html
[29] 2expres: https://habr.com/ru/users/2expres/
[30] glassofkvass: https://habr.com/ru/users/glassofkvass/
[31] Источник: https://habr.com/ru/post/439330/?utm_source=habrahabr&utm_medium=rss&utm_campaign=439330
Нажмите здесь для печати.