Arlo Videosorveglianza, basta con i falsi allarmi

Da quasi 2 anni uso con molta soddisfazione i sistemi Arlo per la videosorveglianza della mia casa.
Per chi non lo conoscesse, Arlo di Netgear, offre un sistema di domotica completa, che va dalle telecamere, alle sirene, dai campanelli alle telecamere per bambini.

Il topic di questo post e’ un tema che probabilmente sta molto a cuore a tutti i possessori di questo tipo di tecnologie (non solo di Arlo): la gestione dei falsi allarmi!
Se avete un sistema di videosorveglianza sapete sicuramente bene che, prima di chiamare la polizia all’arrivo di una notifica di allarme, e’ bene controllare prima la registrazione che lo ha generato, dato che al 99%, la causa non sara’ un tentativo di effrazione.

Stanco di questa situazione (tra l’altro, avendo un cane, vi posso garantire che i falsi allarmi sono all’ordine del giorno), mi sono provato ad inventare qualcosa costruendo un “lego” con tutte le tecnologie esistenti ad oggi.

Quello che volevo realizzare era un sistema che riuscisse, autonomamente, a filtrare i video con persone, da quelli con cani a quelli con automobili fino ad arrivare a video dovuti semplicemente al cambiamento di fattori meteorologici (vento, temporali….)

L’idea si puo’ riassumere in questo piccola ascii art:

sistema arlo casalingo
-> cloud arlo
-> API arlo
-> cloud privato
-> acquisizione video apena registrato
-> ImageAI applicato al video
-> inserimento su db influxdb
-> grafana per statistiche e allarmi
-> eventuale notifica in caso di rilevazione

Sembra complesso ma nella realta’ non lo e’ per niente, sopratutto perche’ persone intorno al mondo come noi, hanno gia’ creato piccoli pezzettini di codice che fanno tutto quello che ci servira’!

Mettiamoci all’opera!

Di cosa abbiamo bisogno?

La cosa fondamentale di cui abbiamo bisogno e’ un SERVER linux (che puo’ essere anche il vostro pc di casa o il vostro raspberry, fino ad arrivare ad una VPS in cloud).
Su di esso dobbiamo installare tutti i vari pacchetti python (hah giusto, ho basato tutto su python) che ci aiuteranno a raggiungere il nostro obiettivo ovvero:
1) python3 (almeno versione 3.5)
2) tensorflow 1.4.0 o successivo
3) opencv
4) keras
5) imageai
6) arlo python library

Sintentizzando, bastera’ lanciare questi comandi:

pip3 install -U tensorflow keras opencv-python arlo
pip3 install imageai --upgrade

Fatto questo il nostro ambiente sara’ operativo, ora sporchiamoci le mani con un po’ di codice!

from influxdb import InfluxDBClient
import os
import re
import datetime
import calendar
import warnings
import logging
from imageai.Detection import VideoObjectDetection
import os
from arlo import Arlo
import pytz
tz = pytz.timezone('Europe/Rome')
from datetime import timedelta, date
import sys
### Variables 
influxhost = "$INFLUXHOST"              #CHANGEME
influxport = "$INFLUXPORT"              #CHANGEME
influxuser = "$INFLUXUSER"              #CHANGEME
influxpassword = "$INFLUXPASSWORD"      #CHANGEME
influxdbname = "$DBARLO"                #CHANGEME
USERNAME = '$ARLOUSERNAME'              #CHANGEME
PASSWORD = '$ARLOPASSWORD'              #CHANGEME
videoinfo = None
datevideo = datetime.datetime.now()
fluxdb = InfluxDBClient(influxhost, influxport, influxuser, influxpassword, influxdbname)

prima di tutto andiamo a includere tutti i moduli che ci serviranno e andiamo a definire (ricordatevi di cambiare i valori) tutte le variabili che ci serviranno piu’ avanti.

def forSeconds(output_arrays, count_arrays, average_output_count):
        global datevideo
        global videoinfo
        try:
                count=0
                for i in average_output_count:
                        count+=1
                        json_body = [
                        {
                                "measurement": "motion",
                                "time": datevideo,
                                "tags": { "camera": videoinfo['deviceId'], "objects": "yes"  },
                                "fields": {
                                        i: "1",
                                        "videoid": videoinfo['uniqueId']
                                }
                        }]
                       fluxdb.write_points(json_body)
                if(count==0):
                        json_body = [
                        {
                                "measurement": "motion",
                                "time": datevideo,
                                "tags": { "camera": videoinfo['deviceId'], "objects": "no"  },
                                "fields": {
                                        "videoid": videoinfo['uniqueId']
                                }
                        }]
                        fluxdb.write_points(json_body)
    except Exception as e:
            print(e)

questa funzione sara’ il vero e proprio cuore di tutto, verra’ chiamata automaticamente ad ogni fine video, e aggiungera’ al db influx i dati raccolti. Ovviamente siete liberi di fargli fare quello che volete!

execution_path = os.getcwd()
fluxdb.create_database(influxdbname)
detector = VideoObjectDetection()
detector.setModelTypeAsTinyYOLOv3()
detector.setModelPath( os.path.join(execution_path , "yolo-tiny.h5"))
detector.loadModel(detection_speed="flash")

qui creiamo il db e istruiamo ImageAI a come operare una volta chiamato

try:
        arlo = Arlo(USERNAME, PASSWORD)
        today = (date.today()-timedelta(days=0)).strftime("%Y%m%d")
        library = arlo.GetLibrary(today, today)
        for recording in library:
                videoinfo = recording
                datevideo = datetime.datetime.fromtimestamp(int(recording['name'])//1000, pytz.timezone("UTC")).strftime('%Y-%m-%d %H:%M:%S')
                videofilename = datetime.datetime.fromtimestamp(int(recording['name'])//1000).strftime('%Y-%m-%d %H-%M-%S') + ' ' + recording['uniqueId'] + '.mp4'

andiamo ad iterare su tutti i video della giornata salvati dalle nostre telecamere Arlo

            if(os.path.isfile('videos/'+videofilename)==False):
                    stream = arlo.StreamRecording(recording['presignedContentUrl'])
                    with open('videos/'+videofilename, 'wb') as f:
                            for chunk in stream:
                                    f.write(chunk)
                            f.close()
                    print('Downloaded video '+videofilename+' from '+recording['createdDate']+'.')

salviamo il video

                    print(os.path.join(execution_path , 'videos/'+videofilename))
                    detections = detector.detectObjectsFromVideo(input_file_path=os.path.join(execution_path , 'videos/'+videofilename), frames_per_second=25, minimum_percentage_probability=50, save_detected_video=False, video_complete_function=forSeconds )

lanciamo ImageAI

except Exception as e:
    print(e)

e ovviamente gestiamo le eccezioni

Ecco tutto! Vi avevo detto che sarebbe stato semplice!
Al termine di questo script il vostro db influx verra’ riempito con gli oggetti riconosciuti comprensivi di data e ora.
Ovviamente voi potreste anche non voler usare un db ma farvi mandare semplicemente una mail con lo screenshot che ha generato il trigger.
Insomma l’integrazione di ImageAI con Arlo apre veramente ad un sacco di implementazioni!

Vi lascio qui sotto un po’ di link utili che mi sono serviti alla realizzazione di questo script, oltre che allo script stesso per intero!

Progetto GitHub: https://github.com/cagnulein/ArloAI

https://towardsdatascience.com/object-detection-with-10-lines-of-code-d6cb4d86f606
https://github.com/OlafenwaMoses/ImageAI
https://github.com/jeffreydwalter/arlo
https://github.com/tensorflow/tensorflow/issues/19584
https://github.com/yaroslavvb/tensorflow-community-wheels/issues/103
https://github.com/matcom/ml/releases/tag/tf-no-avx
https://github.com/OlafenwaMoses/ImageAI/releases/tag/1.0/

Ovviamente tutto cio’ sarebbe gia’ fattibile spendendo circa 1,5 euro al mese per telecamera con Arlo, ma questa e’ tutta un’altra storia…