Как улучшить распознавание маркировки с помощью нейросети
«Мне нужно чтобы всё распозналось, а никто не может это сделать!» С таким почти что криком души к нам с коллегой обратился один из производителей мороженого, на линии которого маркировка никак не хотела распознаваться. Конечно же, мы приняли этот вызов. Почему не каждая маркировка легко считывается, как мы улучшили алгоритм распознавания маркировки «Честный знак» для мягкой упаковки мороженого и что из этого получилось — читайте дальше.
Наверняка многие из вас пользовались кассами самообслуживания в супермаркетах и пробовали отсканировать DataMatrix код «Честный знак» с упаковок мороженого, творога, молока, глазированных сырков и прочих продуктов в тонкой и гибкой упаковке. Согласитесь, редко получается сделать это с первого раза. А теперь представьте такую ситуацию на производстве, где нужно массово агрегировать всю продукцию с маркировкой…, а она не распознаётся! Именно такую проблему мы старались решить в одном из наших кейсов: Работает конвейер, на котором уже готовая, упакованная в БОПП-плёнку, продукция идет в хаотичном положении, но кодами «честный знак» вверх. Проходя участок сканирования, она попадает на групповую упаковку в картонный короб по несколько штук. И для дальнейшей логистики очень важно знать какие именно коды маркировки находятся в конуретной упаковке.
Итак, перед нами стояла задача — отсканировать максимальное количество кодов (т. е. распознать всю маркировку с упаковок мороженого на конвейере), а те, что не отсканировались, отбраковать (в нашем случае сбросить для повторного, ручного сканирования или перемаркировки).
Пример линии групповой упаковки мороженного
Почему код не распознаётся с первого раза
На это есть две причины. Первая — низкий грейд кода. Подробнее об проблемах печати можно прочитать здесь: https://habr.com/ru/articles/599405/ Вторая — даже когда код напечатан идеально, с грейдом А, всё может подпортить алгоритм распознавания, который «не увидит» код.
Если пойти в историю и задаться вопросом «Для чего придумали код DM?», то окажется, что код DataMatrix используется, в первую очередь, для маркировки изделий на производстве с целью прослеживаемости. То есть код априори должен наноситься на твердую поверхность: чугунный блок двигателя, лист стали, корпус процессора или на бирку изделия. И максимальные его повреждения в процессе жизни — смазали, покоцали или закрасили. А вот его геометрия всегда прямоугольна и сетка всегда ровная. От этого и алгоритм его распознавания рассчитан на идеально ровное, твердое размещение кода. Но как вы понимаете, упаковка мороженного таковой не является.
ЧТо Пример нанесения кода DataMatrix лазером
Как работает алгоритм распознавания DM:
Он находит так называемую L-границу кода, по ней понятна ориентация кода и его границы.
Определяются тактовые ячейки, для алгоритма они задают сетку, по которой считывается код.
Из зоны хранения данных кода берется графическая информация, по полученной сетке она разбивается на бинарную матрицу 0 и 1.
Применяются различные алгоритмы восстановления данных (так как не всегда однозначно по сетке удается определить значение точки) и код преобразовывается в текстовую информацию.
Этапы распознавния кода маркировки
Что пошло не так?
Проблема с кодами начинается на мягкой упаковке, где место нанесения кода физически может деформироваться. В результате на сканере кода получаем вот такую картинку, которую, естественно, алгоритм не может распознать. Да, он видит что-то похожее на код, но всячески отказывается с ним работать.
Пример искаженного кода маркировки с грейдом B
Это как раз наш случай. К тому же небольшие трудности вызывали блики на упаковке, но с помощью правильно подобранной оптики и света удалось быстро это решить. А вот проблему помятой упаковки с кодом мы решили отбраковкой с применением нейросети.
Реализация этого решения выглядела следующим образом:
Натренировать нейросеть класса Semantic Segmentation с целью выделить границы кода. На выходе получим ломаный контур кода, но он даст нам понять, как именно искажён код.
Математически «развернуть» искажённый код до состояния квадрата (благо, коды «Честный знак» всегда квадратные, хотя и имеют разное количество модулей).
Попробовать распознать растянутый код стандартным алгоритмом чтения DM.
Если не получится распознать, то по выровненной L стороне, зная шаг и размер кода, попытаться восстановить сетку кода и его логические значения и передать на распознавание алгоритму уже готовую бинарную матрицу. (Пока не реализовал, оставил на будущее)
Пример определения модулей по сетке кода классическим алгоритмом распознавания маркировки
Цель, стек и план разработки MVP
Цель. Клиенту было важно показать снижение процента отбраковки (ручного сканирования) в идеале до 2%. Сроки поджимали, так как были значительные затраты на дополнительных операторов линии.
Стек. Разработку вели на Python, а для создания пользовательского интерфейса использовали модернизированный GUI другого проекта PyQT, библиотеку машинного зрения и нейронку от MVTec Halcon (её мы часто используем для распознавания Datamatrix, а работать в рамках одного пакета и с камерой, и с MV и DL весьма удобно).
План. Выезд на площадку + съемка данных, пара недель на MVP, тест-прогон, боевое тестирование на производстве, доведение по ходу работы до бета-версии.
Теперь о самом интересном, о разработке.
Первый этап — обучение нейросети
Сам процесс разметки и обучения нейросети происходил в Deep Learning Tool. Это весьма удобное приложение, в котором получается готовая, натренированная нейронка со всеми метриками. Первый объем снимков с кодами был довольно скромным — 332 кадра искревлённого кода, размеченных вручную.
Конфигурация первого датасета и нейросети
Однако первая попытка натренировать нейросеть показала вполне неплохие результаты: она с лёту находила код и весьма хорошо справлялась с определением его границ.
Результат определения контура кода
Процесс тренировки
Сделав авторазметку по имеющейся базе читаемых кодов DM, отснятых на производстве (взяв за верную границу рамку кода), получили неплохой датасет на тысячи кодов разного форм-фактора. Дополнительно пришлось сделать предобработку кадров, т. е. кадрировать участки с кодом с целью повысить рабочее разрешение и не обучать нейросеть неделю. Так мы получили вполне боевую нейронку с приемлемым качеством отрисовки границы кода и хорошей производительностью.
Результат определения контура кода после дообучения
Для подтверждения нечитаемости кода запустили на смартфоне ПО с одним из лучших алгоритмов распознавания маркировки — Cognex Barcode Scanner. Результат ожидаемый — маркировка не видна
Искревлённый код ожидаемо, не хочет считываться даже лучшими на рынке алгоритмами распознвания
Второй этап — разработка алгоритма расправления кода
Данный алгоритм должен вырезать код по контуру от нейросети, равномерно растянуть изображение, превратив его в квадрат. Кто знаком с теорией обработки изображений, узнает в этой задаче применение полиномиальных преобразований. В нашем случае оно было обратным: из искаженного кадра с неизвестной кривизной, приведенным к экспонентонициальным кривым нужно было получить прямоугольник.
Примечание: данное упращение стало золотой серединой в производительности и качестве для нас, так как выравнивать весь контур кода затратно по времени, а сводить задачу к выравниванию разностороннего четырехугольника слишком грубо. А описать геометрию кода четырмя экспонентами по «нейросетевому» краю, и от них выравнить код — оказалось самое оно.
пример задачи обратных полиномиальных преобразований
Дополнительно, под код добавляется белая квадратная подложка, облегчающая его распознавнаие классическим алгоритмом.
Тестирование
Задача тестирования — понять, достаточно ли обучилась нейросеть, снять метрики и получить новые данные для дообучения нейросети и усовершенствования алгоритма. Тестирование было в два этапа: в лаборатории и на производстве.
Тестирование в лаборатории
Для тестирования в лабораторных условиях мы собрали небольшой стенд, состоящий из следующего оборудования:
небольшой конвейер,
камера машинного зрения с объективом,
кольцевая подсветка,
фотодатчик,
мини-ПК с развернутым ПО.
В качестве объекта тестирования пошло в ход всё, что было в холодильнике в аналогичной мягкой упаковке (творог, сырки, мороженое), а также нанесенные на фольгу коды DataMatrix. Ниже приведу пример работы алгоритма выравнивания кода по контуру.
Пример снимка кода с творожного сырка. Маркировка не читаема обычным алгоритмом.
Код с данного снимка имеет минимальные искажения, однако упаковка повернута под большим углом относительно камеры, делая код нечитаемым. Чтобы гарантированно распознать такой код классическим алгоритмом, нужен массив разнонаправленных камер. Но это не наш метод, нейросеть без проблем нашла код, а алгоритм «развернул» его лицом к нам:
Пример успешного распознавния кода после его «разворота»
Это достаточно легкий случай, но даже такая реализация уже значительно повышает процент распознавания. Однако есть к чему стремиться — конечной целью нашей разработки будет распознавание кода со значительно искажённой геометрией путем восстановления его смятых участков из стереоизображения и чтением его модулей нейросетью. Пример такого кода на фото:
Пример сильно замятой упаковки с нечитаемой маркировкой. Одако, количество дефектных модулей у него минимально, и шанс обработать и распознать такой код есть!
По итогам тестирования, смятия фольги и прогонки более 1000 кодов вышли на следующие метрики:
Максимальное время распознавания кода (от получения ПО снимка до выдачи информации о коде) — 340 мс. Сделаем скидку на мини-ПК — не для этого он, но что имеем, как говорится.
Среднее время распознавания — 184 мс.
Эффективность обнаружения DM кодов — 99.3% со средней ошибкой по геометрии в 8%.
Эффективность распознавания — 73%. Важно сказать, что некоторые коды сминали слишком сильно, далеко от реальных ситуаций, но тем и интереснее.
Доработки по результатам тестирования свелись к дообучению нейросети на новых, размеченных данных. По итогам повторной прогонки на базе отснятых снимков ошибка по геометрии упала до 5%, а эффективность распознавания выросла на те же 3%. Также мы задумались над использованием иных способов подсветки бликующих поверхностей, рассматривали поляризационные светофильтры и коаксиальный свет. Но в итоге попробовали совсем новый для меня вариант купольного света — туннельная подсветка. По итогам тестирования такой подсветки получилось полностью пересветить блики и бонусом — закрыть зону съемки от постороннего света.
Тунельная подсветка, изготовленная с применением дендрофекальных технологий. Прототип, не продаётся
Такая подсветка заменяет купольную подсветку на конвейере, обеспечивая равномерную засветку всей упаковки. Благодаря данной подсветке мы можем получать снимки блестящей упаковки без бликов.
Пример фото блестящей упаковки в световом туннеле. Минимальныйе отблески хоть и присутствуют -, но чтению информации они не мешают.
Та же упаковка, но уже при офисном освещении.
Тестирование на производстве
Тестирование на производстве было более основательным. Мы использовали следующее оборудование:
Три камеры машинного зрения, расположенные аркой, с шагом в 45 градусов над конвейерной лентой.
Туннельная подсветка — собственная разработка, позволяющая «засветить» упаковку полностью, избежав блика. Выполнили из матового металла с несколскими светодиодными арками из COB светодиодной ленты.
Фотодатчик и энкодер, позволяющие синхронизировать съемку и скорость конвейера, тем самым получаем только заведомо информативные кадры.
Пневматический отбраковщик — готовое покупное изделие.
Контроллер вход-выход для управления отбраковщиками и сигнализацией.
Шкаф с промышленным ПК и сенсорным монитором.
В настоящий момент система находится в боевом тестировании, а параллельно мы получаем с неё новые данные о нераспознанных кодах и дообучаем алгоритм. Планируем довести подобное тестирование до 60 рабочих дней и в последующем снять метрики для производства и выкатить рабочий релиз.
Итого: даже на данном этапе реализации проекта нейросеть хорошо помогла нам распознать проблемную маркировку и тем самым снизить процент отбраковки. Сейчас система проходит «боевое крещение», пока рано говорить о точных цифрах, но результат нововведения уже заметен. В планах разработать алгоритм «усиленного» распознавания кодов с восстановлением сетки и дообучить нейросеть на новых кейсах с производства. Весьма вероятно, что подобный способ работы с распознаванием маркировки решил бы и проблему распознавания на кассах супермаркетов (разумеется, при наличии доступа к аппаратной части сканера).
И напоследок проведу небольшой ликбез, почему нейросеть сразу не распознаёт код. Ответ тут прост — она не может, ну по крайней мере пока что. Мне сложно представить, как можно натренировать искусственный интеллект так, чтобы он «в лоб» распознавал DM коды, в которых заложена определенная математика. Нейросети отлично справляются с понятной человеку информацией: OCR например — где всё однозначно, А это А, а слово яблоко это я6л0к0 (шутка). В то время как DM код невозможно прочитать в таком режиме — изменение даже одного символа в его информации влечёт значительные перестановки его точек. Такая перестановка точек крайне мешает в предсказании данных для нейросети, делая применение нейросети для распознавания бессмысленным занятием. По этой причине и был использован данный подход, где нейросеть лишь инструмент, помогающий обычному алгоритму распознать информацию.
Благодарю за прочтение! Буду рад вашим комментариям, критике и советам. А если у вас есть проекты, где нужна экспертиза в CV, пишите в телеграм, чтобы обсудить возможное сотрудничество.