Удосконалення системи відеоспостереження з використанням OpenCV і Telegram bot

З чого все починалося
Все почалося з того, що я захотів встановити у себе «розумну» систему відеоспостереження на 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(########, 'from Alarm 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. і звичайно, налаштувати параметри визначення осіб на знімках.

Подальші дослідження/тестування рішення будуть продовжені…
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.