Хочу поделиться опытом добавления некоторой вольности Алисе (внутри колонок поддерживающих локальный API).

О локальном API колонок уже писали тут.

Идея заключается в том, чтобы Алиса реагировала на присутствующих людей. Для этого их необходимо идентифицировать, например, с помощью распознавания лиц. В статье будет использован самый простой (на мой взгляд), вариант создания модели для распознавания – тренировка модели в Google Teachable Machine, так как он не требует знаний и хорошего железа.

Для управления колонкой используется модуль node-red-contrib-yandex-station-management для Node-Red позволяющий отправлять на колонку текст, который произнесет Алиса (а так же посылать команды, управлять воспроизведением и получать статус колонки). Еще Алиса в случайное время будет выдавать некоторую «отсебятину».

Все  скрипты, упомянутые в статье, и инструкции по их запуску и настройке можно скачать из репозитория.

Используемые инструменты:
Все действия выполнялись на:
  • Intel NUC core i5

  • 4GB RAM

  • Видеокарта Haswell-ULT Integrated Graphics Controller (не задействована).

  • Веб камера для сбора лиц и отладки

  • Камера выдающая RTSP поток для основной задачи

  • ОС Ubuntu Server 20.04

В репозитории присутствует файл docker-compose.yml для быстрой установки Node-Red, MQTT и PostgreSQL. Инструкцию по установке docker-compose можно почитать тут. Основной скрипт запускается без использования docker.

Для установки Tensorflow и OpenCV в Ubuntu 20.04 необходимо выполнить:

sudo apt install python3-venv python3-dev

pip3 install opencv-python@4.5.1 tensorflow@2.10.0 paho

Статьи про установку и настройку вышеперечисленных сервисов без использования Docker:

Принцип работы:

  1. Скрипт alice_has_fun.py распознает лица и отправляет процент совпадения в MQTT брокер в формате json;

  2. Node-Red получает сообщения об обнаружении людей из MQTT, для каждого лица получает из БД время его последней фиксации и обновляет его на текущее;

  3. В зависимости от времени суток и того, как давно система фиксировала человека, Node-Red отправляет на станцию команду сказать что-либо. Фразы для Алисы, а так же время последней фиксации хранятся в БД PostgreSQL;

Основной поток в Node-Red:

При первом запуске docker-compose необходимо настроить блок My Yandex Station станции, потоки добавляются автоматически.

Настройка блока Yandex Station:

Если станция имеет статический IP адрес лучше использовать режим Manual для наиболее быстрого обнаружения станции.

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

Цепочка, которая начинается с блока alice_fun, срабатывает в случайное время, кратное заданной в настройках блока задержке, и Алиса произносит случайную фразу из списка Fun без ожидания ответа. В блоке rand3 можно установить ограничение, чтобы Алиса не болтала ночью.

Для того чтобы Алиса произносила фразы последовательно и не прерывала сама себя создан подпоток Say by case:

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

Для более удобного добавления новых фраз в БД присутствует поток UI. Так же добавлен UI управления воспроизведением, спасибо twocolors.

Создание модели для распознавания лиц

В репозитории присутствует скрипт collect_images.py для сбора лиц и сохранения их в коллекцию. Я собирал примерно по 150-300 вариантов для каждого человека. Скрипт запускается следующим образом:

python3 collect_images.py -i <source> -n <face_name>

source:

  • 0 – Первая веб камера

  • Поток ("rtsp://192.168.1.86:8554/unicast")

  • Расположение медиа файла ("raw/IMG_2404.MOV")

face_name: Имя поддиректории куда будут сохранены выделенные лица

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

Полученные коллекции необходимо добавить в Google Teachable Machine, обучить и скачать готовую модель в формате Keras h5. Для проверки модели можно показывать фото участников в камеру.

Модель в формате h5 вместе с файлом labels.txt необходимо скопировать в директорию со скриптом alice_has_fun.py. В файле labels.txt первый столбец содержит порядковый номер класса, его можно убрать.

Для запуска Node-Red, PorstgerSQL и Mosquitto необходимо выполнить:

docker-compose up -d

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

Описание параметров config.json:

{
"mqtt_pub": true,
"show_camera": false,
"input_source": 0,
"frame_recognition_rate": 4,
"publish_min_dalay": 1,
"camera_w": 1080,
"camera_h": 720,
"mqtt_broker": "127.0.0.1",
"mqtt_port": 11883,
"save_on_detect": true,
"draw_rect": true,
"min_predict_threshold": 65
}

Параметр

Назначение

mqtt_pub

Елси True то рзультаты не публикуются в MQTT брокер

show_camera

Елси True то с помощью cv2.imshow отображается видео из источника

input_source

Число (0 это первая веб камера), адрес потока ("rtsp://192.168.1.86:8554/unicast") или расположение видео файла ("raw/IMG_2404.MOV")

frame_recognition_rate

Частота распознавания кадров в секунду

publish_min_dalay

Задержка перед публикацией, публикуются средние значения из распознаных кадров

camera_w

Ширина видео для устройств поддерживающих задание разрешения видео

camera_h

Высота видео для устройств поддерживающих задание разрешения видео

mqtt_broker

Адрес MQTT брокера

mqtt_port

Порт MQTT брокера

save_on_detect

Помимо публикации в брокер также будет сохранен кадр в директорию on_detect

draw_rect

выделять лица

min_predict_threshold

минимальный процент совпадения для публикации

После того как лица выделены и выполнено предсказание, его результат публикуется в MQTT брокер. Если частота распознавания выше чем частота публикации, например, распознавание 4 кадра в секунду, а публикация 1 раз в секунду, то публикуется наибольшее значение предсказаний преодолевших порог.

Запуск:

python3 alice_has_fun.py

Проверка работоспособности

Если все настроено правильно в консоли будут появляться сообщения вроде:

1/1 [==============================] - 0s 44ms/step

1/1 [==============================] - 0s 48ms/step

1/1 [==============================] - 0s 45ms/step

1/1 [==============================] - 0s 42ms/step

Creating Images........../on_detect/2022-11-13/2022-11-13_13_59_59.jpg

Send {"Бэм": 71.39} to topic for_alice/peoples

1/1 [==============================] - 0s 45ms/step

1/1 [==============================] - 0s 48ms/step

Видео демонстрация:

Исходный код проекта.

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

Комментарии (4)


  1. ilye
    14.11.2022 10:47

    Для распознавания лиц, стоит посмотреть в сторону insightface, вполне прилично работает


    1. guinmoon Автор
      14.11.2022 20:17

      Спасибо, посмотрю.


  1. opexu1986
    14.11.2022 12:32

    У меня вопрос: alice_has_fun.py и python можно в докер упаковать?


    1. guinmoon Автор
      14.11.2022 12:32

      Можно. Нужно ли?