Привет, Хабр! Немного наболело, хочу поделиться. В серии материалов я освещу ряд аспектов мобильного компьютерного зрения по принципу “от простого к сложному в имплементации”, однако буду фокусироваться на сложных кейсах, которые выходят за грань банального “распознать QR-код с фотографии один раз в сутки на %гиперскейлере%”. Я пишу только о мобильном, полностью автономном подходе, и надеюсь, смогу раскрыть для широкой аудитории мобильных разработчиков определённую глубину задач мобильного компьютерного зрения, о которых не подозреваешь, принимаясь за работу по распознаванию данных с физических носителей в первый раз.  Количество практических задач, где требуется распознавание метаданных, таких как штрих-коды, неуклонно растёт. Лучше впитать лучшие практики сейчас, чем после продакшена с низкой конверсией по определенным процессам в приложении и post-mortem анализа, который, увы, не вернёт маркетинговый бюджет. Казалось бы, если в суете дней кто-то спросит или, что более вероятно, на горизонте забрезжит задача по оптическому распознаванию штрих-кодов с смартфонами или планшетами, на уровне рефлекса проскочит мысль-ответ - задача уже решена тысячу и один раз, есть куча опробованных тулзов и фреймворков, как открытых, так и платных, которые полностью покрывают данный вопрос и, как кажется, время работы над именно этой частью вашего мобильного приложения будет ничтожно мало.  Ответ в стиле “1 человеко-день разработки, три с тестированием, пять в план/трекер с учетом непонятных пока мелочей” будет весьма традиционен, вы примете его как верный и перейдете к планированию более важных аспектов вашего приложения, например, интеграции с бэкэндом. Однако, перед тем как окончательно утвердиться в возможности реализации задачи за условный “человеко-день” (или даже неделю), стоит провести совершенно не банальный анализ того, как именно, с чем именно, где именно и при каких условиях должен, в большинстве своём, происходить процесс сканирования, особенно, если этот процесс - часть вашей клиентской воронки.  Если коротко, то для большинства разработчиков - да. Только они об этом пока не знают, надеюсь, что после прочтения материала ниже проблематика переместится из категории "неизвестных неизвестных" в "известные неизвестные" (про категории неизвестных см. видео).  В случае проработки задач мобильного компьютерного зрения, а распознавание штрих-кодов с реальных физических носителей это задача мобильного компьютерного зрения, у разработчиков приложения практически нет никаких возможностей повлиять на то, в каком окружении, в какое время суток, с каких носителей будет идти считывание информации. Более того, часто аналитики, разработчики и руководители в целом не задумываются, что именно в этом шаге  процессов выполнение вываливается из строго контролируемой песочницы мобильной платформы в наш неидеальный физический мир. В этом мире руки у людей могут дрожать, солнце скрываться за горизонтом, смартфоны - быть в корне непохожими по характеристикам на смартфон разработчика, а камеры различных устройств совершенно по-разному работать, выполняя при этом одни и те же команды Camera API 1 или 2. Оговоримся, что первое условие для этого эксперимента – наличие у вас готового рабочего демо-приложения (окей, github) с тем или иным сканером штрих кодов (ZXing, AVFramework, MLKit и другие). Запустите приложение на реальном мобильном устройстве. Тестировать такие вещи в эмуляторах полностью лишено смысла - железо камер не эмулируется, эмулируется лишь передача и оборачивание видео и фото данных, а это очень разные вещи. Далее, для простоты, возьмите любую упаковку продуктов из холодильника или коробку/упаковку оставшуюся от доставки/заказа. Наверняка на этом предмете есть штрих-код: если это продукт из супермаркета, там будет EAN13, но быть может и EAN8 - если речь о косметике, EAN13+2 / 5 для журналов и книг, Code39 или Code128 для посылок и заказов, и, разумеется, DataMatrix для лекарств и всех продуктов с “Честным Знаком”. Попробуйте считать данные этого штрих-кода используя предполагаемый к внедрению/любимый/популярный/только что изученный фреймворк в нескольких ситуациях: При хорошем искусственном освещении в помещении Выключив искусственное освещение в этом же помещении  Отсканировать этот же код в сумерках, на улице  В каждой из ситуаций, вы сперва попытались считать значение штрихкода мобильным устройством максимально комфортно для вас и поначалу не следили за дистанцией от носителя до камеры смартфона.  Если же в состоянии максимального комфорта для ваших рук были затруднения считывания - вы, скорее всего, подносили упаковку с штрихкодом ближе к камере и старались, чтобы плоскость кода совпадала с плоскостью камеры, то есть, кроме дистанции вы уменьшали и угловые искажения.  Если же и при этом код распознавался долго (т.е. вы успели подумать “не пойму, почему сейчас он тоже ничего не может считать, ведь код прямо перед объективом”) или не распознался совсем, то, может быть, вы даже включали подсветку камеры или подходили ближе к источникам света/окну для успешного считывания.  Тем не менее, несмотря на сложности, я уверен, что вы смогли успешно считать значение штрихкода во всех ситуациях и эти значения посимвольно совпали.  Поздравляю! Именно ваш смартфон и стоит выдать всем пользователям вашего приложения! Уверен, что целевая аудитория Хабра имеет достаточно хорошие устройства в своём распоряжении и многие курьеры, сортировщики и сотрудники доставки, а так же покупатели в магазинах будут рады вашему подарку. Разумеется, это юмор, однако с существенной долей горькой правды. Факторов, которые задают успешность процесса распознавания на моб. устройствах гораздо больше, чем перечисленный в примере выше смартфон (точнее, железо камеры, процессор и количество запущенных в это время приложений), освещённость, угловые искажения и дистанция от камеры до носителя. Как минимум, добавьте следующие "неопределенности": Носители могут отличаться материалом, размером, качеством и цветом печати, могут быть покрыты дополнительной упаковкой и факт сканирования именно тех кодов, что вы имеете в качестве тестовых, не означает, что все продукты в супермаркете можно так же быстро распознать с этим же решением Пользователю может быть критичным уложиться в определенное время по числу сканирований и скорости каждого отдельного скана. Эргономика тоже в приоритете - удобство хвата устройств, удобство работы одной рукой. Экономичность - если процесс сканирования это основной рабочий процесс и требует 2-3-8 часов работы с приложением, не сядет ли батарея (и что вы, как разработчик и пользователь фреймворка можете сделать, чтобы это предотвратить)  Вам, в свою очередь, как команде, важно реализовать прототип приложения сейчас и только под Android, но потом, в случае хорошего старта / выигрыша в конкурсе, вы готовы и под iOS сваять, посему сразу используете кросс-платформенный фреймворк (Flutter, Xamarin и др.) и код прототипа станет основой проекта.  На практике все выше указанные обстоятельства командой разработки не рассматриваются сразу и в комплексе, скорее идёт постепенный рост проблем - сделаем прототип-проверим-по откликам доработаем.  После того, как уже сформирован набор архитектурных решений - какие фреймворки для разработки приложения будут использованы (native а-ля Swift + Kotlin или кросс-платформ, а-ля Flutter или Xamarin), каков срок на проработку задачи, какой плагин для сканирования будет использован, появляются юзер-стори с весьма туманными требованиями на тему распознавания: "я, как пользователь, хочу отсканировать код под крышкой бутылки не более чем за 5 секунд". И дело тут не в пресловутых 5 секундах, а как именно сканирует и что и чем - разработчик и как - пользователь. Кстати, именно по распознавалке выбор часто протекает на основе бумажного / youtube / github поиска и сравнения двух-трёх бесплатных / условно бесплатных решений Поддерживает наши платформы? Да Поддерживает наш фреймворк мобильной разработки? Да Поддерживает наши символики (типы штрих кодов)? Да Работает в оффлайне? Да Ок, погнали... А требования по эргономике процесса часто появляются только после того, как приложение ушло в тестирование на фокус-группу (а иногда и эксплуатацию) - только на большом количестве пользователей становятся заметными такие ситуации, как медленное или ошибочное (на определенных кодах в одном-двух знаках) сканирование у части аудитории, плохое сканирование конкретных типов штрих-кодов, неудобства при работе в складских помещениях или внутри автомобиля, из которого посылки извлекают для вручения в руки клиентам. Зачастую всё происходящее не расценивается как единый связанный с чем-то набор проблем, так как выбранное решение, разумеется, в лабораторных условиях работает адекватно. Всё списывается на “условия”, “плавающие баги”, "старые телефоны" и закрывается повторным тестированием. Однако, по сути, имеет более простое объяснение - чтобы выявить сбой в самом сканировании, благодаря математике лежащей в основе любой из символик (EAN8/13, Code128, DataMatrix и т.п.) требуется очень большое для обычного процесса тестирования (но не для эксплуатации) количество повторных сканирований в различных условиях. Не единицы и не десятки, как минимум - сотни. В лучшем случае - тысячи попыток при разных условиях. Сам, как потребитель, я часто наблюдаю все эти шишки, но увы, не в тестовой эксплуатации, а на практике - сканирую продукты для повторного заказа на смартфоне (а потом решаю прекратить это извращение), наблюдаю как выдают мне посылки / заказы курьеры - иногда при частичной выдаче товара  достаточно долго сканируют, а потом вручную вводят возвращаемые позиции. Не хочется называть конкретные компании, но для некоторых больших игроков онлайн-ритейла уже 90% автоматизация ввода штрих-кодов - прогресс по сравнению с 100% ручным вводом, как это было еще год назад. Тем не менее, оставшихся 10% с ручным вводом достаточно, чтобы задержать сотрудника. Да да, тот самый Covid-19 и спрос на курьерскую доставку дал понять, что рынок труда может неожиданно схлопнуться и вопрос эффективности процессов гораздо важнее, чем может казаться (до пандемии всегда находились дополнительные руки, и можно было ими перекрыть убогую автоматизацию, ведь себестоимость ручного труда у нас исторически ниже стоимости автоматизации). НО! Когда на банальные операции уходят минуты, а твоя сеть доставки перегружена, заказы уходят конкурентам - в вашем приложении просто нет слотов на доставку в нужное время. И с привлечением временного персонала появляется огромный парк разношёрстных личных устройств, сканирование ш/к на которых заставляет сотрудников задерживаться на минуты (!) у конкретной двери в момент выдачи. Воистину, где-то даже удивляет бескрайняя терпимость полевых сотрудников по отношению к рабочему оборудованию и ПО, особенно в сравнении с офисным персоналом и любимым обращением в поддержку а-ля “мой Outlook | Word | всё тормозит, невозможно работать!!!”... Но, если с проблемой производительности персонала компании живут (однако не всегда успешно конкурируют), то вот вернуть маркетинговый бюджет потраченный на привлечение уже не всегда бывает безболезненно, особенно при больших инициативах, трансформирующих сам бизнес.  К таким инициативам, например, можно отнести запуск процессов самостоятельного оформления покупок в супермаркете - речь не о кассе самообслуживания, а о сканировании и оплате с мобильного устройства клиента, через приложение. Такие процессы набирают популярность в ритейле, так как  разгружают кассовую зону выносят часть инфраструктуры на устройства клиентов  не создают зон без соц.дистанции  дают возможность для быстрых импульсивных покупок 2-3 позиций в “один клик”, что особенно важно для магазинов с высокой загрузкой в обеденный период или точек с короткопериодической высокой проходимостью. Эффективность процессов сканирования с использованием смартфонов, как во внутренних операциях, выполняемых сотрудниками, так непосредственно клиентами на своих устройствах, требует, увы и к сожалению, более глубокого, всестороннего и качественного тестирования, чем кажется на первый взгляд. Многократное сканирование образцов камерой смартфона в идеальных условиях не покажет разницы, однако 2-3 недели тестовой эксплуатации и дальше проблема вылазит уже в бизнес-показателях аналитических отчётов: меньшей, чем ожидалось по фокус-группе, конверсией по целям в приложении, высоким показателем отказов на этапе сканирования купона или промо или падением производительности с 30 до 29 доставок в смену у курьера, несмотря на прогнозируемый прирост производительности при использовании мобильного приложения.   Отталкиваться при появлении задачи мобильного зрения для распознавания физических материалов / носителей метаданных необходимо от результатов пред-проектного тестирования в реальных условиях.  Качественная работа сканера может быть критическим фактором успеха всей инициативы или, как минимум, её масштабирования (мобильное рабочее место сотрудника, приложение программы лояльности, приложение самообслуживания).  Требуется обеспечить наличие парка устройств, максимально отражающего спектр устройств целевой аудитории и обязательно включающего в себя самые старые и простые из используемых ЦА устройств, которые совместимы с приложением и платформой (версия Android/iOS), равно как и самые распространённые устройства эконом-класса и, разумеется, устройства среднего класса от самых популярных у ЦА производителей (не во всех аудиториях iOS это iPhone 7/8/9/10+, а Android - вовсе и не Samsung/Redmi/Huawei). Набирать в тест топовые смартфоны можно по остаточному принципу, т.к. железо в них априори качественнее остальных, а вот с мид-маркет бывают сюрпризы, когда мид-маркет устройства проседают даже по сравнению с эконом-моделями прошлых лет (удешевление комплектующих, увы). Необходимо обеспечить тестирование процесса в окружениях максимально близких к реальным условиям плохая освещённость - улица утром/днём/вечером/ночью средняя освещённость - склад, метро, подземный переход, цокольный этаж с постаматом и подобное достаточная освещённость - офис переосвещённость - шоу-рум, розничный магазин Проведите тесты руками конечного пользователя - запишите видео, как выполняет операции сканирования сотрудник/пользователь (не поручайте это членам команды, увы, мы все субъективны и склонны подстраиваться под наш проект и его вводные). Обязательно запишите весь процесс, для дальнейшего пошагового разбора:  Важно сделать данный тест еще только в начале процесса разработки, для понимания эргономики и качества распознавания до момента принятия окончательного решения и выработки окончательного UI приложения.  Ни ритейлу, ни логистам в работе с штрих-кодами не бывает просто. Может придти посылка из-за рубежа с своим, уникальным ш\к, полную прослеживаемость которого надо обеспечить по условиям контракта. Может новая замечательная предновогодняя упаковка товара из А-сегмента товарной матрицы очень плохо сканируется, а высокая оборачиваемость данного товара приводит к очередям из посетителей с булочкой и шоколадкой на кассе. Посему, несмотря на ограниченные рамки при разработке, особенно на предпроекте, нельзя предполагать 100% покрытие кейсов тестирования лимитированным набором этикеток/лейблов, усилив тесты максимально сложными и редкими вариантами вкупе с часто встречающимися.  Да, не имеет смысла сканировать весь ассортимент супермаркета (он тоже может быть нерепрезентативен), но иметь арсенал по 3-5 единиц образцов где коды имеют следующие свойства просто критически необходимо: повреждённые коды  низкоконтрастные (тёмно-серый код на светло-сером фоне) цветные (черный на красном фоне, розовый на белом) инверсные (черный фон, белые элементы),  минимально возможные по размеру искривлённые (банки) прозрачными (бутылки) отражающими (алюминиевые банки и коробки) деформируемыми (CPG, конфеты, батончики) кодами на обёртках и пакетах в дополнительной упаковке (сигареты, контрацептивы) с нарушением пропорций и т.н. тихой зоны (гуглить по ключевым словам "barcode quiet zone requirements", дальше вымерять отступы на ваших этикетках, в дизайне иногда такие креативные решения бывают, вау) для логистов - образцы почтовых этикеток всех партнёров/клиентов для понимания особенностей (вдруг, там рядом 2 ш/к одной символики и длины, например, code128, вечер перестанет быть таким томным)  и замерять сканирование именно таких сложных случаев в определенном миксе с обыденными вариантами и является минимально необходимым. Ведите видеозапись процесса сканирования со второго устройства (держа в кадре и носитель и экран сканирующего устройства - это минимальный сетап для бенчмаркинга. Внимание! Весь этот параграф должен быть написан жирным капслоком! Подчеркну полную недопустимость принятия решения о выборе компонент распознавания на основе сугубо девелоперского, не контролируемого извне, тестирования (- ты протестил? - ага, из трёх только ХХХ справляется, предлагаю его брать): Места обитания разработчиков моб. приложений весьма комфортны для длительной работы глаз (и камер - как следствие) и совершенно не совпадают по эргономике с реальными помещениями  Разработчики склонны распечатать образцы ш/к на ближайшем принтере (иногда - по фотографии из интернетов), а не заполучить и постоянно обновлять запас реальных образцов (как происходит на складе или на полке магазина) Смартфоны разработчиков лучше медианных по характеристикам Далее, совершенно недопустимо тестирование путём считывания штрих кодов по фотографии с экрана монитора. Это часто и есть этап “предпроектного тестирования” за которым идёт финализация состава библиотек и архитектуры приложения. Как ни странно на первый взгляд, такой метод тестирования даёт совершенно неправильные представления о работе того или иного фреймворка. Фотография + монитор значительно затрудняют распознавание, но, как ни странно, в жизни оно будет тоже сложным, однако, по совсем другим причинам, не связаным с фреймрейтом видеоряда / разрешением фотографии и частотой монитора, а с эргономикой (положением тела и устройства, хватом рук, движениями), размером носителя, расположением и направлением света, качеством печати на носителе и другим. Поэтому, вы, по сути, будете руководствоваться ложными критериями при тестировании с экрана, и, скорее отбросите ряд подходящих вариантов, нежели сможете найти единственно верный. Так же недопустимо в любом, даже мало-мальском проекте предполагать возможность полного онлайна и анализа изображений, а тем более видео потока на сервере. Мобильная связь даже в пределах Москвы достаточно неустойчива к передаче потоковых данных и больших файлов (таких как фото без сжатия). Конкретно по этому пункту необходимо закладывать только edge-обработку и распознавание (привет, %гиперскейлер%, мы все тебя любим, но не в этот раз). Только имея на руках  Аналитику по устройствам целевой аудитории и обращая внимания на экстремумы в ней в виде “очень старых устройств / дорогих клиентов на них” Репрезентативную выборку носителей штрихкодов (товары, этикетки), отражающих как обычные, так и сложные кейсы для распознавания Понятный набор условий окружающей среды (освещенность от и до, дистанция от и до) в тех сценариях, где сканирование будет происходить чаще всего / может происходить с существенным риском успешности Видео- или другие материалы (возможно, живая сессия с ключевыми пользователями) фиксирующие желаемую и текущую эргономику процесса (возможно, текущий процесс удобен, но обходится проводным сканером, без смартфона) Дорожную карту проекта возможно провести качественный подбор оптимального решения по распознаванию штрих-кодов на мобильных устройствах для промышленного использования (тысячи пользователей с использованием функции каждый день).  Исходя из этой картины, каждой команде ещё на предпроекте требуется реализовать простое приложение с возможностью (в идеале) переключения с одного компонента по распознаванию на другой для оперативного выполнения тестов в процессе пред-проектного исследования. Особенно актуально это при выездном пред-проектном исследовании, когда каждое “соприкосновение” с реальными условиями несёт за собой командировочные и временные расходы. По итогу такого исследования, имея чёткую статистику по количеству неверных считываний и среднему времени считывания, предлагаю вам для мобильных решений в области B2C - экстраполировать количество ошибок за день по аудитории и суммарную стоимость этого сегмента (как в заказах, так и в маркетинге на удержание). Учтите, что 1 неверное считывание в супермаркете - это случайность, второе - закономерность, третья минута и третий несчитанный штрихкод ставят крест на данном процессе для покупателя, он переходит со своей корзиной на кассу для мобильных приложений в области B2B - количество ошибок влияет на количество операций сотрудников в единицу времени, но эффективность падает не линейно, а по экспоненте - равно как и с покупателем, энтузиазма у сотрудника на третьей ошибки ноль, а перед ним еще 15 коробок на приёмке. Он пойдет искать тот самый единственный на весь магазин ТСД (терминал сбора данных), который видел в руках коллеги. Спасибо и надеюсь, кого-то данный материал предостережёт в этом году от поспешного выхода в продакшен с непоправимыми для карьеры и бизнеса последствиями.