Каталог решений - Распознавание лиц в связке с 1С на коленке

Распознавание лиц в связке с 1С на коленке

Распознавание лиц в связке с 1С на коленке

В наличии

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

Категория:

Описание

Конечно, идея не новая, на инфостарте есть несколько статей про работу со сторонними сервисами по распознаванию лиц. Некоторые из данных статей написаны еще в 2017 году (распознавание лиц с тех пор значительно развилось). Тем не менее, надеюсь кому-то будет полезно.

В общем, на досуге пишу платформу по работе с видео потоком и обработкой результатов, платформа еще сыровата, но что-то (например, узнавание лиц из базы) работает вполне себе приемлемо. И родилась тут мысль, интегрировать платформу с 1С. А именно, написать «на коленке» такой механизм, который будет вместо карты лояльности покупателя считывать его лицо и исходя из этого рассчитывать скидку. Кстати «на коленке» пишу специально (чтобы сильно не ругали за кривую архитектуру и реализацию на стороне 1С). Ведь в данном случае цель – проверить гипотезу.

А гипотеза выглядит так:

Покупатель стоит у кассы, его лицо находится в объективе камеры. Камера каждые несколько секунд улавливает его лицо, распознает через нейросеть, и результаты распознавания записываются в БД событий. Далее, кассир вместо привычного:

— У Вас есть карта нашего магазина? Нет? Желаете оформить?

Просто нажимает кнопку «Проверить покупателя», и последнее событие из базы проверяется на наличие у него карты лояльности (виртуальной конечно же). Если таковая есть, 1С учитывает скидки.

Сейчас комплекс выглядит следующим образом:

Платформа работает с изображением с камеры, распознает лица, кидает изображение в нейросеть, получает ответ и записывает результаты в БД MySQL. К демонстрационной базе 1С: Управление торговлей 11.4 требуется реализовать получение данных событий (та самая MySQL база в которой фиксируются результаты с камеры).

 

 

 

Для того, чтобы это заработало, требуется:

  1. Добавить получение событий из БД событий в 1С: УТ.
  2. Добавить в 1С: УТ признак опознанного пользователя.  
  3. Добавить в 1С: УТ процедуру которая будет проверять наличие виртуальной карты лояльности у покупателя.

Итак, начнем с первого пункта.

Правильно было бы написать веб-сервис при обращении, к которому в 1С «прилетали» данные события. Но поскольку «на коленке» то будем подключить базу MySQL в качестве внешнего источника данных. Интересно, как это будет работать если в таблице записей больше чем хотя-бы 100 тысяч? Есть у кого опыт работы с большими таблицами во внешних источниках? Расскажите, как оно. Кроме тех случаев, когда внешние источники используются для разовой загрузки данных в 1С.

 Подключить внешний источник данных в 1С дело нехитрое. Для подключения используется коннектор ODBC

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

 

 

Есть контакт, таблицы доступны, ошибок не выявлено.

Поскольку, делать персональные карты лояльности, для программы которая работает по распознаванию лица было-бы как-то не логично, правильнее использовать для этого справочник «Виды карт лояльности». Для этого, добавляю в данный справочник новую табличную часть «Ники владельцев». В данной табличной части есть всего один реквизит «Ник владельца» с типом строка. Как нетрудно догадаться, в данную табличную часть будут заполняться наименования пользователей в том виде, в котором они содержатся в БД событий.

 

 

Указываем, что код состоит из двух символов. Теперь в системе есть не персонализированная карта лояльности, у которой может быть множество держателей, со скидкой 20% на всё. Данной виртуальной карте присвоен код 18.   

Сразу добавлю себя в табличную часть «Ники владельцев». В базе лиц я числюсь как пользователь с ником Kirill. Добавляю данный ник в таблицу.

Теперь интереснее. На фронте кассира, на форме считывания карты, добавляем кнопку «Считать покупателя» и процедуру для нее.

 

 

 

Приступаем писать процедуру проверки. Как вдруг сталкиваемся вот с этой болью:

 

 

Да, я знаю, что эту «боль» можно преодолеть используя таблицу значений, но поскольку пишем «на коленке» то просто добавим регистр сведений в который каждый раз при выполнении процедуры будет записываться последнее событие (а все остальные при этом удаляться, итого в базе не может быть более одной записи в данном регистре). Состав регистра при этом состоит всего из двух измерений (id, user) по аналогии с названиями колонок в MySQL. В данном случае id это порядковый номер события за день, то есть чем больше ID тем актуальнее событие. В случае если события записываются в одно и тоже время с точностью до секунды, то ID лучший вариант определения последнего.               

В итоге, перед началом проверки наличия виртуальной карты у покупателя, обновляем в регистре сведений последнее событие, и далее работаем по нему.  А после этого, проверяем по данному покупателю наличие у него бонусов. В конце, заполняем из запроса значение в реквизит «код карты» (если есть чем заполнить)

Код процедуры получился следующий:

  &НаСервере
  Процедура СчитатьПокупателяНаСервере()
  	Запрос1 = Новый Запрос();
  	Запрос1.Текст = 
  	 "ВЫБРАТЬ ПЕРВЫЕ 1
  	 |	events.id КАК id,
  	 |	events.user КАК user
  	 |ИЗ
  	 |	ВнешнийИсточникДанных.Faces.Таблица.events КАК events
  	 |
  	 |УПОРЯДОЧИТЬ ПО
  	 |	id УБЫВ" ;
  	Результат = Запрос1.Выполнить();
  	Выборка = Запрос1.Выполнить().Выбрать();
  	Пока Выборка.Следующий() Цикл
  	МенеджерЗаписи = РегистрыСведений.АктуальноеЛицо.СоздатьНаборЗаписей();
  	ТекущийПокупатель = МенеджерЗаписи.Добавить();
  	ТекущийПокупатель.ID = Выборка.id;
  	ТекущийПокупатель.User = Выборка.user;
  	МенеджерЗаписи.Записать();
  	КонецЦикла;
  	Запрос2 = Новый Запрос();
  	Запрос2.Текст =
  	"ВЫБРАТЬ
  	|	АктуальноеЛицо.User КАК User,
  	|	ВидыКартЛояльностиВладеющиеКартой.НикВладельца КАК НикВладельца,
  	|	ВидыКартЛояльностиВладеющиеКартой.Ссылка КАК Ссылка,
  	|	Карты.Штрихкод КАК Штрихкод
  	|ИЗ
  	|	РегистрСведений.АктуальноеЛицо КАК АктуальноеЛицо
  	|		ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ВидыКартЛояльности.ВладеющиеКартой КАК ВидыКартЛояльностиВладеющиеКартой
  	|			ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
  	|				КартыЛояльности.Штрихкод КАК Штрихкод,
  	|				КартыЛояльности.Владелец КАК Владелец
  	|			ИЗ
  	|				Справочник.КартыЛояльности КАК КартыЛояльности
  	|			ГДЕ
  	|				КартыЛояльности.Владелец.Наименование ПОДОБНО ""Лицо"") КАК Карты
  	|			ПО ВидыКартЛояльностиВладеющиеКартой.Ссылка.Ссылка = Карты.Владелец.Ссылка
  	|		ПО АктуальноеЛицо.User = ВидыКартЛояльностиВладеющиеКартой.НикВладельца";
  	Результат2 = Запрос2.Выполнить();
  	Выборка2 = Запрос2.Выполнить().Выбрать();
  	Пока Выборка2.Следующий() Цикл
  		ЭтаФорма.КодКарты = Выборка2.Штрихкод;
  	КонецЦикла;
  	Сообщение = Новый СообщениеПользователю();
  	Если ЭтаФорма.КодКарты = NULL Тогда
  		Сообщение.Текст = "Покупатель не опознан"
  	Иначе Сообщение.Текст = "Обпознан покупатель с ником" + Выборка2.user;
  		КонецЕсли
  КонецПроцедуры
  

 

Ошибок нет, пробуем в режиме предприятия.

Платформа распознавания лиц в это время работает примерно так:

 

То есть каждые несколько секунд «узнает» лицо в кадре и пишет в базу событий и записывает в базу результаты. А еще утверждает, что покупатель «чёт приуныл».

 

Запускаем фронт кассира, добавляем в покупки двух «белочек» (просто для данной номенклатуры настроены цены в демонстрационной базе).

 

 

Нажимаем «Считать карту» и новую кнопку «Считать покупателя»

 

 

It works! При нажатии код карты определился как «18» (тот самый код который присвоился карте). Нажимаем «Готово» и «Рассчитать скидки» на фронте кассира.

 

 

Скидка на «белочек» учитана. ЧИТД.

Выводы:

В целом, все это максимально просто с точки зрения реализации, поэтому сомнений что идея «взлетит» не было. Опасения вызывала скорость работы 1С с внешними источниками, то есть что пока он получит данные, в базе создастся еще несколько событий и то что получит 1С будет уже не актуальным. Но по-факту запрос 1С вытащил актуальное событие из БД MySQL.

Как это можно использовать еще? На скриншотах видно, что помимо «узнавания» система также пытается определить пол, возраст и эмоции человека. Исходя из этого кассир также может попытаться определить возраст. Это актуально в случаях если на продукцию стоит ограничение 18+. Конечно есть вероятность того что система неправильно определит человека. Но можно усложнить логику — в зависимости от уровня соответствия человека в объективе тому что в базе. Если уровень соответствия не высок, но система определяет что это «именно тот покупатель» то можно задавать вопрос кассиру – учитывать ему скидку или нет? Но это размышления из серии – «а что, если»? 

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

Насколько подобное решение может быть эффективно для бизнеса? Не важно, мы же кодеры)). Лучики добра всем в лапки!

has been added to your cart:
Оформление заказа