«Мне нужно чтобы всё распозналось, а никто не может это сделать!» С таким почти что криком души к нам с коллегой обратился один из производителей мороженого, на линии которого маркировка никак не хотела распознаваться. Конечно же, мы приняли этот вызов. Почему не каждая маркировка легко считывается, как мы улучшили алгоритм распознавания маркировки «Честный знак» для мягкой упаковки мороженого и что из этого получилось — читайте дальше.

Наверняка многие из вас пользовались кассами самообслуживания в супермаркетах и пробовали отсканировать DataMatrix код «Честный знак» с упаковок мороженого, творога, молока, глазированных сырков и прочих продуктов в тонкой и гибкой упаковке. Согласитесь, редко получается сделать это с первого раза. А теперь представьте такую ситуацию на производстве, где нужно массово агрегировать всю продукцию с маркировкой... а она не распознаётся! Именно такую проблему мы старались решить в одном из наших кейсов: работает конвейер, на котором уже готовая, упакованная в БОПП-плёнку, продукция идет в хаотичном положении, но кодами «Честный знак» вверх. Проходя участок сканирования, она попадает на групповую упаковку в картонный короб по несколько штук. И для дальнейшей логистики очень важно знать какие именно коды маркировки находятся в конкретной упаковке.

Итак, перед нами стояла задача —  отсканировать максимальное количество кодов (т. е. распознать всю маркировку с упаковок мороженого на конвейере), а те, что не отсканировались, отбраковать (в нашем случае сбросить для повторного, ручного сканирования или перемаркировки).

Пример линии групповой упаковки мороженого
Пример линии групповой упаковки мороженого

Почему код не распознаётся с первого раза

На это есть две причины. Первая — низкий грейд кода. Подробнее об проблемах печати можно прочитать здесь. Вторая — даже когда код напечатан идеально, с грейдом А, всё может подпортить алгоритм распознавания, который не увидит код. 

Если пойти в историю и задаться вопросом «Для чего придумали код DM?», то окажется, что код DataMatrix используется, в первую очередь, для маркировки изделий на производстве с целью прослеживаемости. То есть код априори должен наноситься на твердую поверхность: чугунный блок двигателя, лист стали, корпус процессора или на бирку изделия. И максимальные его повреждения в процессе жизни — смазали, покоцали или закрасили. А вот его геометрия всегда прямоугольна и сетка всегда ровная. От этого и алгоритм его распознавания рассчитан на идеально ровное, твердое размещение кода. Но как вы понимаете, упаковка мороженого таковой не является.

Пример нанесения кода DataMatrix лазером
Пример нанесения кода DataMatrix лазером

Как работает алгоритм распознавания DM:

  1. Он находит так называемую L-границу кода, по ней понятна ориентация кода и его границы.

  2. Определяются тактовые ячейки, для алгоритма они задают сетку, по которой считывается код.

  3. Из зоны хранения данных кода берется графическая информация, по полученной сетке она разбивается на бинарную матрицу 0 и 1.

  4. Применяются различные алгоритмы восстановления данных (так как не всегда однозначно по сетке удается определить значение точки) и код преобразовывается в текстовую информацию.

    Этапы распознавания кода маркировки
    Этапы распознавания кода маркировки

Что пошло не так?

Проблема с кодами начинается на мягкой упаковке, где место нанесения кода физически может деформироваться. В результате на сканере кода получаем вот такую картинку, которую, естественно, алгоритм не может распознать. Да, он видит что-то похожее на код, но всячески отказывается с ним работать.

Пример искаженного кода маркировки с грейдом B
Пример искаженного кода маркировки с грейдом B

Это как раз наш случай. К тому же небольшие трудности вызывали блики на упаковке, но с помощью правильно подобранной оптики и света удалось быстро это решить. А вот проблему помятой упаковки с кодом мы решили отбраковкой с применением нейросети.

Реализация этого решения выглядела следующим образом:

  1. Натренировать нейросеть класса Semantic Segmentation с целью выделить границы кода. На выходе получим ломаный контур кода, но он даст нам понять, как именно искажён код.

  2. Математически «развернуть» искажённый код до состояния квадрата (благо, коды «Честный знак» всегда квадратные, хотя и имеют разное количество модулей).

  3. Попробовать распознать растянутый код стандартным алгоритмом чтения DM.

  4. Если не получится распознать, то по выровненной L стороне, зная шаг и размер кода, попытаться восстановить сетку кода и его логические значения и передать на распознавание алгоритму уже готовую бинарную матрицу. (Пока не реализовал, оставил на будущее)

Пример определения модулей по сетке кода классическим алгоритмом распознавания маркировки
Пример определения модулей по сетке кода классическим алгоритмом распознавания маркировки

Цель, стек и план разработки MVP

Цель. Клиенту было важно показать снижение процента отбраковки (ручного сканирования) в идеале до 2%. Сроки поджимали, так как были значительные затраты на дополнительных операторов линии.

Стек. Разработку вели на Python, а для создания пользовательского интерфейса использовали модернизированный GUI другого проекта PyQT, библиотеку машинного зрения и нейронку от MVTec Halcon (её мы часто используем для распознавания Datamatrix, а работать в рамках одного пакета и с камерой, и с MV и DL весьма удобно).

План. Выезд на площадку + съемка данных, пара недель на MVP, тест-прогон, боевое тестирование на производстве, доведение по ходу работы до бета-версии.

Теперь о самом интересном, о разработке. 

Первый этап — обучение нейросети

Сам процесс разметки и обучения нейросети происходил в Deep Learning Tool. Это весьма удобное приложение, в котором получается готовая, натренированная нейронка со всеми метриками. Первый объем снимков с кодами был довольно скромным — 332 кадра искривлённого кода, размеченных вручную.

Конфигурация первого датасета и нейросети
Конфигурация первого датасета и нейросети

Однако первая попытка натренировать нейросеть показала вполне неплохие результаты: она с лёту находила код и весьма хорошо справлялась с определением его границ.

Результат определения контура кода
Результат определения контура кода
Процесс тренировки
Процесс тренировки

Сделав авторазметку по имеющейся базе читаемых кодов DM, отснятых на производстве (взяв за верную границу рамку кода), получили неплохой датасет на тысячи кодов разного форм-фактора. Дополнительно пришлось сделать предобработку кадров, т. е. кадрировать участки с кодом с целью повысить рабочее разрешение и не обучать нейросеть неделю. Так мы получили вполне боевую нейронку с приемлемым качеством отрисовки границы кода и хорошей производительностью.

Результат определения контура кода после дообучения
Результат определения контура кода после дообучения

Для подтверждения нечитаемости кода запустили на смартфоне ПО с одним из лучших алгоритмов распознавания маркировки — Cognex Barcode Scanner. Результат ожидаемый - маркировка не видна

Искривлённый код ожидаемо не хочет считываться даже лучшими на рынке алгоритмами распознавания
Искривлённый код ожидаемо не хочет считываться даже лучшими на рынке алгоритмами распознавания

Второй этап — разработка алгоритма расправления кода

Данный алгоритм должен вырезать код по контуру от нейросети, равномерно растянуть изображение, превратив его в квадрат. Кто знаком с теорией обработки изображений, узнает в этой задаче применение полиномиальных преобразований. В нашем случае оно было обратным: из искаженного кадра с неизвестной кривизной, приведенным к экспонентонициальным кривым нужно было получить прямоугольник.

Примечание: данное упрощение стало золотой серединой в производительности и качестве для нас, так как выравнивать весь контур кода затратно по времени, а сводить задачу к выравниванию разностороннего четырехугольника слишком грубо. А описать геометрию кода четырьмя экспонентами по "нейросетевому" краю, и от них выравнить код — оказалось самое оно.

Пример задачи обратных полиномиальных преобразований
Пример задачи обратных полиномиальных преобразований

Дополнительно под код добавляется белая квадратная подложка, облегчающая его распознаванаие классическим алгоритмом.

Тестирование

Задача тестирования — понять, достаточно ли обучилась нейросеть, снять метрики и получить новые данные для дообучения нейросети и усовершенствования алгоритма. Тестирование было в два этапа: в лаборатории и на производстве.

Тестирование в лаборатории

Для тестирования в лабораторных условиях мы собрали небольшой стенд, состоящий из следующего оборудования:

  • небольшой конвейер,

  • камера машинного зрения с объективом,

  • кольцевая подсветка,

  • фотодатчик,

  • мини-ПК с развернутым ПО.

В качестве объекта тестирования пошло в ход всё, что было в холодильнике в аналогичной мягкой упаковке (творог, сырки, мороженое), а также нанесенные на фольгу коды DataMatrix. Ниже приведу пример работы алгоритма выравнивания кода по контуру. 

Пример снимка кода с творожного сырка. Маркировка не читаема обычным алгоритмом.
Пример снимка кода с творожного сырка. Маркировка не читаема обычным алгоритмом.

Код с данного снимка имеет минимальные искажения, однако упаковка повернута под большим углом относительно камеры, делая код нечитаемым. Чтобы гарантированно распознать такой код классическим алгоритмом, нужен массив разнонаправленных камер. Но это не наш метод, нейросеть без проблем нашла код, а алгоритм "развернул" его лицом к нам:

Пример успешного распознавания кода после его "разворота"
Пример успешного распознавания кода после его "разворота"

Это достаточно легкий случай, но даже такая реализация уже значительно повышает процент распознавания.  Однако есть к чему стремиться — конечной целью нашей разработки будет распознавание кода со значительно искажённой геометрией путем восстановления его смятых участков из стереоизображения и чтением его модулей нейросетью. Пример такого кода на фото:

Пример сильно замятой упаковки с нечитаемой маркировкой. Количество дефектных модулей у него минимально, поэтому шанс обработать и распознать такой код есть!
Пример сильно замятой упаковки с нечитаемой маркировкой. Количество дефектных модулей у него минимально, поэтому шанс обработать и распознать такой код есть!

По итогам тестирования, смятия упаковки и прогонки более 1000 кодов вышли на следующие метрики: 

  1. Максимальное время распознавания кода (от получения ПО снимка до выдачи информации о коде) — 340 мс. Сделаем скидку на мини-ПК — не для этого он, но что имеем, как говорится.

  2. Среднее время распознавания — 184 мс.

  3. Эффективность обнаружения DM кодов — 99.3% со средней ошибкой по геометрии в 8%.

  4. Эффективность распознавания — 73%. Важно сказать, что некоторые коды сминали слишком сильно, далеко от реальных ситуаций, но тем и интереснее.

Доработки по результатам тестирования свелись к дообучению нейросети на новых, размеченных данных. По итогам повторной прогонки на базе отснятых снимков ошибка по геометрии упала до 5%, а эффективность распознавания выросла на те же 3%. Также мы задумались над использованием иных способов подсветки бликующих поверхностей, рассматривали поляризационные светофильтры и коаксиальный свет. Но в итоге попробовали совсем новый для меня вариант купольного света — туннельная подсветка. По итогам тестирования такой подсветки получилось полностью пересветить блики и бонусом — закрыть зону съемки от постороннего света. 

Туннельная подсветка, изготовленная с применением дендрофекальных технологий. Прототип, не продаётся
Туннельная подсветка, изготовленная с применением дендрофекальных технологий. Прототип, не продаётся

Такая подсветка заменяет купольную подсветку на конвейере, обеспечивая равномерную засветку всей упаковки. Благодаря данной подсветке мы можем получать снимки блестящей упаковки без бликов.  

Пример фото блестящей упаковки в световом туннеле. Минимальные отблески хоть и присутствуют, но чтению информации они не мешают.
Пример фото блестящей упаковки в световом туннеле. Минимальные отблески хоть и присутствуют, но чтению информации они не мешают.
Та же упаковка, но уже при офисном освещении.
Та же упаковка, но уже при офисном освещении.

Тестирование на производстве

Тестирование на производстве было более основательным. Мы использовали следующее оборудование:

  • Три камеры машинного зрения, расположенные аркой, с шагом в 45 градусов над конвейерной лентой.

  • Туннельная подсветка — собственная разработка, позволяющая «засветить» упаковку полностью, избежав блика. Выполнили из матового металла с несколькими светодиодными арками из COB светодиодной ленты.

  • Фотодатчик и энкодер, позволяющие синхронизировать съемку и скорость конвейера, тем самым получаем только заведомо информативные кадры.

  • Пневматический отбраковщик — готовое покупное изделие. 

  • Контроллер вход-выход для управления отбраковщиками и сигнализацией.

  • Шкаф с промышленным ПК и сенсорным монитором. 

В настоящий момент система находится в боевом тестировании, а параллельно мы получаем с неё новые данные о нераспознанных кодах и дообучаем алгоритм. Планируем довести подобное тестирование до 60 рабочих дней и в последующем снять метрики для производства и выкатить рабочий релиз.

Итого: даже на данном этапе реализации проекта нейросеть хорошо помогла нам распознать проблемную маркировку и тем самым снизить процент отбраковки. Сейчас система проходит «боевое крещение», пока рано говорить о точных цифрах, но результат нововведения уже заметен. В планах разработать алгоритм «усиленного» распознавания кодов с восстановлением сетки и дообучить нейросеть на новых кейсах с производства. Весьма вероятно, что подобный способ работы с распознаванием маркировки решил бы и проблему распознавания на кассах супермаркетов (разумеется, при наличии доступа к аппаратной части сканера). 

И напоследок проведу небольшой ликбез, почему нейросеть сразу не распознаёт код. Ответ тут прост — она не может, ну по крайней мере пока что. Мне сложно представить, как можно натренировать искусственный интеллект так, чтобы он «в лоб» распознавал DM коды, в которых заложена определенная математика. Нейросети отлично справляются с понятной человеку информацией: OCR например — где всё однозначно, А это А, а слово яблоко это я6л0к0 (шутка). В то время как DM код невозможно прочитать в таком режиме — изменение даже одного символа в его информации влечёт значительные перестановки его точек. Такая перестановка точек крайне мешает в предсказании данных для нейросети, делая применение нейросети для распознавания бессмысленным занятием. По этой причине и был использован данный подход, где нейросеть лишь инструмент, помогающий обычному алгоритму распознать информацию.

Благодарю за прочтение! Буду рад вашим комментариям, критике и советам. А если у вас есть проекты, где нужна экспертиза в CV, пишите в телеграм, чтобы обсудить возможное сотрудничество.

Комментарии (12)


  1. RodionGork
    10.12.2024 20:58

    Натренировать нейросеть класса Semantic Segmentation с целью выделить границы кода. На выходе получим ломаный контур кода

    любопытно, а что эта задача без нейросети не решается?


    1. avsolovyev Автор
      10.12.2024 20:58

      Обычно это и решается поиском на основании патерна статических элементов кода. Классический алгоритм распознавание так и работает. Но в случае сильной деформации - велик риск не найти или потратить непредсказуемое количество времени.

      В случае нейросети - появляются зоны вероятной схожести с обученными данными (причем достаточно быстро), зная точно что код на фото только один, и он примерно ХХХ пикселей по площади - становится намного проще их отфильтровать и взять контур кода, который бы на 99.9% был именно кодом, а не чем-то на него похожим.


  1. Wesha
    10.12.2024 20:58

    Использовать не L-код (который, как было отмечено, предназначен для размещения на твёрдых поверхностях), а тот, который с самого начала предназначен для гибких? Да не, ерунда какая — давайте будем георически преодолевать проблему, которую создали себе сами!


    1. avsolovyev Автор
      10.12.2024 20:58

      +1

      Мне изначально очень нравилась идея RFID меток: набрал тележку с таким маркированным товаром, вывез её через рамку и карточку приложил - и всё куплено. Никаких тебе штрихкодов, касс, кассиров не надо... Но реальность выглядит немного иначе)


      1. shornikov
        10.12.2024 20:58

        Ага. Непонятна стоимость итоговая. Может дублирование rfid-ом дешевле будет.
        И вообще, в рамках пиления и воровства бюджетов - всё переделать на rfid - это же золотое дно (Может это нам на новый год?).


    1. StepanovAlex
      10.12.2024 20:58

      Только вот, что это за код для изогнутых поверхностей?


      1. Wesha
        10.12.2024 20:58

        что это за код для изогнутых поверхностей?

        (Участливо:) А, в гугле забанили? Примите мои соболезнования!


        1. StepanovAlex
          10.12.2024 20:58

          (Участливо) Как интересно, PDF417 лучше читается на мятой и блестящей упаковке чем DM? А на чем основано такое мнение?


          1. Wesha
            10.12.2024 20:58

            Потому что это, условно говоря, набор одномерных кодов, расположенных один под другим, а с чтением одномерного кода с помятой упаковки проблемы редко возникают.

            А на «блестящей упаковке» печатается прямоугольник белой краской, а уже на нём — код.


  1. orekh
    10.12.2024 20:58

    Странно, что статьей рассмотрены восстановление геометрии кода нейросетью + выпрямление классическим алгоритмом, и полное декодирование данных нейросетью (как фантастика), но не промежуточный вариант где нейросеть на выходе давала бы datamatrix с исправленной геометрией


    1. avsolovyev Автор
      10.12.2024 20:58

      Я сейчас пытаюсь это реализовать, но пока не нашёл способ, который бы надёжно работал. Буду признателен за любые идеи, которыми вы можете поделиться!


      1. orekh
        10.12.2024 20:58

        Сам нейросети не обучал, но вообще выглядит очень похоже на Stable Diffusion, который обучается сначала подачей на вход синтетических изображений DataMatrix с минимальными искажениями, а потом с постепенным увеличением шума / перспективного наклона / прочих трансформаций, пока не сможет работать с реальными изображениями.