Как я делал видеоаналитику магазинов, не зная ничего про машинное зрение
Однажды я проснулся и подумал: почему бы не сделать видеоаналитику по записям камер в магазинах? Раньше я об этом и мечтать не мог, а теперь можно взять готовую модель и с коллегой (Claude) все собрать. В итоге это растянулось на два месяца. И самым сложным оказались не технологии, а то, что модель все время останавливалась на первом попавшемся решении.
Акт 1. Получение видео для теста
Чтобы начать эксперименты, нужно было перенести видео с камер на компьютер. У меня в магазинах стоят домашние камеры Xiaomi. Пишут они на SD-карту, а скачать записи можно только через мобильное приложение, через браузер не зайти. Была идея эмулировать Android и скачивать все по порядку: костыль, но для теста это дешевле, чем менять оборудование во всех магазинах. Claude вообще предлагал поставить в каждый магазин мини-компьютер.
В итоге я пересилил себя и сделал самую сложную часть всего эксперимента: пешком сходил в ближайший магазин (назову его магазин 1), вытащил карту и принес домой. На ней было 29 ГБ - всего четыре дня записи. Я почему-то представлял меньше.
Акт 2. Прогоняем модель
Я ничего не знаю про машинное зрение. Слышал только, что по видео можно распознавать людей и предметы. Попросил ИИ прогнать какую-нибудь модель, и он выбрал YOLO11 в размере s (small). Почему именно s, никто не проверял: это просто было удобно, ноутбук и так грелся. Потом я спросил, почему не взять модель получше, и только тогда их сравнили и перешли на m.
Ноутбук ушел в стратосферу на всю ночь. Результат был эффектный: в среднем 2,7 человека в кадре. Конверсию модель не считала: она не может проследить одного и того же человека от кадра к кадру и путается, так что считала просто, сколько людей в кадре. Цифры намекали, что людей очень много, а продавец плохо с ними работает. Подкрути продажи, и можно больше никогда не работать.
Я попросил прислать пару кадров с разметкой и увидел, что людьми модель считает и манекены. Причем манекен она принимает за человека увереннее, чем живого продавца за вешалкой. Манекены в магазине стоят всегда, отсюда и постоянные 2,7 человека в кадре.
Акт 3. Апатия и попытка вытянуть что-то полезное
Обсудили с ИИ и поняли, что так ничего не посчитать. Чтобы не уходить ни с чем, я попросил найти хоть какую-то пользу. Смогли определить, когда продавец действительно пришел и ушел: тут все четко, нашлись опоздания и ранние уходы. А время на стуле у кассы получилось спорным: продавец отвернулся - и модель его уже не узнает. Доверять этому нельзя.
Я загрустил, а потом вспомнил, что можно распознать звук и по разговорам понять, как продает продавец. Попросил прогнать все записи через модель распознавания речи (Whisper). Но я не проверил, правильно ли меня поняли, и модель прогнала только несколько минут вокруг каждой продажи. Так не узнаешь, почему продажа не случилась. А если с клиентом работали минут десять?
Дальше стало интереснее. Чтобы найти речь во всем дне, Claude взял отдельную модель - детектор речи. Тот сказал, что речь занимает 1-4% времени, и Claude уверенно заключил: звук бесполезен, нужен отдельный микрофон у кассы. Я открыл запись и услышал ссору с покупательницей ровно там, где детектор показывал «тишину». На записи с камеры он оказался глухим.

Акт 4. Сопротивление навязанным убеждениям
В очередной день просыпаюсь и думаю: неужели нельзя дообучить модель на моей разметке? Ответ: можно. Непонятно только, почему сразу так не сделали.
Взяли случайные кадры за каждый день, получилось 254. Быстро сделали интерфейс для разметки, и я разметил все минут за двадцать: где манекен посчитан человеком - помечаю манекен, где человека пропустили - помечаю человека.
Первое обучение девять часов шло впустую из-за одной настройки. Со второго раза получилось. Проверили на кадрах, которых модель не видела: раньше она правильно считала людей на 8% кадров, теперь на 76%. Лишних «людей» стало 7 вместо 81.

Акт 5. Посчитаем конверсию
Счастливый, прошу посчитать конверсию, забыв, что людей еще надо связывать между кадрами. Получаю около 240 человек в день и конверсию 2%: опять плохие продавцы. Прошу фото каждого «посетителя» и вижу, что одних и тех же людей модель посчитала по несколько раз, а продавца - каждый раз как нового.

Тогда я сам разметил людей и продавца: 1580 кадров за 40 минут. Оказалось, что в день заходит 32-53 человека, в среднем 43. За четыре дня это 172 человека, 21 чек, конверсия 12%. Первая цифра трафика была завышена в пять раз.

Заодно я хотел ответить на вопрос, с которого все началось: почему в один день выручка нормальная, а в другой провал. С пятницы на субботу выручка упала в 6,5 раза. Людей зашло меньше, 35 вместо 52, и в субботу магазин закрылся раньше. Но и чеков было 2 вместо 8. По двум чекам о продавце ничего не скажешь, четырех дней для такого ответа мало.
Акт 6. Второй раунд с голосом
Мне все же было интересно, как продает каждая продавщица. Я попросил прогнать распознавание речи по всему рабочему времени и сопоставить текст с видео, чтобы в любой момент самому послушать, где продавец, а где клиент. Claude предупреждал, что в тишине модель начнет выдумывать слова. Выдумывает, но отсеять это несложно.
За четыре дня нашлось 119 разговоров, и только 17 из них закончились чеком. Продавец на замене все время тратит на продажи, сухо, но продает хорошо. Основной продавец постоянно болтает о чем угодно, кроме товара. Самый длинный разговор у кассы перед покупкой длился восемь минут - про засолку огурцов. А одну покупательницу она своим мнением об одежде так обидела, что та ушла.
Четыре дня - это мало. Но уже видно, какие привычки стоит перенести на других продавцов, а за что сделать замечание.
Акт 7. Скачивание записи
Мне не давала покоя мысль, что записи можно получать на сервер без смены оборудования. Хотелось поставить систему на поток, а не провести эксперимент один раз.
В приложении Xiaomi видео скачивается по одной минуте, и каждую надо выбрать вручную: час записи - это 60 раз. Одна минута на телефоне качалась полторы минуты. Чтобы скачать рабочий день, нужно больше времени, чем длится сам рабочий день.

Снова прошу эмулировать Android на сервере. На этот раз даже войти не получилось: экран входа Xiaomi защищен и на сервере просто не рисуется. Обошли так: вошли в эмуляторе на ноутбуке и перенесли готовую сессию на сервер. Посмотрел, сколько стоят серверы с видеокартой - от 15 000 ₽ в месяц. Как-то не прикольно, и я отложил проект.
Акт 8. Промышленный масштаб
Между делом я дважды садился писать этот пост, и оба раза казалось, что эксперимент неполноценный. Через месяц решил все организовать на сервере. Нашел сервис, где сервер с видеокартой можно арендовать поминутно (потом он мне не раз пригодился и в других задачах, всем советую).
Скачивание снова не пошло: Claude написал, что пока не получается. Я ответил: «Нет, изучи, как это сделать, я уверен, что есть способ». Нашлось: приложение качает записи только по Wi-Fi, а эмулятор сообщает, что подключен кабелем. Исправили три строки, и минута записи стала качаться за 11 секунд вместо полутора минут. Скачали 11 дней по двум другим магазинам, 2 и 3, 67 ГБ - чуть не забили сервер, свободными остались 9 ГБ. Для скачивания, кстати, видеокарта вообще не нужна, она нужна только для модели.
Магазины другие, угол камер другой, модель надо учить заново. На этот раз я размечать сам не стал и попросил Claude. По его разметке точность выросла с 41% до 84%. Потом я все-таки прошел 300 кадров сам, и на 69 пришлось править. Лишних людей Claude почти не рисовал, всего 5, зато пропустил 61 из 342, примерно каждого шестого. Оказалось, он не размечал с нуля, а раскладывал по классам то, что нашла стандартная модель. Кого не увидела она, не увидел и он. Так что 84% посчитаны по неполным ответам, и настоящую точность покажет только новое обучение.

И тут модель снова поспешила с выводом. Claude посчитал 130-150 заходов в день и конверсию 6-9%: «людей хватает, продают плохо». Я попросил второго Claude вручную пересчитать эталонный час, и он нашел 7 человек вместо 17-20: первый посчитал покупателями прохожих за витриной. Сверили с ручным счетом на 12 часах. Итог: в магазин 2 заходит 47-61 человек в день, и каждый 5-7-й покупает. В магазин 3 заходит 59-87 человек, конверсия от 5% до 24% в разные дни. Это пока предварительные цифры: модель училась на разметке, где не хватало каждого шестого человека.
Акт 9. Пауза, а не конец
В остальных магазинах надо поменять SD-карты, поэтому промышленный масштаб я пока отложил. Модель надо дообучать дальше, хотя бы до 95%. Хранить видео не обязательно: обработал - и удалил, остаются только цифры.
По деньгам: если раз в неделю брать один день со всех камер шести магазинов и считать на арендованной по часам видеокарте, выходит около 2 500 ₽ в месяц. Каждый день - уже 15-25 тысяч, и тогда упираешься в мобильный модем магазина: семь камер - это около 35 ГБ в день через один модем. Так что я, скорее всего, начну с такого еженедельного пульса.
К чему все это
Во-первых, когда бы я еще занялся машинным зрением? Это абсурд, а вот - занялся.
Во-вторых, будьте готовы, что модель будет вас останавливать. Она выбирает самое простое решение и говорит «не получится», пока не скажешь «я уверен, что есть способ». А когда что-то получается, она так же уверенно выдает первую цифру и сразу делает вывод. Дважды я чуть не решил, что продавцы плохо продают, и оба раза правду показал ручной счет. А когда разметку делал сам Claude, он пропустил каждого шестого человека. Не верьте ни «не получится», ни первой цифре: проверьте сами на маленьком куске.