Привет, Хабр!

Меня зовут Денис. Хочу рассказать о том, как мы разрабатывали и внедряли кассы самообслуживания для столовых и фудкортов. 

Краткое содержание: 

  • почему распознавать еду сложно (но можно);

  • где мы ожидали получить проблемы, и где они были на самом деле;

  • почему не нужно помогать кассиру делать свою работу;

  • сколько котлет нужно сфоткать для уверенного распознавания;

  • бунт кассиров, бессмысленный и беспощадный;

  • какие проблемы создает товароведу касса самообслуживания;

  • и еще много интересного!

Поехали.

Часть первая. «Давайте автоматизируем кассу!»

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

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

Вот примерно такие очереди.
Вот примерно такие очереди.

Ну вот же! Давайте сделаем ускорение обслуживания на кассе. Автоматизируем пропикивание и тем самым облегчим работу кассиров. О разработке замены кассирам речь, конечно, не шла. Лишь об ускорении их работы. Заодно разгрузим зал и увеличим пропускную способность столовой.

Мы запартнерились с компанией SkalaVision, ребята взяли на себя матчасть по OCR. На нас же осталась разработка POS-систем, интеграция с оборудованием и кастомная доводка решения по месту.

Работать должно было так. Гость ставит поднос под стойку с камерой на кассе. Кассир нажимает на экране POS-системы кнопку «Распознать». Происходит магия OCR и на экране появляются все блюда, которые система узнала. Кассир вручную вносит корректировки, если нужно, и пробивает чек.

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

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

  • Цикличность меню. В общепите существует ротация блюд. Это нужно не только для того, чтобы разнообразить ассортимент и порадовать клиентов, но и для оптимизации расходования продуктов. Поэтому недельное меню варьируется.

  • Внешний вид блюд зависит от смены. Несмотря на технологические карты, в которых вроде бы расписано приготовление блюда, салат «Весенний» одной смены отличается от такого же салата другой. Чуть иначе порезано, немного другая форма котлеты, пюрешку размазывают по тарелке слева направо, а не справа налево — и вот уже нейросеть запинается.

  • Схожие блюда. Борщ красный и свекольник тоже красный. Даже потребитель не всегда отличит одно от другого, а нейросетка путается постоянно.

Это котлеты.
Это котлеты.
И это котлеты.
И это котлеты.
И это тоже.
И это тоже.

Все это требовало увеличения количества сэмплов, а значит сроки обучения неприлично увеличивались.

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

Научить нейросеть различать свекольник и борщ сложно. А убедить владельца не снижать расходы — невозможно. Если ресторан высокой кухни еще со скрипом может себе позволить списать остатки томленой косули под трюфельным соусом, то в низкомаржинальном общепите разнообразие блюд приходится совмещать с экономикой.

Что с этим можно сделать? Мы придумали два варианта.

  1. Разносить визуально схожие блюда по разным сервисам подачи (утро-день-вечер) или по разным дням, а нейросети объяснять, что борщ бывает, например, по вторникам и четвергам, а свекольник только в среду. Это решение требует некоторой реорганизации технологических процессов в столовой и естественным образом не реализуется. Нужно продавливать управляющих.

  2. Оставить в системе распознавание для бизнес-ланчей. На некоторых предприятиях мы пошли этим путем. Суть в том, что бизнес-ланч имеет фиксированный набор блюд. Поэтому, даже если система ошибется и неверно идентифицирует борщ, точность распознавания бизнес-ланча в целом останется высокой и он добавится в чек правильно. Фактически, мы добились 100% точности в распознавании бизнес-ланчей.

Идентификация Борна борща.
Идентификация Борна борща.

Результаты: все пошло не так

Напомню: по задумке, наша система должна была упростить и ускорить работу кассиров в столовой. В реальности кассы стали работать в 2-3 раза медленнее! При работе в архаичном ручном режиме обслуживание одного клиента занимало у кассира от 20 до 30 секунд в среднем. А с помощью нашей суперсовременной OCR-системы — до полутора минут. Это фиаско.

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

Ожидание.
Ожидание.
Реальность.
Реальность.

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

В нашей же системе на экране отображались лишь распознанные блюда. Их порядок каждый раз был разным. Нужно смотреть на экран, а это медленно.

Во-вторых, из-за ошибок распознавания, мало просто смотреть на экран, нужно смотреть внимательно, чтобы убедиться, что в списке есть компот, а котлета — именно биточек, а не бифштекс. Это еще медленнее.

Частично удалось решить с помощью реорганизации экранного пространства (подогнали layout под быстрые пальчики кассирш), и цветового кодирования.

С бизнес-ланчами дело обстояло намного лучше. Но и здесь не обошлось без сюрпризов. Например, как-то раз на раздаче закончились рубленные бифштексы и повара стали в бизнес-ланч класть обычную котлету. А на кассе в чек заносится бифштекс! Потому что бизнес-ланч распознается целиком и подразумевает именно бифштекс. Возникает пересортица.

Выводы по первой части

Не ошибается тот, кто ничего не делает. Мы выяснили, что помогать кассиру делать свою работу не надо. Лучше просто не мешать. Но хотелось бы это знать до того, как мы разработали и внедрили наше «ускорение» на нескольких крупных предприятиях. Конечно, далеко не на всех из них все было настолько плохо, а на многих даже было хорошо. Но это другая история.

Правильно было бы провести детальную аналитику и кастдев потенциальных пользователей решения, изучив их потребности и реальные, а не выдуманные нами проблемы. Потом как следует обкатать в тестовом режиме и… сразу перейти к правильному варианту решения. А именно:…

Часть вторая: «Кассир не нужен!»

Не можешь победить — возглавь. В смысле, а почему бы не сделать кассиром саму POS-систему? Так наше решение по распознаванию еды эволюционировало в терминалы самообслуживания.

Задумка была проста как вареная картошка. Ставим терминал, в который занесено все сегодняшнее меню. Клиент подходит к терминалу, ставит поднос под камеру и нажимает кнопку «Распознать», а затем тут же и оплачивает банковской картой или картой сотрудника.

Как это выглядит у Сбера. Рандомное фото из интернета.
Как это выглядит у Сбера. Рандомное фото из интернета.

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

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

  • Меню столовых длиннее и чаще меняется. Следовательно, пользователь будет испытывать те же трудности, что и кассиры: блюда раз от раза будут оказываться в разных местах.

  • Бургер достаточно сфоткать красиво один раз. Красивые картинки для всех видов котлет отснять сложнее.

  • Система распознавания работала на тот момент все же не идеально.

Похожее зарубежное решение.
Похожее зарубежное решение.

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

Результаты: намного лучше

В этот раз тестовые прогоны показали очень хорошие результаты. Мы установили один терминал рядом с кассовой зоной. Т.е. часть клиентов шла через кассира, часть через терминал. Оказалось, что скорость обслуживания примерно одинаковая. При том, что кассир вводит блюда быстро, а клиент — не торопясь. Это успех!

Проблемы, конечно, тоже были.

С технической стороны были подтормаживания кассы из-за процесса распознавания. Обработка потока на слабеньком Atom или Celeron кассы приводила к ощутимому снижению производительности терминала и жалобам на подвисания. Решилось снижением частоты кадров камеры и сменой кодека с MPEG на YUYV 4:2:2.

Был еще забавный момент. Спустя какое-то время после внедрения решения кассиры начали саботировать терминалы. «Да они там глючные, давайте лучше я вас сама посчитаю, быстрее будет». Натурально сговорились и подняли восстание против машин.

Выводы по второй части

Внедрение киосков самообслуживания оказалось успешным. Постепенно люди привыкли и стали постоянно пользоваться ими, даже когда кассиры были свободны.

Однако как масштабировать этот опыт? Одно дело три комплексных обеда, совсем другое, когда блюд в меню 30-40 разных. Очевидно, нужно прокачивать OCR. Прежде чем переходить к заключительной части, попробую порассуждать, почему распознавать еду оказалось так сложно.

Почему распознавать еду сложно?

Во-первых, есть очевидные факторы — освещение, ракурс съемки, шумы и размытия на фото из-за движения подноса в момент захвата изображения, неконтрастный фон и т.д. Во-вторых, есть факторы, непосредственно обусловленные тем, что еда — это, вообще говоря, не цельный объект, а некая нечеткая форма с весьма условными границами.

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

С едой все иначе. У нее нет четких границ, практически нет реперных точек (особенно для мелкодисперсной еды, типа каши), текстура часто невыраженная и хаотичная, а цвета далеко не всегда яркие и контрастные.

Борщ сложно отличать не только от свекольника. Очень часто борщ и сам по себе сложно идентифицировать. Где-то положили гуще, где-то жиже. Тут нарезка ингредиентов крупная, а там мелкая. Не говоря уже о ситуациях, когда закончились глубокие суповые тарелки, и суп теперь наливают в глубокие миски для бульона. Ситуация из жизни, если что.

Есть нюансы с отличием схожих блюд с разным ингредиентами.

Вот ризотто с креветками.
Вот ризотто с креветками.
Вот ризотто без креветок.
Вот ризотто без креветок.
А здесь ризотто с омлетом.
А здесь ризотто с омлетом.
Это тоже ризотто. Скорее всего.
Это тоже ризотто. Скорее всего.

К слову, однородную пюрешку распознать проще, чем разноцветное месиво мелко порезанных овощей.

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

Наконец, нельзя сбрасывать со счетов и человеческий фактор. Редко, но и такое бывает. Бороться с этим, конечно, бесполезно.

Часть третья: «Обучение через уточнение»

Итак, мы остановились на вопросе масштабирования. Нужно было создать OCR-решение, которое достаточно уверенно распознавало бы десятки блюд, но при этом ошибка распознавания не выливалась бы в какие-то проблемы.

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

Например, если было продано 100 компотов и 3 бифштекса, то прогноз точности распознавания компота будет 100/103 = 97%. А вот для бифштекса лишь около 3%. Уточнений будет намного больше.

В случае масштабного обновления меню, первоначальные данные для распознавания нужно добавлять заново.

Результаты: работает, внедряем

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

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


На этом пока все, спасибо, что дочитали. В следующий раз подробнее расскажу про техническую реализацию: выбранные модели, особенности формирования датасетов, какие методы повышения точности распознавания использовали, а также технические моменты внедрения. Подписывайтесь.

Если у вас есть задачи по OCR, требующие экспертного подхода, обращайтесь. Пишите в личку или сюда: https://t.me/delykov