Computer Vision позволил создать принципиально новые продукты и механники в многих областях жизни: умный город, беспилотный транспорт, аналитика производств.То же самое произошло и с супермаркетами: “оценка длины очереди”, “оценка загруженности зала”, “оценка загруженности полок товарами”, “проверка выкладки”, “проверка качества уборки”, “проверка ценников” и многое-многое другое это теперь автоматизированные задачи.В этой статье я хочу рассказать про общие принципы распознавания товаров. Эти алгоритмы необходимы для проверки выкладки, заполненности полок, контроля остатков, умных касс и других задач.Так получилось что за последние 7 лет мы были вовлечены в решение и консультирование по большинству таких задач, так что накопилось много интересного опыта. Задача распознавания товаров на полках содержит в себе несколько существенных математических проблем: Товары могут быть расположены близко друг к другу Товары могут заслонять друг друга Каталог товаров может содержать десятки тысяч элементов Товары постоянно добавляются и исчезают. Новые вкусы, сезонные предложения, и.т.д. Классы скорее всего не сбалансированы. При сборе датасетов могут быть классы где десятки тысяч примеров и классы где единицы примеров.  Съемка происходит в сложных условиях: ограниченное освещение, сложные ракурсы Можно ли решать эти задачи одной нейронной сетью? В теории да. Помните, была такая Yolo9000? Сейчас так можно сделать через трансформеры. Но я ни разу не видел чтобы кто-то так делал. Слишком сложно балансировать датасет. Обычно задачу разбивают на две основных части: Детекция. При этом все товары обычно относят к единому классу.  Классификация найденных  товаров. Плюс, почти в любом проекте появляются ещё два дополнительных класса задач: Сети оценки качества Постобработка  Но окончательный выбор сетей и логики должен осуществляться исходя из задачи. О чем поговорим чуть позже Впервые с задачей распознавания товаров на полках мы столкнулись в 2016 году. На тот момент только появились анкерные детекторы по типу SSD и Yolo-v1. Но анкерные детекторы работали достаточно плохо когда в одной области может быть много мелких объектов.  До 2016 года мы отказывались от этой задачи, так как не были уверены что сможем получить продуктовую точность.  Но внезапно, я натолкнулся на статью которая пыталась явно бороться с плотной упаковкой объектов: “End-to-end people detection in crowded scenes”. В статье вместо каждого анкера была отдельная рекуррентная сеть, которая могла выдать большой объем детекций.  Статья была красивой и хорошо работала. Пришлось правда переписать все с нуля, так как она была основана на своем фреймворке. Но на тот момент результат детекции мы получили значительно лучше чем все остальное что пробовали. Как решать эту задачу сейчас?  В целом, большая часть современных state-of-art детекторов работает. Я видел примеры как у людей Yolov5x работала и давала удовлетворительное качество детекции. Но он обычно не отрабатывал пакеты и плотно уложенные объекты. При этом если цель - распознать какую-то простую выкладку (бутылки, бытовую химию, косметику) - то его может хватить Если вы хотите работать с сложными случаями и получить дополнительную точность когда объекты могут пересекаться, то имеет смысл обратить внимание на модели работающие с толпой и плотными объектами: https://paperswithcode.com/sota/object-detection-on-widerperson https://paperswithcode.com/task/crowd-counting https://paperswithcode.com/sota/object-detection-on-crowdhuman-full-body  https://paperswithcode.com/sota/dense-object-detection-on-sku-110k (вот эта задача именно про товары на полках!), но на мой взгляд сетки из первых пунктов дают качество выше. Если в двух словах современные алгоритмы используют: Итеративные методы выбора гипотез Работу с гипотезами имеющими низкую достоверность Трансформеры для достижения максимальной точности Есть несколько способов классифицировать товары. Если у вас есть несколько стабильных классов которые не меняются (например сигареты или небольшой сет на десятки классов) - проще всего обучить классификатор. Берете вашу любимую timm-model и обучаете. Но на практике все оказывается несколько иначе: Число классов может достигать десятков тысяч Некоторые из классов могут быть не представлены или представлены плохо в вашем датасете На практике часть классов может быстро изменяться Для таких случаев лучше всего работают не классификационные сети, а сети которые могут сгенерировать embedding. Например ReID сети: https://paperswithcode.com/task/person-re-identification  https://github.com/layumi/Person_reID_baseline_pytorch  Если объяснять что такое эмбеддинг в двух словах - это аналог хэша. Чем больше похоже два товара - тем ближе дистанция между их хэшами. Аналогичные подходы используются для того чтобы распознать человека по лицу. Плюсы подхода: Вам достаточно одной картинки чтобы распознавать товар. Конечно, лучше будет если есть 2-3 картинки, но даже по одной обычно работает. Сеть можно обучить один раз. Если изначальный датасет достаточно репрезентативен - переобучение с добавлением 100-200 товаров почти не улучшает качество. Минусы Похожие товары будут иметь маленькую дистанцию. Даже если это разные товары.  Например стиральные порошки с разным ароматом. Товары разного размера но одинаковой формы будут иметь одинаковый класс.  Обычно эти минусы можно компенсировать с продуктовой стороны или со стороны дополнительных алгоритмов, о чем будем говорить ниже. Кстати, NVIDIA выпустила недавно сетки для распознавания товаров - https://developer.nvidia.com/metropolis-microservicesНо на мой взгляд пока что все выглядит слабо. Но я не люблю и DeepStream и Tao. Иногда, кроме сетей которые реализуют классификацию имеет смысл сделать один из следующих алгоритмов: Анализ качества снимка. Если кадр плохого качества - лучше не работать с ним. Иначе качество распознавание упадет.  Для этого проще всего обучить отдельную сетку для анализа качества: нерезкость, пересвет, недосвет, неправильный ракурс. Я предпочитаю решать эти проблемы отдельной сеткой, обученной на проблемных кадрах.  Анализ перекрытости. Если вы фотографируете в автоматическом режиме, или если ваши камеры стоят далеко от полки - в поле зрения могут попасть люди, тележки, паллеты. Лучше иметь отдельную сетку для их детекции. Проще всего обучить сегментационную сеть на целевые классы.  Сшивка. Очень часто в магазинах маленькое расстояние между полками. А для решения продуктовой задачи вам нужно оценивать сразу все что есть на полке. Для этого можно использовать различные алгоритмы сшивки. В реальности, из-за сдвига ракурсов это очень нетривиальная задача. Взять SuperGlue и использовать его - зачастую недостаточное решение.  Анализ размера. Как я говорил выше - одинаковые объекты будут похожи друг на друга. В том числе если это один и тот же товар разного размера. Но размер иногда можно оценить. Например если вы знаете размеры ваших шкафов, или размеры соседних товаров. Это не имеет смысл делать отдельной сеткой, а проще реализовать какой-то логикой. Давайте немного поговорим о том как алгоритмы превращаются в продукт. Что есть продукт? Мне известно несколько задач: Контроль выкладки. В магазин приходит мерчандайзер. Он должен убедиться что на полке стоит 20 товаров X и 10 товаров Y. Мерчандайзер может перепутать количество товаров которые должен поставить. Или перепутать товар. Чтобы убедиться что все правильно: Мерчандайзер делает кадр. Система распознает на нём все товары принадлежащие классам X и Y. Оценивается необходимый объем выкладки Мерчандайзер выкладывает товары на полку. Делает итоговый анализ: сколько появилось новых товаров. Такой подход позволяет сделать систему полностью автоматической. Качество распознавания 1-2 классов детерминированных товаров обычно очень высокая. Но конкретная логика обычно опирается на конкретные граничные условия: какие данные есть, и как устроена процедура выкладки.  Контроль товаров. Используется для парсинга конкурентов и проверка качества выкладки своих товаров. При таком подходе нет априорной информации. Это не позволяет корректно распознавать 99.9% товаров на полках. Есть товары которые лежат боком, есть похожие товары, и.т.д. Если нужна более высокая точность - необходимо добавить human-in-the-loop.  Площадь на полке. Часто не требуется распознавать товары, а достаточно распознавать площадь занятую товаром/классом товаров/брендом. По сути это тот же “контроль товаров”, но обычно можно объединять классы (кока-кола разных размеров и ароматов, и.т.д.).  При этом не требуется высокая точность, и ошибка в несколько процентов обычно не критична.  Автоматическая система контроля ассортимента. Иногда сети устанавливают камеры напротив полки с ассортиментом с высокой циркуляцией. Такая камера позволяет просто контролировать исчезновение товара в области и дать сигнал менеджменту выложить новый товар. Часто при таких задачах не требуется распознавать товар (отсутствие товара - достаточный сигнал). Скорее всего вам понадобиться распознавать ту полку по которой вы работаете (или пользователь должен вводить номер полки) Если товары выложены с пропуском товара/с сдвигом в один товар - обычно это не является нарушением. Поэтому надо делать алгоритмы оценки близости последовательностей (по сути NLP задача с близостью текста).  Парсинг отдельного товара. Используется для распознавания отдельных товаров по базам. Например автоматические кассы, умные тележки, и.т.д. По сути детектор может быть ощутимо проще, но необходим трекинг товаров в поле зрения камеры. Алгоритм распознавания товаров практически идентичный с алгоритмом выше. Распознавание цены. Часто распознавание цены делается в том же модуле который распознает товары. И часто для детекции используется та же нейронная сеть что распознает товары. Но алгоритм работы по ценнику принципиально другой. Если интересно, почитайте мою статью про распознавание номеров, там похожая логика.  Магазины без кассиров. В таких системах распознавание товаров обычно лишь один маленький кусок всей системы. Зачастую распознавание товаров должно быть совмещено с подсчетом их числа. Поэтому камеры устанавливаются в таких местах где это хорошо видно. Например внутри полки. Если это интересно - я делал подробное видео про эту задачу Роботы.  Я не буду фокусироваться на этих задачах, но можно отметить что будущее за роботами которые расставляют товары на полках. Там есть много специфики с картами магазина, SLAM алгоритмами и трекинга. Надеюсь, что наш старатап с управлением роботов рано или поздно дорастет до этих задач. Пока что я видел несколько попыток, но одного универсального решения пока не видел. Имея поток детекций и поток классификаций товара надо на их базе сделать продукт. И для этого обычно нужно прокинуть какой-то мостик, который будет учитывать: Ошибки в модулях распознавания Ошибки в модулях классификаций товаров Ошибки в точке съёмки В Computer Vision мы всегда имеем дело с неполнотой данных (товар не различим), с ошибками алгоритмов (товар задетектирован на лампочке). И решение должно всегда быть одним из следующих: Поменять задачу так, чтобы точность ниже 100% была эффективна для конечной цели (площадь, решения для мерчандайзинга). Использовать более качественные снимки (съемка в близи, умные check-out) Ввести Human-in-the-loop Добавить некоторые априорные данные (планограмма, и.т.д.) которые повысят качество работы и нивелируют ошибку.   Все эти логические элементы могут очень сильно изменять постпроцессинг. Но в общем случае это поиск хешей по базе. Какие трюки тут помогают: Явно прописывать близкие товары (например бренды). И исходя из близости разных брендов выводить достоверность (например 50/50 если это 1.5/2 литра кока-колы). Использовать более одного изображения в базе (например несколько примеров с каждой стороны). Если слишком много примеров это может тоже ухудшить качество.  Использовать знание о том какие товары расположены рядом на полке. Обычно похожие товары выставляют рядом. Это может оптимизировать качество. Не хочу погружаться глубоко в эту часть, но не могу не затронуть. Где делать распознавание? На сервере, на мобильном телефоне, на отдельной плате подключенной к локальной камере? Моя логика обычно следующая. Распознавание на телефоне не позволяет использовать тяжелые детекционные сети. Но качества современных YOLO может хватить если товары имеют хорошую выкладку, а люди аккуратно их фотографируют.  Минус распознавания на телефоне - вам необходимо выгружать базу данных туда. Либо итоговые хэши отсылать на сервер (что нивилирует смысл телефона). Плюс, на телефоне невозможно добавить Hooman in the loop. Серверное распознавание - базовый подход. 90% систем делается именно так. Это позволяет интегрировать в систему дообучение, повысить качество распознавания, отслеживать качество на продакшне.  Распознавание на камерах, на отдельных устройствах - нишевый подход, зависящий от задачи. Например умные тележки или умные кассы. Я почти уверен что за ним будущее автоматизации торговли. Но он проигрывает если мы хотим собирать данные с продакшна. Надеюсь вам было интересно. Есть идеи какую тему описать подробнее? Больше моих статей и видео есть не только на Хабре но и в канале в телеге.   Computer Vision, Machine Learning