Усовершенствование системы видеонаблюдения с использованием OpenCV и Telegram bot

в 20:51, , рубрики: opencv python, python, Raspberry Pi, shell scripting, telegram bots, Разработка под Linux

С чего все начиналось

Все началось с того, что я захотел установить у себя «умную» систему видеонаблюдения на Raspberry.
Хочу отдельно отметить, что для этого воспользовался несколькими статьями на Хабре. Спасибо авторам за их посты. Они реально помогли.
В итоге установил на купленном Raspberry Pi3 USB-камеру Logitech, смонтировал Яндекс.Диск и с периодичностью в 30 секунд делал снимки, которые затем копировал в папку на Яндекс.Диске.
Поигравшись с дальнейшем архивированием файлов, монтированием из отдельных снимков видео, забросил новую «игрушку» на несколько месяцев.

Продолжение истории

Пока Raspberry был выведен из продакшен, не давала покоя мысль как избавиться от большого количества снимков, которые будут скапливались на Яндекс.Диске при работе решения. Хотелось оптимизировать реализованное решение…

Идея

Немного погуглив, выработал такое усовершенствование: копировать на Яндекс.Диск только те изображения, на которых будет выявлено присутствие человека или изображение на снимке будет изменено, например, сначала на изображении дверь закрыта, а затем открыта. При этом отправлять при выявлении таких событий уведомление, используя Telegram. Telegram был выбран вместо почты, т.к. обеспечивает доставку сообщений в режиме real-time, плюс, это модно.
Разработку решил выполнять на Python и bash.

Реализация

Для выявления присутствия человека была выбрана библиотека OpenCV, которая в числе прочего, способна определить наличие предмета на снимке, например, лица человека. Так же данная библиотека предлагает реализацию большого количества алгоритмов Machine Learning.
Пример кода на Python ниже. Использовал один из готовых xml для определения лица (haarcascade_frontalface_default.xml).

import cv2
import sys

imagePath = sys.argv[1]
cascPath = sys.argv[2]

faceCascade = cv2.CascadeClassifier(cascPath)

image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

faces = faceCascade.detectMultiScale(
    gray,
    scaleFactor=1.3,
    minNeighbors=5,
    minSize=(30, 30),
    flags = cv2.cv.CV_HAAR_SCALE_IMAGE
)

if(len(faces)>0):
 print("Found {0} faces!".format(len(faces)))
else:
 print("Not found")

Определение изменений на снимке оказалось не совсем тривиальной задачей, к тому же на Raspberry, хочу заметить, что у меня последняя версия – Pi3, выявление разницы (изменения) для двух снимков занимает определенное время. Покопался в Интернете, нашел несколько разных методов.
Сразу оговорюсь, что использовал готовые алгоритмы на Python, лишь немного их дорабатывал, при необходимости. Поэтому приводить коды не стал.

1. Начал с функции subtract из библиотеки OpenCV.

diff=cv2.subtract(img2,img1)

2. Попробовал определять евклидово и манхеттенское расстояние с использованием scipy.
3. Поигрался с библиотекой PIL.
Попробовав эти варианты, остановился на определении разницы в размере файлов между двумя изображениями в процентном отношении. Реализовал этот «подход» в shell-скрипте. Этот метод оказался самым производительным из опробованных, что неудивительно. Разумеется, о высокой точности пока говорить не приходится, но поскольку мой планировщик cron настроен на периодическую съемку, которая выполняется каждые 30 секунд, то позволить себе лишние 7-8 секунд на выявление разницы, счел слишком расточительным. У меня уже определение лица «съедает» около 5 секунд (с учетом невысокого разрешения съемки).
Небольшой кусочек shell-скрипта ниже.

f1=`stat -c%s "$prev_file"`
f2=`stat -c%s "$new_file"`

if [[ $f1 -le $f2 ]];then
 top=$f1
 base=$f2
else
 top=$f2
 base=$f1
fi

percentage=$(( (100-(100*top / base)) ))
echo "Difference is $percentage%"

if(($percentage >= $hurdle));then
 changed=0
 echo "Big change"
else
 echo "Small change"
fi

Интеграция с Telegram

Интеграция с Telegram уже достаточно описана. Я выполнил необходимые шаги, зарегистрировал бота, получил токен.
Затем написал небольшой скрипт на Python, который отправляет мне сообщение от созданного telegram бота. Сообщение — один из параметров скрипта, который указываю при его вызове.

import sys

import telepot
bot = telepot.Bot('###############################')
#bot.getMe()

#from pprint import pprint
#response = bot.getUpdates()
#pprint(response)

#bot.sendMessage(########, 'Alarm from Telegram bot!')
bot.sendMessage(########, sys.argv[1])

Алгоритм решения

Алгоритм решения реализовал на shell-скрипт, который последовательно выполняет съемку, затем анализирует есть ли изменения в полученных изображениям, выявляет лицо на снимке и отправляет сообщение от созданного Telegram бота с определенным сообщением, если выявлено изменение или обнаружено лицо. Если выявлено лицо или изменение, то файл копируется на Яндекс.Диск.

Ниже приведу только часть скрипта, которая отражает вызовы python-скриптов.

#! /bin/bash

#...

face=$(python face_detect.py "$new_file" haarcascade_frontalface_default.xml 2>&1)
echo "$face"
if [[ $face != "Not found" ]];then
 ffound=0
 echo "Faces found"
else
 echo "Faces does not found"
fi
echo "----------"

echo "Changes: $changed"
echo "Faces found: $ffound"
echo "----------"
#=====================Processing=========================================

now=$(date +"%Y-%m-%d_%H%M")
# 1. Copy
if [ $changed == 0 ] || [ $ffound == 0 ];then
 cp "$new_file" "/home/pi/webcam/$now---$new_file" 
 &&  echo "File copied."
else
 echo "All Ok."
fi
# 2. Rename
cd /home/pi 
&& mv "$new_file" previous.jpg 
&& echo "File renamed."
# 3. Send telegram nessage
if [ $changed == 0 ] && [ $ffound == 0 ];then
 python send_telegram.py 'Alarm: Changes & Faces detected!' 
 && echo "Alarm: Changes & Faces detected!"
elif [ $changed == 1 ] && [ $ffound == 0 ];then
 python send_telegram.py 'Alarm: Faces detected!' 
 && echo "Alarm: Faces detected!"
elif [ $changed == 0 ] && [ $ffound == 1 ];then
 python send_telegram.py 'Alarm: Changes detected!' 
 && echo "Alarm: Changes detected!"
else 
 echo "Nothing to send."
fi

#...

exit 0

Результаты

Ниже представлю некоторые результаты работы решения.
1. Результаты определения лиц на фото. Свои фото прикладывать не стал.
image

image
2. Сообщения от Telegram бота.
image
3. Фото на Яндекс.Диске
image

Выводы и дальнейшие шаги

Тестирование нового решения выявило ряд проблем:

Определение лица на снимке и контроль изменений – штука, требующая тонкой настройки. С этим еще придется повозиться, чтобы, например, мой бот не спамил меня сообщениями об обнаружении лиц, которые нормальному человеку никогда не вздумается считать лицом.

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

Дальнейшие исследования/тестирование решения будут продолжены…

Автор: Tkachev_KV

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js