- BrainTools - https://www.braintools.ru -
Привет! Меня зовут Наталия Вареник, я DS-инженер в Авито [1], занимаюсь моделями распознавания изображений. Расскажу про один из наших проектов — пайплайн для распознавания номеров с фотографии свидетельства транспортного средства (СТС). В статье описала особенности задачи и рассказала, как мы решали её с помощью декомпозиции.
Материал будет полезен начинающим и мидл-DS-инженерам, которые хотят узнать больше про декомпозицию задачи на этапах разметки и построения моделей.
А еще материал стоит прочитать тем, кто работает с доменами, где нужно иметь дело с задачами распознавания информации с документов — наш подход прекрасно переносится на другие категории. В целом рекомендую статью всем, кто интересуется компьютерным зрением [2] и его применимостью в разных сферах.

Контекст
Суть задачи [3]
Требования к модели [4]
Этапы работы над моделью и результаты
Начали с тестирования опенсорсных-решений [6]
Решили разработать своё решение и разбили его на 3 этапа: проверочные модели, детектор, OCR [7]
Сделали проверочные модели для анализа пользовательских снимков СТС [8]
Внедрили детектор для распознавания положения номеров на фото [9]
Использовали OCR для распознания текста [10]
Результаты: попали в целевые метрики и получили показатели выше ожидаемых [11]
Пользователям сложно проходить проверки на Авито — мы требуем много информации с документов, в которой легко ошибиться, если вводить вручную. Мы следим за качеством контента на площадке, поэтому на этапе подачи объявления просим много подтверждённых данных.
Так, чтобы разместить объявление о продаже машины на Авито, мы просим продавцов добавлять в объявление фото машины, VIN и госномер.
Все данные, которые добавляют пользователи, мы проверяем на соответствие.
VIN и госномер — это длинные последовательности символов, в которых легко ошибиться при ручном вводе. Но эти данные важны, так как, например, по VIN-номеру мы смотрим историю автомобиля, а потом сверяем его с госномером.
Часть пользователей уставали заполнять форму отправки объявления. Часть заполняли всё, но объявления не проходили модерацию из-за ошибок в VIN или госномерах. Из всех отказов в публикации объявлений 8% мы отклоняли именно по этой причине.
Многие пользователи обращались в поддержку, когда заполнить данные не получалось, и нагрузка на сотрудников саппорта росла.
Мы хотели найти решение, чтобы повысить процент объявлений, которые успешно проходят модерацию, упростить процесс ввода данных для пользователей и снизить нагрузку на саппорт.
Этим решением стала модель, которая автоматически заполняет поля для VIN и госномера по фотографии свидетельства транспортного средства — СТС.
Было четыре основных требования:
Высокая точность. На основе данных про авто принимаются важные решения, поэтому ради точности мы были готовы пожертвовать ресурсами.
Переносимость на другие домены — чтобы мы или коллеги в дальнейшем могли решать запросы на распознавание данных с фото по уже проработанному пайплайну.
Масштабируемость под продовую нагрузку — чтобы мы легко могли увеличить пропускную способность и скорость обработки, и модель не легла под большим потоком пользователей. Например, это будет полезно, если другие команды тоже начнут использовать нашу модель для распознавания данных.
Устойчивость к вариативности данных — об этом расскажу дальше.
Для распознавания данных мы решили взять свидетельство транспортного средства (СТС). Это обязательный документ для автовладельцев, который подтверждает, что машина зарегистрирована и может законно находиться на дороге.
Выглядит это так:
Дисклеймер: все фотографии документов предоставили для статьи мои коллеги. Мы не публикуем персональные данные пользователей.
В процессе работы мы поняли, что разные СТС могут отличаться друг от друга. И из-за этого возникли некоторые сложности.
Первая сложность — в участках нанесения номеров. Хотя СТС — это документ с чёткой структурой, конкретные области с нужными номерами могут отличаться.
Есть ещё одна особенность — различия в VIN или идентификационном номере транспортного средства. У большинства машин — обычный VIN, который состоит из 17 символов и совпадает с номером кузова. Но у старых японских машин в графе VIN часто пишут слово «Отсутствует», а вместо него в качестве идентификатора используют номер кузова:
И хотя нам нужны только VIN и госномер, модель всё равно должна уметь распознавать ещё и номер кузова:
в случае с «обычным» СТС, номер кузова поможет точнее распознать VIN, если с нужной области корректно распознать не получилось;
в ситуации с «японским» СТС, мы будем использовать номер кузова вместо отсутствующего VIN.
У самих номеров тоже есть особенности и чёткая структура:
Перед разработкой своей модели мы попробовали поработать с тремя популярными end-to-end решениями, которые подходят под задачу, а после сравнили результаты.
Требования к решениям: точность > 95%, полнота > 90%. Оценку точности свели к бинарным кейсам: распознали / не распознали.
Библиотеки, которые мы использовали, с документацией на GitHub:
🔗 PaddleOCR [15]
🔗 DocTR [16]
🔗 EasyOCR [17]
Сравнили результаты:
|
Модель |
Точность — госномер |
Полнота — госномер |
Точность — VIN |
Полнота — VIN |
|
PaddleOCR |
94,3% |
78,7% |
74,1% |
85,6% |
|
DocTR |
95,4% |
85,8% |
43,0% |
89,6% |
|
EasyOCR |
25,3% |
79,6% |
30,9% |
30,7% |
Лидером стал PaddleOCR, но даже это решение не вписывалось в требования. Мы разобрали ошибки [18] и обнаружили, что модель:
пропускала нужные номера на этапе детекции;
допускала ошибки в одиночных символах;
делала ошибки на концах номеров из-за наложения другого текста или близкого соприкосновения;
склеивала два слова из строки в одно.
После всех тестов мы решили не докручивать опенсорсное решение, а сделать свой лёгкий в использовании пайплайн под конкретную задачу.
Очень высокой точности распознавания мы добились с помощью декомпозиции. Это значит, что решение состоит не из одной модели, которая делает все задачи по распознаванию, а из нескольких моделей с узкой «зоной ответственности». При этом каждая из этих промежуточных моделей готовит данные для следующего этапа.
Пайплайн состоит из трёх этапов:
проверочные модели — проверяют исходную фотографию свидетельства и, если она некачественная, возвращают её пользователю с подсказками по улучшению. Так мы не будем плодить ошибки распознавания на некачественных данных и поможем автору объявления дойти до публикации;
детектор — выделяет и вырезает области с нужными номерами из исходных фотографий;
OCR — распознаёт номера.
Первый шаг после того, как пользователь загрузил фотографию документа — проверить снимок с помощью классификаторов. Они определяют:
какой тип документа на фото — если это не СТС;
видно ли в кадре СТС полностью;
насколько далеко находится СТС на фото.
Во всех этих случаях, если фото не удовлетворяет нашим требованиям, мы отказываем в распознавании и даём пользователю подсказку.
Ещё определяем, под каким углом сфотографировали СТС. Если фото сделали под углом или с перспективой, исправляем до нормального положения. На этом этапе можно добавить дополнительные параметры проверки — например, размытость, тени и блики в важных местах.
Детектор мы обучали на собственной разметке — датасете из фотографий документов, где руками были выделены области с номерами.
Поскольку текст на самом документе может быть под углом, для выделения нужных областей мы использовали ориентированные четырёхугольники — так в области не попадёт лишний текст.
Разделили разметку на два проекта, чтобы проверить качество работы асессоров. В рамках первого просили выделить номера, во втором — просили проверить качество по критериям.
Затем контролировали точность разметки во втором проекте. Для этого использовали голден — набор примеров, где мы знаем эталонные ответы. Эти примеры случайно подмешивали асессорам, после чего сравнивали эталонные ответы с теми, что дали асессоры. Считали долю правильных ответов и ошибок.
Таким образом мы оценивали качество работы как отдельных асессоров, так и разметки в целом.
Благодаря декомпозиции получилась очень точная разметка.
Для детекции использовали сегментационную модель U-Net, потому что она позволяла очень тонко выделить область с номером. Обучили модель на два класса: 1 — пиксель принадлежит маске одного из номеров, 0 — часть фона. На выходе получаем маску, которая накладывается на изображения и показывает, где расположены номера:
Для повышения точности провели аугментацию — добавляли на фотографии размытие, засветы, затемняли их. Это помогло получить более точные границы на размытых фотографиях и исключить разрезы маски из-за бликов на номерах.
Мы получили улучшенный результат на данных с размытостью и засветами, так как модель видела это на обучении [20] и училась, как работать в таком случае.
Эта модель хорошо работала на большинстве фотографий, но давала неточности на изображениях с большой перспективой, отдалённостью, или, если снимки были сделаны под углом. Мы пытались добавлять фотографии под углом в данные, но этого было недостаточно — маски всё равно искажались.
Добавили блок для выравнивания документа перед этапом детектирования. Если пользователь присылает фотографию под углом или с перспективой — мы поворачиваем её до нормального положения и корректируем перспективу.
Для выравнивания используем архитектуру RetinaNET — находим четыре координаты углов документа, по ним определяем границы, обрезаем фон и выравниваем.
Для коррекции перспективы применяем warpPerspective. Это функция в OpenCV Python [21], которая применяет аффинное преобразование к картинке, которое убирает перспективу.
Нам она нужна, чтобы убрать перспективу на фотографиях СТС, которые были сделаны не строго сверху:
🔗 Документация для архитектуры RetinaNET на GitHub [22]
На последнем этапе модель распознаёт номера на кусочках из исходной картинки, которые вырезали по маске из детектора. Для распознавания текста мы обучили свёрточно-рекуррентную архитектуру CRNN с CTC-декодером и датасетом из пар: «картинка + текст».
По маске с предыдущего этапа мы вырезаем области с номерами из фотографий и выравниваем их:
После распознавания текста номеров мы применили валидационные правила, чтобы проверить или скорректировать результаты. Это нужно для большей точности. Правила построили на основе знаний о структуре номеров.
Провели тесты нашей модели и смогли побить пороги, которые ставили ещё до разработки. Получили такие значения:
|
|
Точность |
Полнота |
|
Госномер |
97,5% |
90,1% |
|
VIN |
98,5% |
90,3% |
Также мы собрали данные по ошибкам после внедрения модели. На графике видно, что она не смогла распознать текст только у 8% фотографий. В остальных случаях модель либо распознала всё успешно, либо мы дали подсказки, как исправить ошибки, и она распознала нужные данные после этого.
Улучшили целевые метрики:
повысили конверсию в публикацию объявления на 4%;
снизили количество отказов в публикации объявлений из-за неверного номера на 55%;
уменьшили количество обращений в поддержку на 45%.
В работе над этим проектом мы использовали её дважды.
Первый раз на этапе разметки — делили большую задачу по разметке со сложным контролем качества на подзадачи для асессоров. Чтобы датасет был более качественным, и мы смогли отобрать только самые подходящие примеры для обучения модели.
Второй раз, когда разбили задачу «распознать номер с документа» на несколько этапов и сделали отдельную модель для каждой стадии.
Вот что нам это дало:
Качество. Система становится качественнее, так как каждый шаг подготавливает данные для следующего. На каждом отдельном этапе решается узкая задача, и у нас появляется больше контроля.
В итоге мы можем использовать полученные данные либо при подготовке к распознаванию, либо чтобы возвращать фотографию пользователям на доработки.
Контролируемость. Отдельные шаги пайплайна проще проверять на качество, чем огромную модель, которая занимается сразу всем.
Интерпретируемость. Пайплайн с детализацией по шагам позволяет логировать промежуточные результаты и исследовать, где возникла проблема.
Гибкость. В зависимости от потребности [23] можно настраивать отдельные шаги и не трогать весь пайплайн — например, докручивать детектор или добавлять новые параметры в проверочную модель.
Переносимость. Модели в пайплайне обучены под СТС, но ту же технологию можно применить для других документов — например, для кадастровых номеров в объявлениях о продаже недвижимости.
Масштабируемость. Адаптироваться к продовой нагрузке проще, если есть возможность настроить ресурсы на отдельные шаги.
Спасибо вам за уделенное статье время! На вопросы буду рада ответить в комментариях к статье.
Больше интересных кейсов и историй из мира Data Science в Авито читайте в нашем не душном, а душевном телеграм-канале — «Доска AI объявлений» [24]. Подробнее о том, какие задачи решают инженеры Авито и с помощью каких инструментов они это делают — на нашем сайте [1] и в телеграм-канале AvitoTech [25]. Свежие вакансии в нашу команду — вот здесь [26].
Автор: natalia_varenik
Источник [27]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/15191
URLs in this post:
[1] Авито: https://clc.to/LV3FBg
[2] зрением: http://www.braintools.ru/article/6238
[3] Суть задачи: #section1
[4] ребования к модели: #section2
[5] Что мы знаем о данных: #section3
[6] Начали с тестирования опенсорсных-решений: #section4
[7] Решили разработать своё решение и разбили его на 3 этапа: проверочные модели, детектор, OCR: #section5
[8] Сделали проверочные модели для анализа пользовательских снимков СТС: #section6
[9] Внедрили детектор для распознавания положения номеров на фото: #section7
[10] Использовали OCR для распознания текста: #section8
[11] Результаты: попали в целевые метрики и получили показатели выше ожидаемых: #section9
[12] : https://docs.google.com/document/d/1cpQKsfd-yotGeu1r1FMrBvz6EJeAdxeoKv50aQQjiWw/edit?tab=t.0#heading=h.4gz8m5dt8jdb
[13] Что даёт декомпозиция: #section10
[14] Кликни здесь и узнаешь: https://clc.to/vtMlJg
[15] PaddleOCR : https://paddlepaddle.github.io/PaddleOCR/main/ru/index.html
[16] DocTR: https://github.com/mindee/doctr
[17] EasyOCR: https://github.com/JaidedAI/EasyOCR
[18] ошибки: http://www.braintools.ru/article/4192
[19] Жми сюда!: https://clc.to/MDY_jw
[20] обучении: http://www.braintools.ru/article/5125
[21] OpenCV Python: https://docs.opencv.org/4.x/da/d54/group__imgproc__transform.html
[22] Документация для архитектуры RetinaNET на GitHub: https://github.com/yhenon/pytorch-retinanet
[23] потребности: http://www.braintools.ru/article/9534
[24] «Доска AI объявлений»: https://web.telegram.org/a/#-1002449381443
[25] в телеграм-канале AvitoTech: https://clc.to/mnG_FQ
[26] вот здесь: https://clc.to/1QTHTg
[27] Источник: https://habr.com/ru/companies/avito/articles/908650/?utm_campaign=908650&utm_source=habrahabr&utm_medium=rss
Нажмите здесь для печати.