Сделай сам: умная камера для наблюдения за питомцами
Обучаем нейросеть на котиках.
1показ
16Kоткрытий
В серии DIY-статей «Пространство для изобретений» мы пробуем в домашних условиях разработать необычные гаджеты и оставляем все необходимые инструкции, чтобы любой желающий мог повторить наш опыт. Серию статей поддерживает Selectel — провайдер ИТ-инфраструктуры, которая помогает в решении рабочих задач и разработке личных проектов. Посмотреть, что интересного есть у провайдера, и выбрать для себя подходящие решения можно на сайте.
В этом материале Виктор Петин, разработчик электронных устройств, собирает умную камеру для наблюдения за котиками: она сфотографирует питомцев за домашними занятиями и в конце дня отправит мини-фильм хозяину в Telegram.
Зачем нужна камера
В моём частном доме с участком в шесть соток живут пять котов, к которым периодически захаживают хвостатые гости. Всегда было интересно, чем они занимаются в моё отсутствие, поэтому решил понаблюдать за котиками через камеры. А чтобы не сидеть перед экраном часами — автоматизировать процесс с помощью нейросети.
Рассказываю, что из этого вышло.
Что потребуется для сборки
Большую часть времени коты проводят на участке — там у меня уже установлена система видеонаблюдения из четырёх аналоговых камер с простым регистратором Falcon Eye, поэтому ничего нового я не покупал. Для моей задумки было важно, чтобы регистратор мог отдавать в сеть RTSP-поток для покадровой обработки видео в режиме реального времени.
Устанавливаем софт
До начала сборки камеры у меня было довольно смутное представление о работе нейросетей и особенностях компьютерного зрения: в лаборатории робототехники для детей, которой я руковожу, мы занимаемся программированием на Arduino и до этого не касались подобных проектов. Изучать область я начал с библиотеки PixelLib — она помогает определять и сегментировать объекты на изображениях, при этом разбираться в нейросетях не нужно.
Установил утилиту Virtualenv — она позволяет создавать изолированные виртуальные окружения для Python: создаёт внутри вашего проекта каталог, в который устанавливает нужную версию Python и все необходимые пакеты для приложения, фреймворка или скрипта. В результате вы получаете рабочее, полностью изолированное и переносимое окружение — это значит, что пакеты мы сможем устанавливать именно в это окружение, а не глобально.
Сначала я настроил камеры в самом щадящем режиме — один кадр в секунду. А ещё отключил на них режим «тревоги», при котором поток увеличивается до 15 кадров в секунду.
Пробую захватить поток с одной камеры и получить картинку в виде фрейма для последующей обработки. Полученную картинку прогоняю через детектор объекта (модель mask_rcnn_coco.h5, ссылка для скачивания) и сохраняю в папке, если объект (кот) обнаружен.
import os
os.environ["TF_CPP_MIN_LOG_LEVEL"] = "3"
import time
#import _thread
from pixellib.instance import instance_segmentation
import cv2
from datetime import datetime
Загрузка модели (указываю путь к скачанной модели mask_rcnn_coco.h5):
segment_frame.load_model("mask_rcnn_coco.h5")
Выбор объектов для определения (для тестирования person и cat):
Запускаю программу — опознание приемлемое, но скорость не радует: на анализ картинки уходит секунда. Это неудивительно: детектор работает с CPU. Для работы с графикой библиотеке необходима установка CUDA, а для этого нужны графическая карта NVIDIA, которой на NUC нет.
Есть пара альтернатив: можно установить OpenVINO и подключить Neural Compute Stick 2 или попробовать Nvidia Jetson Nano. У меня был Neural Compute Stick 2, поэтому пробую этот вариант.
Устанавливаю OpenVINO toolkit — открытый бесплатный набор инструментов, который помогает детектировать лицо, распознавать объекты, текст и речи. По описаниям Intel производительность OpenVINO при вычислении сетей на платформах Intel в разы выше по сравнению с популярными фреймворками, а требования памяти — значительно ниже.
Во время установки выбираю последний дистрибутив 2021.3.394 и устанавливаю Intel® Neural Compute Stick 2. OpenVINO включает в себя несколько модулей и скриптов. Сразу попробовал, как работает определение объектов. Я использовал модель mobilenet-ssd — её нужно преобразовать во внутренний формат OpenVino с помощью Model Optimizer.
Перед запуском примера с обученной моделью убедитесь, что она преобразована в формат механизма вывода (* .xml + * .bin) с помощью инструмента Model Optimizer.
Изображения сохраняются в папках cam/. Скорость хорошая — для двух камер при частоте 5 кадров в секунду задержек нет. Но получается слишком много фото, поэтому поток я уменьшил до 1 кадра в секунду.
Обязательно делаю автозагрузку скрипта. Создаю файл autoupload.sh следующего содержания:
Для остальных камер — по аналогии. Показалось, что фото будет много, поэтому выбрал скорость 10 кадров в секунду. Команды помещаю в cron (запуск в конце дня — в 18:00) для формирования файлов cam-.mp4.
Теперь настраиваю отправку файлов в Telegram. Создаю телеграм-бота: пишу пользователю @BotFather и придумываю имя. В ответ приходит сообщение с токеном для http api — его нужно сохранить.
Создаю группу, добавляю в неё бота, устанавливаю библиотеку:
pip3 install pytelegrambotapi
И пишу программу:
import telebot
from telebot import types
from datetime import datetime, timedelta
from pathlib import Path
keyboard1 = [["","Камера 1","Камера 2","Камера 3","Камера 4","Не надо"],["","cam1","cam2","cam3","cam4","no"]]
bot = telebot.TeleBot('your-token');
@bot.message_handler(content_types=['text', 'document', 'audio'])
def get_text_messages(message):
chatId=message.chat.id
print(chatId)
key_1=[0,0,0,0,0,0]
ftime=datetime.now()
print(ftime.day," ",ftime.hour)
day=ftime.strftime("%d-%m-%Y")
if message.text == "/help":
bot.send_message(message.from_user.id, "Привет, здесь ты можешь посмотреть, что делали мои котики за день 9:00–18:00. Набери /video")
elif message.text == "/video":
msg="здесь ты можешь посмотреть, что делали мои котики за день 9:00–18:00"+day
bot.send_message(message.from_user.id, msg)
keyboard = types.InlineKeyboardMarkup(); # клавиатура
for i in range(1,6):
#кнопка
key_1[i] = types.InlineKeyboardButton(text=keyboard1[0][i], callback_data=keyboard1[1][i]);
#добавляем кнопку в клавиатуру
keyboard.add(key_1[i]);
bot.send_message(message.from_user.id, "Выбери камеру", reply_markup=keyboard)
else:
bot.send_message(message.from_user.id, "Я тебя не понимаю. Напиши /help.")
@bot.callback_query_handler(func=lambda call: True)
def callback_worker(call):
ftime=datetime.now()
day=ftime.strftime("%d-%m-%Y")
if call.data.find("cam") < 0:
bot.send_message(call.message.chat.id, 'No');
else:
if ftime.hour >= 18:
bot.send_message(call.message.chat.id, 'Видео с камеры '+call.data.replace("cam","")+'. Wait ....');
videofile = Path(call.data+'-'+day+'.mp4')
if videofile.is_file():
video = open(call.data+'-'+day+'.mp4', 'rb')
bot.send_video(call.message.chat.id, video)
bot.send_message(call.message.chat.id, "Загружено")
else:
bot.send_message(call.message.chat.id, 'Видео отсутствует !!!');
else:
bot.send_message(call.message.chat.id, 'Просмотр видео текущего дня только после 18:00, Просмотр за предыдущий день');
ftime=datetime.now()- timedelta(days=1)
dayold=ftime.strftime("%d-%m-%Y")
videofile = Path(call.data+'-'+dayold+'.mp4')
if videofile.is_file():
video = open(call.data+'-'+dayold+'.mp4', 'rb')
bot.send_video(call.message.chat.id, video)
bot.send_message(call.message.chat.id, "Загружено")
else:
bot.send_message(call.message.chat.id, 'Видео отсутствует !!!');
bot.polling(none_stop=True, interval=0)
Запуск бота (чтобы он мог отвечать на сообщения, скрипт должен быть постоянно запущен):
cd /home/petin/python3_prgs_1/OpenVino01
python3 pets_send_telegram.py
Скрипт бота также добавляю в автозагрузку.
Создаю файл autoupload_telegram.sh
#!/bin/bash
cd /home/petin/python3_prgs_1/OpenVino01
python3 pets_send_telegram.py
И помещаю в автозагрузку autoupload.sh.
Обзор → Автоматически запускаемые приложения → Добавить
И указываю путь к python-скрипту.
Бот знает две команды: /help и /video. Когда просишь видео — открывает меню с выбором камеры. Бот присылает видео от сегодняшнего дня (если просим после шести вечера) или от вчерашнего.
Выбираем место для установки камер
Я выбирал места методом проб и ошибок, потому что не знаю точно, где котики обычно проводят время.
Подсоединяю камеры к регистратору.
В сети — роутер, регистратор, NUC по Wi-Fi. При загрузке запускаются python-скрипт получения данных с камер и детектирования, плюс скрипт бота.
Захожу в Telegram, выбираю камеру и… начинаю смотреть за котиками.
Я доволен результатом — теперь могу медитировать, наблюдая за своими питомцами.
До совершенства пока далеко: хвостатые постоянно меняют места отдыха и разбредаются, ловить их на большом участке непросто. К тому же появились новые «хотелки»: здорово было бы получать видео по каждому коту — для этого нужно обучить модель их различать. Занялся этим сразу.
Первым делом решил собрать фотографии питомцев: для тренировки сети нужно минимум по 300 фото каждого кота и по 100 — для тестирования. При этом коты не хотели фотографироваться в разных позах, так что после нескольких дней съёмок я собрал всего 314 снимков.
Выделил объекты на фото и пометил их (использую программу labelme):
sudo pip3 install labelme
Для каждой фотографии создаётся файл json.
Разделяю фото в папки train и test и запускаю скрипт для обучения модели.
За 7 дней прошло 25 шагов тренировки из 300 — не очень-то быстро. Ускориться помогут либо мощное железо, либо облачные сервисы с графическими процессорами. Например, серверы с GPU от Selectel: провайдер предлагает мощную ресурсную базу, с которой время тренировки удастся сократить с нескольких недель — до дней или даже часов.
Вот такую конфигурацию служба поддержки Selectel подобрала для меня:
На сервере уже была установлена заказанная мной ОС Ubuntu 20.04. Устанавливаю CUDA по этой инструкции и библиотеку pixellib.
Install the latest version of tensorflow(Tensorflow 2.0+) with:
pip3 install tensorflow-gpu
pip3 install imgaug
pip3 install pixellib --upgrade
Сделал много дополнительных фотографий, разделил их на две папки и разметил, как предыдущие в программе labelme. Загрузил набор данных на сервер.
Для обучения нашей модели будем применять методику трансферного обучения, используя базовую модель mask_rcnn_coco.h5, обученную на 80 категориях объектов.
Модель готова, теперь её можно использовать в проекте.
За месяц аренды сервера для своей задачи я бы потратил 25 600 рублей. Целого сервера для одного пет-проекта «слишком много»: арендовать его можно совместно с друзьями, чтобы по очереди учить модели для разных задач.
Хозяин: делает систему видеонаблюдения за котами, медитирует на них.
Коты: делятся на группы А и Б, и пока группа А отвлекает внимание хозяина, валяясь, потягиваясь и вылизываясь под камерами, группа Б проникает на кухню и взламывает холодильник.
Хозяин: делает систему видеонаблюдения за котами, медитирует на них.
Коты: делятся на группы А и Б, и пока группа А отвлекает внимание хозяина, валяясь, потягиваясь и вылизываясь под камерами, группа Б проникает на кухню и взламывает холодильник.
Комментарий недоступен
Такие можно ставить в гостиницах для кошек, чтобы в отъезде можно было наблюдать за ушастыми и не беспокоиться ^_^
У нас в гостинице просто стоят камеры в каждом номере. Нужны ли там такие усложнения? У автора задачи посложнее.
Наверно идеально чтобы просто приходил ответ со списком котов и временем их последнего появления на камере
камера наблюдения за питомцами.
Узко товарищи смотрите применение данного проекта не ограничено питомцами! Автору спасибо за статью познавательно показательно!