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

Распознавание номеров. Как мы получили 97% точности для Украинских номеров. Часть 2

Nomeroff Net numberplate detection OCR example

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

Тренируем Mask RCNN находить область с номером

Конечно же, находить можно не только номер, а любой другой объект, потребность в поиске которого у вас возникла. Например можно, по аналогии, поискать кредитную карту и считать ее реквизиты. В общем, нахождение маски, в которую вписан объект на изображении называют задачей «Instance Segmentation» (об этом я уже писал в первой части).

Сейчас мы разберемся как натренировать сеть для решения этой задачи. На самом деле тут программирования мало, все сводится к монотонной, нудной, однообразной разметке данных. Да-да, после того как вы разметите свою первую сотню вы поймете о чем я :)

Итак, алгоритм подготовки данных следующий:

  • Берем изображения размером не менее 300x300, сбрасываем все в одну папку
  • Загружаем инструмент для нанесения разметки VGG Image Annotator (VIA) [2], можно размечать прямо онлайн [3], на выходе будет директория с фото и сформированный вами json-файл с разметкой. Таких папок нужно две, в одной под названием train поместите основную часть примеров, во вторую val приблизительно 20-30% от числа примеров первой паки (Конечно же, в этих папках не должно быть одинаковых фотографии). Можете посмотреть пример размеченных данных для проекта Nomeroff Net [4]. По количеству — чем больше тем лучше. Некоторые специалисты рекомендуют 5 000 примеров, мы обленились, набрав чуть более 1 000 так как результат нас вполне устроил.

    VGG Image Annotator (VIA) editing example

  • Чтоб приступить к обучению вам нужно загрузить с Github сам проект Nomeroff Net [5], установить Mask RCNN [6] со всеми зависимостями и можно попробовать запустить скрипт тренировки train/mrcnn.ipynb [7] на наших данных [8]
  • Сразу предупреждаю, это работает не быстро. Если у Вас нет GPU это может занять дни. Чтоб существенно ускорить процесс обучения желательно установить tensorflow с поддержкой GPU [9].
  • Если тренировка на нашем датасета у вас прошла успешно, теперь можно смело переключатся на свой.
  • Обратите внимание — мы не обучаем все «с нуля», мы дотренировываем модель, обученную на данных COCO dataset [10], которую Mask RCNN закачает при первом запуске

  • Вы можете дотренировывать не coco, а нашу модель mask_rcnn_numberplate_0700.h5 [11], при этом укажите путь к этой модели в конфигурационном параметре WEIGHTS (по умолчанию «WEIGHTS»: «coco»)
  • Из параметров, которые можно протюнить это: EPOCH, STEPS_PER_EPOCH
  • Результат после каждой эпохи будет сбрасываться в папку ./logs/numberplate<дата запуска>/

Чтоб опробовать натренированную модель в деле, в примерах проекта [12] замените MASK_RCNN_MODEL_PATH на путь к своей модели.

Улучшаем классификатор номерных знаков под свои требования

После того, как области с номерными знаками найдены, нужно попробовать определить какого государства/типа номер мы распознаем. Тут универсализация работает против качества распознавания. Поэтому, в идеале, нужно тренировать классификатор, который не просто определяет какой страны номер, но и разновидность оформления этого номера (расположение символов, варианты символов для заданной разновидности номера).

В нашем проекте мы реализовали поддержку распознавания номеров Украины, РФ и Европейские номера в целом. Качество распознавания европейских номеров немного хуже, так как там номера с разным дизайном и увеличенным количеством встречающихся символов. Возможно, со временем, будут отдельные модули распознавания для «eu-ee», «eu-pl», «eu-nl»,…

Перед классификацией номерного знака его нужно «вырезать» из изображения и нормализировать, другими словами по максимуму убрать все искажения и получить аккуратный прямоугольник, который будет подвергаться дальнейшему анализу. Эта задача оказалась достаточно нетривиальной, мне даже пришлось вспомнить школьную математику и написать специализированную реализацию алгоритма кластеризации k-means :). Модуль, который это все процессит называется RectDetector, вот как выглядят нормализованные номера, которые далее будем классифицировать и распознавать.

Пример нормализации номерных знаков

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

Классификаторов может быть несколько. В нашем случае по типу номера и по тому зарисован/закрашен ли он на фото.

Админка для разметки номерных знаков Nomeroff Net

После того как разметили датасет, делим его на тренировочную, валидационную и тестовую выборки. В качестве примера скачайте наш датасет autoriaNumberplateOptionsDataset-2019-03-06.zip [14], чтоб посмотреть как там все устроено.

Так как выборка уже размечена (отмодерирована), то вам нужно в рандомных json-файлах поменять «isModerated»:1 на «isModerated»:0 и после этого запустить админку [13].

Тренируем классификатор:

Скрипт тренировки train/options.ipynb [15] поможет получить Вам свой вариант модели. На нашем примере видно что для классификации регионов/типов номерных знаков мы получили точность 98.8%, для классификации «закрашен ли номер?» 99,4% на нашем датасете. Согласитесь, неплохо получилось.

Тренируем свою OCR (распознавалку текста)

Ну вот мы нашли область с номером и нормализировали ее в прямоугольник, который содержит надпись с номером. Как нам прочитать текст? Проще всего прогнать его через FineReader или Tesseract. Качество будет «не очень», но при хорошем разрешении области с номером сможете получить точность на уровне 80%. На самом деле это неплохая точность, но если я Вам скажу что можете получить 97% и при этом потратите значительно меньше компьютерных ресурсов? Звучит неплохо — попробуем. Для этих целей подойдет немного необычная архитектура, в которой используются как сверточные так и рекуррентные слои. Архитектура этой сети выглядит приблизительно так:

image

Реализация взята с сайта 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%.

Несколько рекомендаций:

  • Не нужно инициализировать все по-новой просто перезапускаем строку model = ocrTextDetector.train(mode=MODE) пока не получим ожидаемый результат
  • Одна из причин плохой точности недостаточное количество данных. Если не устраивает — размечаем еще и еще, в какой-то момент качество расти перестает, для каждого датасета по-разному, можно ориентироваться на цифру 10 000 размеченных примеров
  • Тренировка будет проходить быстрее, если у вас установлен драйвер CuDNN от NVIDIA [9], поменяйте значение MODE = «gpu» в сценарии обучения и вместо слоя GRU подключится CuDNNGRU, что приведет к трехкратному ускорению.

Немного о настройке tensorflow для GPU NVIDIA

Если вы счастливый обладатель GPU от NVIDIA, то вы можете в разы все ускорить: и тренировку моделей и инференс (режим распознавания) номеров. Проблема заключается в том чтоб корректно все установить и скомпилировать.

Мы на своих серверах ML используем Fedora Linux (так сложилось исторически).

Приблизительная последовательность действий для тех кто использует эту OS следующая:

  • Ставим драйвер GPU для вашей версии OS, вот тут для Fedora [24]
  • Подключаем репозиторий NVIDIA и ставим оттуда набор пакетов CUDA, вот тут для CentOS/Fedora [25]
  • Ставим bazel, и собираем tensorflow из исходников по этой доке [26]
  • Так же желательно установить старую версию компилятора gcc, который называется cuda-gcc, у меня все нормально собиралось на cuda-gcc 6.4. При настройке сборки указывайте путь именно к cuda-gcc

Если собрать 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