Обновленная версия этой истории доступна бесплатно в блоге Platypush.

Запуск событий, основанный на присутствии людей, долгое время был мечтой многих компьютерных фанатов и самодельных автоматов. Например, интересное приложение - включить или выключить свет в вашем доме, когда вы входите в гостиную или выходите из нее. Большинство решений для решения подобных проблем, даже более высокотехнологичные решения, такие как датчики оттенка Philips, обнаруживают движение, а не фактическое присутствие людей - это означает, что свет выключается, когда вы ложитесь на диван, как будто ленивец. Возможность выключить музыку и / или телевизор, когда вы выходите из комнаты и направляетесь в свою спальню, без хлопот с выключением всех кнопок, также является интересным следствием. Еще одно интересное приложение - обнаружение присутствия людей в вашей комнате, пока вас нет дома.

Тепловизионные камеры в сочетании с глубокими нейронными сетями - гораздо более надежная стратегия для фактического обнаружения людей. В отличие от датчиков движения, они обнаруживают присутствие людей, даже если они не двигаются. И, в отличие от оптических камер, они обнаруживают тела, измеряя тепло, которое они излучают в виде инфракрасного излучения, и поэтому намного более надежны - их чувствительность не зависит от условий освещения, положения цели или цвета. . Прежде чем исследовать решение с тепловизионной камерой, я некоторое время пытался построить модель, которая вместо этого полагалась на оптические изображения с традиционной веб-камеры. Различия ошеломляют: я обучил оптическую модель на более чем десяти тысячах изображений 640x480, снятых в течение недели при различных условиях освещения, в то время как я обучил тепловизионную модель на наборе данных из 900 изображений 24x32, снятых в течение одного дня. Даже с более сложной сетевой архитектурой точность оптической модели не превышает 91% при обнаружении присутствия людей, в то время как тепловая модель обеспечивает точность около 99% за один этап обучения более простой нейронной сети. Несмотря на высокий потенциал, на рынке не так много предложений - были проведены некоторые исследования по этой теме (если вы погуглите «тепловизионная камера для обнаружения людей», вы в основном найдете исследовательские статьи) и несколько высококачественных и дорогих продуктов для профессиональное наблюдение. Поскольку у меня дома не было готовых решений, я решил взять на себя ответственность и создать собственное решение, чтобы оно могло быть легко воспроизведено кем угодно.

Аппаратное обеспечение

  • RaspberryPi (стоимость: около 35 долларов). Теоретически любая модель должна работать, но, вероятно, не стоит использовать одноядерный RaspberryPi Zero для задач машинного обучения - сама задача не очень дорогая (мы будем использовать Raspberry только для выполнения прогнозов на обученной модели, не для обучения модели), но на Zero может возникнуть некоторая задержка. Любая более производительная модель должна хорошо работать.
  • Тепловизор. В этом проекте я использовал камеру Pimoroni MLX90640 (стоимость: 55 долларов), поскольку она относительно дешевая, проста в установке и дает хорошие результаты. Эта камера выпускается в стандартной (55 °) и широкоугольной (110 °) версиях. Я использовал широкоугольную модель, поскольку камера контролирует большую гостиную, но учтите, что обе имеют одинаковое разрешение (32x24 пикселя), поэтому более широкий угол приводит к снижению пространственного разрешения. Если вы хотите использовать другую тепловизионную камеру, вам не нужно ничего менять, если она поставляется с программным интерфейсом для RaspberryPi и совместима с platypush.
  • Если вы использовали камеру Breakout, я лично советую установить ее на что-то вроде Breakout Garden (стоимость: 10–14 долларов), так как это позволяет легко установить ее поверх RaspberryPi без необходимости пайки.

Если у вас есть Breakout Garden, настроить MLX90640 на RaspberryPi очень просто. Установите Breakout Garden поверх RaspberryPi. Вставьте разъем камеры в слот I2C. Загрузите RaspberryPi. Выполнено.

Программное обеспечение

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

Программная поддержка тепловизора требует немного доработки. MLX90640 не имеет (пока) готового к использованию интерфейса Python, но для него предусмотрен драйвер с открытым исходным кодом C ++. Инструкция по установке:

# Install the dependencies
[sudo] apt-get install libi2c-dev
# Enable the I2C interface
echo dtparam=i2c_arm=on | sudo tee -a /boot/config.txt
# It's advised to configure the SPI bus baud rate to
# 400kHz to support the higher throughput of the sensor
echo dtparam=i2c1_baudrate=400000 | sudo tee -a /boot/config.txt
# A reboot is required here if you didn't have the
# options above enabled in your /boot/config.txt
# Clone the driver's codebase
git clone https://github.com/pimoroni/mlx90640-library
cd mlx90640-library
# Compile the rawrgb example
make clean
make I2C_MODE=LINUX examples/rawrgb

Если все прошло хорошо, вы должны увидеть исполняемый файл с именем rawrgb в каталоге examples. Если вы запустите его, вы должны увидеть кучу двоичных данных - это необработанное двоичное представление кадров, снятых камерой. Запомните, где он находится, или переместите его в специальную папку bin, так как это исполняемый файл, который platypush будет использовать для взаимодействия с модулем камеры.

В этом посте предполагается, что вы уже установили и настроили platypush в своей системе. Если нет, перейдите к моему сообщению о начале работы с platypush, странице readthedocs, странице GitHub или wiki.

Вам также понадобятся следующие зависимости Python от RaspberryPi:

# For machine learning image predictions
pip install opencv opencv-contrib-python
# For image manipulation in the MLX90640 plugin
pip install Pillow

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

# For image manipulation
pip install opencv
# Install Jupyter notebook to run the training code
pip install jupyterlab
# Then follow the instructions at https://jupyter.org/install
# Tensorflow framework for machine learning and utilities
pip install tensorflow numpy matplotlib
# Clone my repository with the image and training utilities
# and the Jupyter notebooks that we'll use for training
git clone https://github.com/BlackLight/imgdetect-utils

Фаза захвата

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

camera.ir.mlx90640:
    fps: 16      # Frames per second
    rotate: 270  # Can be 0, 90, 180, 270
    rawrgb_path: /path/to/your/rawrgb

Перезапустить утконос. Если вы включили HTTP backend, вы можете проверить, можете ли вы делать снимки:

curl -XPOST -H 'Content-Type: application/json' \
     -d '{"type":"request", "action":"camera.ir.mlx90640.capture", "args": {"output_file":"~/snap.png", "scale_factor":20}}' \
      http://localhost:8008/execute?token=...

Тепловизор должен храниться в ~/snap.png. В моем случае это выглядит так, пока я нахожусь перед датчиком:

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

Если вы откроете веб-панель (http://your-host:8008), вы также увидите новую вкладку, представленную значком солнца, которую вы можете использовать для наблюдения за камерой через веб-интерфейс.

Вы также можете контролировать камеру непосредственно за пределами веб-панели, указав в браузере http://your-host:8008/camera/ir/mlx90640/stream?rotate=270&scale_factor=20.

Теперь добавьте cronjob в вашу конфигурацию platypush, чтобы делать снимки каждую минуту:

cron.ThermalCameraSnapshotCron:
    cron_expression: '* * * * *'
    actions:
        -
            action: camera.ir.mlx90640.capture
            args:
                output_file: "${__import__(’datetime’).datetime.now().strftime(’/img/folder/%Y-%m-%d_%H-%M-%S.jpg’)}"
                grayscale: true

Изображения будут храниться под /img/folder в формате YYYY-mm-dd_HH-MM-SS.jpg. Масштабный коэффициент не применяется - даже если изображения будут крошечными, они понадобятся нам только для обучения нашей модели. Кроме того, мы преобразуем изображения в оттенки серого - нейронная сеть будет легче и точнее, поскольку ей нужно будет полагаться только на одну переменную на пиксель, и ее не обманут комбинации RGB.

Перезапустите platypush и убедитесь, что каждую минуту в вашем каталоге изображений создается новое изображение. Дайте ему поработать несколько часов или дней, пока вы не будете удовлетворены количеством образцов. Постарайтесь сбалансировать количество фотографий, на которых нет людей в комнате, и тех, на которых есть люди в комнате, стараясь охватить как можно больше случаев - например, сидя, стоя в разных точках комнаты и т. д. Как я упоминал ранее, в моем случае мне нужно было менее 1000 снимков с достаточным разнообразием для достижения уровня точности выше 99%.

Фаза маркировки

Когда вы будете довольны количеством взятых образцов, скопируйте изображения на машину, которую вы будете использовать для обучения своей модели (все они должны быть небольшими файлами JPEG весом менее 500 байт каждый). Скопируйте их в папку, в которую вы клонировали мой imgdetect-utils репозиторий:

BASEDIR=~/git_tree/imgdetect-utils
# This directory will contain your raw images
IMGDIR=$BASEDIR/datasets/ir/images
# This directory will contain the raw numpy training
# data parsed from the images
DATADIR=$BASEDIR/datasets/ir/data
mkdir -p $IMGDIR
mkdir -p $DATADIR
# Copy the images
scp pi@raspberry:/img/folder/*.jpg  $IMGDIR
# Create the labels for the images. Each label is a
# directory under $IMGDIR
mkdir $IMGDIR/negative
mkdir $IMGDIR/positive

После того, как изображения будут скопированы и каталоги для этикеток созданы, запустите сценарий label.py, предоставленный в репозитории, для интерактивной маркировки изображений:

cd $BASEDIR
python utils/label.py -d $IMGDIR --scale-factor 10

Каждое изображение откроется в новом окне, и вы можете пометить его, набрав 1 (отрицательное) или 2 (положительное):

В конце процедуры каталоги negative и positive в каталоге изображений должны быть заполнены.

Фаза обучения

Когда у нас есть все помеченные изображения, самое время обучить нашу модель. Блокнот train.ipynb Jupyter предоставляется под notebooks/ir, и он должен быть относительно понятным:

Если вам удалось правильно выполнить всю записную книжку, у вас будет файл с именем ir.pb в папке models/ir/tensorflow. Это ваш файл модели Tensorflow, теперь вы можете скопировать его в RaspberryPi и использовать для прогнозирования:

scp $BASEDIR/models/ir/tensorflow/ir.pb pi@raspberry:/home/pi/models

Обнаруживать людей в комнате

Замените содержимое ThermalCameraSnapshotCron, которое мы ранее создали, логикой, которая делает снимки через запланированные интервалы и использует модель, которую мы только что обучили, чтобы предсказать, есть ли люди в комнате или нет, с помощью platypush MlCv plugin.

Вы можете реализовать любую логику в procedure.people_detected и procedure.no_people_detected. Эти процедуры будут вызваны только при изменении статуса по сравнению с предыдущим наблюдением. Например, простая логика для включения или выключения света, когда кто-то входит / выходит из комнаты:

procedure.sync.people_detected:
    - action: light.hue.on
procedure.sync.no_people_detected:
    - action: light.hue.off

Что дальше?

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