Рассказываем о кейсе внедрения компьютерного зрения в ресторане быстрого питания. Ценность кейса для бизнеса: запись с камеры длиной в 24 часа превращается в 30-секундный эпизод, который проверяющий может разобрать за минуту.
В ресторане быстрого питания есть два источника данных: касса и камера. Касса знает, что продали. Камера видит, что положили на поднос. Не всегда касса и камера фиксируют одно и то же.
Из‑за этого разрыва возникает масса неприятностей: недостачи, жалобы покупателей на забытые блюда и споры о реальном времени обслуживания. Получается, что бизнес QSR (Quick Service Restaurants) становится не таким уж быстрым и гостеприимным, как должен быть.
Для нашего клиента из QSR мы собрали систему, которая связывает чеки с видеопотоком и нарезает для проверяющего готовые эпизоды с ошибками.
По причине NDA, все фотографии и схемы в статье созданы искусственно и служат только примерами: это не съёмка ресторана заказчика и не снимки рабочего интерфейса. Названия блюд, номера заказов и время на иллюстрациях условные. Числовые результаты испытаний взяты из материалов проекта.
А что если просто взять и посмотреть записи камер?
Поиск ошибки в кадре — это, порой, квест. Ну или мини‑расследование.
Выбрать момент сборки
Проследить за нужным подносом
Восстановить его состав
Найти подходящий чек
Сверить позиции
Если рука закрыла стакан — мотаем назад
Если рядом собирали похожий заказ — убедиться, что смотришь на тот самый поднос.
Вручную можно разобрать конкретный случай. Системно контролировать так всю смену уже сложно.
2 контрольные зоны и нюансы
Камера установлена сверху, потому в кадре могут оказаться и соседняя стойка, и витрина, и гость, который уже забрал поднос и стоит рядом. Само появление подноса в кадре не равно тому, что его содержимое нужно распознавать.
Решили, что перед запуском распознавания оператор отмечает рабочую область, то есть зону сборки. Всё, что снаружи, система не видит, это защищает от получения событий, которые не имеют отношения к сборке.
Вторая важная зона появилась чуть позже, это зона выдачи — участок, куда собранный поднос выставляют для гостя: вторая полка, край стойки.
Два нюанса, которые добавляют «специй» к «мясу» кейса.
-
Рамка распознавания от кадра к кадру всегда немного дрожит. Если поднос поставить точно на край, система завалит десятками уведомлений в секунду. Поэтому мы ввели пороги срабатывания:
-
поднос считается вошедшим в зону выдачи, когда внутрь попало больше 45% площади его рамки;
-
поднос считается вышедшим, если внутри рамки осталось меньше 30%;
-
в обоих случаях требуется три кадра подряд.
-
-
Когда программа впервые видит поднос сразу внутри зоны выдачи — это специфичный случай: поднос появился внезапно, значит, мы упустили его где‑то ранее. Такой случай пишется в журнал отдельным предупреждением. Это сигнал не ресторану, а нам.
Научить нейросеть распознавать меню
Не получится. Меню и изображение устроены по‑разному.
Для кассы разные напитки= разные товары.
Для камеры сверху это два одинаковых белых стакана с одинаковыми крышками.
Для камеры закрытая коробка = коробка с неизвестным содержимым. А соус, спрятавшийся за стаканом, не виден вообще.
Потому загрузить в ИИ меню ‑не решение вопроса. Мы работали со списком того, что можно различить по видео сверху. Получилось 26 групп, включая сам поднос: коробки бургеров нескольких видов, роллы, картофель фри, картофель по‑деревенски, баскет фри, баскеты с курицей, напиток в стакане, бутылка, бабл ти, горячий напиток, десерты, мороженое. Обучающий набор — 3 371 изображение.
Не все группы дались легко. Хуже всего себя показали десерты и бутылки: примеров мало, а между собой они похожи. Лечили дополнительной разметкой, чтобы дать системе больше подходящих примеров для обучения.
Откатываемся назад
Пустой поднос
Сотрудник кладёт ролл
Ставит стакан
Ставит упаковку картошки фри
Рука сотрудника проходит над подносом и закрывает стакан.
Если сравнить с чеком данный кадр с перекрытым стаканом, получится недостача.
Но ведь напиток никуда не делся, через полсекунды рука исчезнет из кадра, и тот же заказ снова будет выглядеть правильным.
Мы перестали считать отдельный кадр ответом. Каждый поднос получает постоянный номер и собственную историю наблюдений ‑это всё, что программа знает о подносе с момента появления.
Последний кадр — худший кадр из всех. Поднос уже наполовину за границей, его закрывает сотрудник, детали смазаны движением.
Поэтому откатываемся назад. Берём последние 5 секунд истории и ищем в них самый спокойный и не смазанный отрезок: тот, где соседние кадры больше всего совместимы друг с другом по составу подноса. По нему выявляем:
-
блюдо попадает в итоговый состав, если его видно не меньше чем в 60% кадров отрезка;
-
количество порций считаем по медиане, а не по пиковым скачкам. Если на одном кадре нейросети померещились две картошки вместо одной, алгоритм отбросит эту аномалию и не задвоит позицию в отчете.
По этому же отрезку считаем надёжность:
-
От 80% совпадений состава на кадрах — высокая надежность.
-
От 50 до 80% — средняя.
-
Ниже 50% — ненадежная. Такие «сомнительные» подносы мы вообще не пускаем на автоматическую сверку с чеком, чтобы не генерировать ложные инциденты
Поднос, попавший в кадр меньше 15 раз, система игнорирует. Привязка идет строго к количеству кадров (разбираем каждый третий), а не к таймеру. Так алгоритм перестает собирать «фантомы» — предметы, на секунду появившиеся с краю стола. Да, часть заказов таким образом мы упускаем из проверки. Поэтому само по себе снижение ложных тревог ничего не значит. Оценивать качество нужно в связке с другой метрикой: какую долю заказов система смогла взять в работу
Привязка блюд к подносам
Мы связываем блюдо с подносом по центру его рамки: если центр коробки или стакана попал внутрь рамки подноса — блюдо относится к подносу. Вариант «считать долю перекрытия» мы отвергли: рамки соседних подносов часто задевают и перекрывают друг друга.
Дальше исключаем дубли блюд. Каждая лишняя рамка — это лишняя порция в отчёте. Поэтому:
-
если рамки одной порции перекрываются больше чем на 50%, алгоритм оставляет ту, где процент уверенности выше. Так одна реальная порция не задваивается в отчете.
-
если нейросеть нарисовала рамку подноса внутри другой такой же рамки, меньшая удаляется. Система не посчитает один заказ дважды
Объекты, которые алгоритм нашел, но не смог привязать к конкретному подносу, собираются в отдельный лог. Если таких предметов слишком много, скорее всего, оператор изначально некорректно разметил рабочую зону.
Поднос переставили — и это уже другой поднос
Сотрудник заканчивает сборку и переставляет поднос на полку выдачи
Поднос закрывает рука
Поднос снова в кадре, но заметно правее.
Для программы, которая связывает подносы между кадрами по положению рамок, это новый объект: новый номер, пустая история, ноль блюд.
Таким образом, собранный заказ распадается на два ложных инцидента: «брошенный недособранный поднос» на столе и «пустой поднос» на выдаче, к которому привязан неизвестно откуда взявшийся набор блюд.
Чтобы алгоритм не терял поднос из‑за таких движений, мы решили, что система не должна опираться только на его координаты. Теперь при сопоставлении объекта между кадрами система смотрит на два признака: насколько сместилась рамка и совпадает ли то, что на ней лежит. Если подносы стоят вплотную, решающим фактором становится состав.
От случайных разрывов трекинга защищает функция «воскрешения». Когда поднос на мгновение пропадает за рукой сотрудника, программа перед созданием нового профиля проверяет соседнюю зону (в радиусе 200 точек). Находит объект с тем же составом — возвращает ему старый номер и всю историю наблюдений. При восстановлении трека состав учитывается с большим весом, чем расстояние: поднос при переносе смещается, а набор позиций на нём сохраняется.
«Заказ собран»
Найти момент завершения сборки через простые правила не получается.
Если ориентироваться на последний кадр, где виден поднос, получится, что готовый заказ может еще минуту стоять на полке.
Если привязываться к последнему увиденному предмету, отметку может нарушить случайное движение руки над столом.
Мы определяем финал сборки так: программа анализирует всю историю подноса, находит финальный состав и идет по кадрам назад до точки, где этот набор впервые зафиксировался и больше не менялся.
Кроме того, фиксируется, когда каждое блюдо появляется на подносе, в результате чего виден весь ход сборки, к примеру,
ролл — в 13:08:12,
напиток — в 13:08:40,
картофель — в 13:09:00.
Это позволяет увидеть на каком этапе возникла задержка (если она возникла)
Момент готовности считаем по двум событиям:
-
на подносе появился финальный состав;
-
поднос вошёл в зону выдачи.
Берём более позднее из них, чтобы избежать ситуации, когда система поставит отметку «готово» раньше, чем заказ фактически будет на выдаче.
Если зона выдачи не размечена, остаётся только момент формирования состава. Но это не время передачи заказа гостю: камера может не видеть соус, салфетки или сахар, а готовый поднос ещё некоторое время стоять на стойке.
Поэтому разделяем эти события: оплата, готовность заказа, отметка на кухонном экране и фактическая выдача — разные временные точки, а нам для сравнения ресторанов и смен важно считать один и тот же показатель по одной методике.
Синхронизация времени с кассой
Сначала мы считали время кадра от начала записи: время старта файла плюс смещение внутри видео. На суточной записи к концу дня расхождение между расчётным и реальным временем достигло примерно 38 минут. Это критично.
Регистратор не записывает участки без движения. Из‑за этих пауз временная шкала файла не совпадает с реальным временем. Для синхронизации с кассой система считывает таймкод непосредственно с изображения:
-
ищет его по всей верхней полосе кадра: на разных камерах положение отличается;
-
проверяет пять соседних кадров и берёт срединное значение времени;
-
обрабатывает переход на следующие сутки, если запись идёт через полночь.
Частоту кадров система тоже проверяет сама:
-
значение в метаданных может не совпадать с фактическим: например, указано 60 кадров/с, а реально запись идёт примерно с 20;
-
в некоторых файлах частота меняется по ходу записи;
-
если ориентироваться только на метаданные, номер кадра начинает расходиться с реальным временем, а нужный фрагмент на длинной записи может сместиться на десятки минут;
-
фактическую частоту система рассчитывает по временным отметкам на выборке до 30 тысяч кадров;
-
если файл не удаётся корректно разобрать этим способом, его параметры проверяются отдельно.
Без этого корректно синхронизировать видео с кассовыми данными нельзя.
Как сопоставляем чек и состав подноса
Мы начали с этого тезиса: касса и камера описывают один заказ по‑разному. Поэтому перед сопоставлением кассовые данные приводятся к тем же группам, которые распознаёт система:
-
наборы раскладываются на отдельные позиции;
-
сокращения приводятся к единому названию;
-
вкус, объём и другие признаки, которые нельзя определить по видео, исключаются;
-
количество каждой позиции сохраняется.
Например, в чеке две порции картофеля, и система должна подтвердить именно две, а не просто наличие картофеля на подносе.
В проверку попадают только те позиции, которые камера может увидеть и различить. Соусы, салфетки и другие скрытые или визуально неразличимые позиции в сравнение не включаются, чтобы не создавать ложные расхождения.
Как система связывает поднос с заказом
В ресторане в одно время могут собираться несколько заказов с одинаковым составом. Поэтому система сопоставляет поднос с чеком по двум параметрам:
-
совпадение состава;
-
разница между временем оплаты и готовности.
Для каждой пары рассчитывается оценка. Чем ближе состав и время, тем она выше. Как параметр сопоставления используется интервал в ~ 5 минут
После расчёта система выбирает пары с максимальной оценкой. Один чек связывается только с одним подносом, один поднос — только с одним чеком. Пары с низкой оценкой остаются несопоставленными.
Эпизоды, которые не укладываются в эту схему: два одинаковых заказа, оплаченных почти одновременно, или один заказ на нескольких подносах — отправляются на проверку.
Как формируется эпизод для проверки
Для каждого подноса система вырезает короткий фрагмент: 5 секунд до его появления и 5 секунд после выхода из зоны. Нужный поднос отмечается красной рамкой по сохранённой траектории.
Между обработанными кадрами положение рамки интерполируется. Если в траектории слишком большой разрыв, на этом участке рамка не показывается.
Дальше система формирует события по нескольким сценариям:
-
Лишняя или заменённая позиция. На подносе распознана позиция, которой нет в чеке, либо вместо ожидаемой группы обнаружена другая. Причиной может быть ошибка сборки, неверное сопоставление заказа или плохой обзор камеры. Система фиксирует само расхождение.
-
Недостающая позиция. Позиция есть в чеке, но система не подтвердила её на подносе. В событии сохраняются недостающие группы и степень совпадения состава. Если такие сигналы повторяются, их можно использовать для приоритизации проверки.
-
Превышение норматива. Время от оплаты до зафиксированной готовности превысило заданное значение. Этот показатель относится именно к сборке. Для оценки времени передачи заказа гостю нужен отдельный момент выдачи.
-
Поднос или заказ без пары. Поднос не удалось сопоставить с чеком либо для оплаченного заказа не нашлась соответствующая сборка. Причина может быть в неполных кассовых данных, сборке вне размеченной зоны или ошибке сопоставления.
Проверяющий смотрит сам эпизод, подтверждает или отклоняет событие.
Выбор модели
Мы сравнили три модели на одном наборе изображений, при одинаковом разрешении 1280 × 1280, на видеокарте RTX 3090 Ti, после прогрева, по 100 повторений на каждую конфигурацию.
|
Модель |
Качество распознавания |
Время обработки |
|---|---|---|
|
YOLO26x |
0,865 |
37 мс |
|
RT‑DETR‑x |
0,869 |
67 мс |
|
D‑FINE‑M |
0,886 |
34 мс |
Таблица 1. Результаты внутренних испытаний проекта; это не независимая проверка и не сравнение на всех возможных задачах. Чем выше mAP50–95, тем лучше сводное качество обнаружения и определения границ объектов. Чем меньше время на кадр, тем быстрее модель в этом испытании.
Выбрали D‑FINE‑M: лучшее качество и при этом самое быстрое время на кадр..
Что означают метрики
mAP50–95 = 0,886 — это качество распознавания объектов и их границ. Этот показатель не означает, что система правильно проверяет 88,6% заказов.
То же относится к полноте 0,993: она характеризует работу модели на тестовой выборке, а не долю найденных ошибок сборки.
Производительность.
При пакетной обработке восьми кадров D‑FINE‑M показала 53 кадра/с, YOLO26x — 29 кадров/с.
Скорость модели нельзя напрямую переводить в количество камер на одной видеокарте. При равномерном делении 53 кадров/с на восемь потоков получается около 6,6 кадра/с на камеру, без учёта:
-
чтения видео;
-
трекинга подносов;
-
распознавания времени;
-
сопоставления с кассовыми данными;
-
формирования событий.
Поэтому количество камер на один вычислитель определяется по производительности всей системы, а не только нейросети.
Как проверяли модель после переноса в GPU‑движок
Обработка суточной записи занимает несколько часов, поэтому для ускорения инференса модель перевели в оптимизированный GPU‑движок, и скорость обработки выросла:
-
один кадр — 15,6 мс вместо 29,1 мс;
-
четыре кадра — 58,1 мс вместо 101 мс.
После переноса результаты стали отличаться от исходной модели: рамки объектов стали смещаться..
Прогнали одинаковые данные через исходную модель и движок и сравнили результаты по слоям. Расхождение появлялось во втором слое декодера — в операции выборки по координатам, которую движок обрабатывал иначе.
Проблемную операцию выборки по координатам заменили на эквивалентную реализацию, которую движок обрабатывал корректно. После исправления расхождение между отсортированными оценками исходной модели и GPU‑движка не превышало 0,00005.
Это замеры на рабочей станции, не на сервере. Исправленный граф проверяли только в обычной точности. Режим половинной точности отдельно не тестировали и в запуск не включали.
Выводы
В контроле сборки заказов детекция блюд — только начало. Реальный бизнес результат достижим тогда, когда конкретный поднос связан с конкретным чеком, восстановлено фактическое время сборки и по расхождению можно открыть короткий видеоэпизод.
Для ресторанной сети QSR это меняет формат контроля. Вместо просмотра записей появляется поток конкретных событий, с которыми уже можно работать, не возвращаясь к первоисточнику (видео архив)..
Следующий этап работы оценить эффект в масштабе ресторанной сети, а именно:
-
точность сопоставления «поднос — заказ»;
-
долю подтверждённых сигналов;
-
количество пропущенных ошибок;
-
время проверки смены до и после внедрения;
-
экономический эффект на подтверждённых расхождениях.
Благодарим наших партнеров за то, что представили этот кейс публично на «Форуме ИТ и Инноваций в ритейле» (IT Konnekt).
Примечания
Съёмка ресторана заказчика, снимки рабочего интерфейса, реальные номера заказов, даты и время в публикации не используются. Название заказчика не раскрывается.
Пояснение метрики mAP50–95 приведено по открытой документации Ultralytics и использовано только для объяснения показателя, а не как подтверждение результатов проекта.
Числовые результаты взяты из материалов проекта
Автор: NeuroKirKorov


