Używamy plików cookies (tzw. ciasteczka) by spersonalizować treść i ogłoszenia oraz by analizować ruch na stronie.  W sposób automatyczny dzielimy się informacjami o Twoim użyciu tego portalu z dostawcami ogłoszeń, którzy mogą połączyć te informacje z informacjami, które im udzieliłaś/łeś lub, które sami zebrali. Korzystanie z witryny bez zmiany ustawień dotyczących cookies oznacza, że będą one zamieszczane w Państwa urządzeniu końcowym.  Możecie Państwo dokonać w każdym czasie zmiany ustawień dotyczących cookies zmieniając opcje przeglądarki.

Kamera jako czujnik otwarcia bramy

Przed ułożeniem kostki brukowej na podjeździe doprowadziłem 1 skrętkę do zewnętrznego ogrodzenia.  2 żyły zajął elektrozaczep, 4 videofon, 2 zdalne otwieranie bramy wjazdowej.  Koniec.  Nie ma do czego podłączyć czujników wskazujących że brama jest otwarta.  Zdarzyło się więc kilkakrotnie, że po wieczornym wyjeździe gości działka pozostawała niezabezpieczona przez całą noc.  Niby nic, ale jest dyskomfort... i pole do poprawy!

Pomyślałem ostatnio, że przecież kamera, która wisi od strony wjazdu, rejestruje stale obraz bramy.  Musi się więc dać oprogramować rozpoznawanie otwarcia wrót. Zacząłem przeglądać różne biblioteki i trochę ugrzęzłem.  Wykrywanie krawędzi, rejestrowanie zmian... wszystko to wyższa matematyka.  Stan otwarcia bramy nie jest wart takich przygotowań i poszukiwań.  Ostatecznie jednak udało mi się znaleźć mocno uproszczone rozwiązanie, do którego wystarczy biblioteka GD do PHP i kilka prostych wyliczeń.  Oto, co robię:

1. Co minutę skrypt na RPi pobiera obraz 640x480 z kamery

2. Z obrazu wycinane są 4 próbki 15x15 w obszarach przed i za bramą oraz z początku i z końca bramy:

gate samples

3. Obrazy te są reskalowane z resamplingiem do pojedynczych pixeli (obrazów 1x1)

4. Z owych pod-sampli odczytywany jest kolor

5. Obliczana jest odległość (różnica) między kolorem próbki z ogrodzenia przed bramą a początkiem bramy oraz między kolorem próbki z ogrodzenia za bramą i końcem bramy.

6. Jeśli różnice te przekraczają określony próg, oznacza to, że kolory w miejscu bramy różnią się znacznie od kolorów ogrodzenia, co oznacza, że przestrzeń bramy jest otwarta.

7.  Efekt zapisywany jest w pliku txt, do wykorzystania w innych aplikacjach.

 

Idea jest prosta, a jak ze skutecznością?

 

Otóż - jest całkiem dobrze.  Oczywiście, nie jest to system reagujący błyskawicznie, jest też podatny na zakłócenia, jak choćby cień domu pokazany na poniższym obrazku.  Po kilku dniach obserwacji i dostrajania progów, wszystko działa całkiem zadowalająco.  

Trudnością, z którą sobie poradziłem, jest spłaszczenie palety barw w godzinach wieczornych i tym samym zmniejszenie różnic w kolorach przy otwartej i zamkniętej bramie.  Poradziłem sobie z problemem resamplując cały obraz do 1 pixela i obliczając jego jasność.  Przy 'ciemnym' obrazie (prób ustalony doświadczalnie), wymagam niższych różnic między próbkami obrazu, by stwierdzić, że brama jest otwarta:

gate eveningCapture

Problemem, z którym sobie NIE poradziłem, są sytuacje, w których przy intensywnym słońcu na płot rzucany jest cień domu lub drzew.  Odczyty są wtedy przekłamane.  Docelowo mógłbym wyliczyć w oparciu o jakąś próbkę obrazu stan 'znacznego nasłonecznienia' i podnieść progi wymaganej różnicy między próbkami.  Cóż, dobrze, że jest pole do poprawy.  Oto obraz z cieniem domu, pokazujący, na czym polega problem:

gate shadow problem

Żeby nie być gołosłownym, na dole artykułu zamieszczam kod.  Dla chcących czytać przedstawię kilka komentarzy:

1. Zaczynamy od wczytania obrazu funkcją $image = imagecreatefromjpeg("http://XXX.XXX.XXX.XXX/cgi-bin/snapshot.cgi")

2. Kopiujemy 4 próbki funkcją imagecopy($sample, $image, 0, 0, x, y, $cropSize, $cropSize)

3. Downsamplujemy próbki do pod-próbek o rozmiarach 1x1 funkcją imagecopyresampled($pixel, $sample, 0, 0, 0, 0, 1, 1, $cropSize, $cropSize)

4. Odczytujemy nr koloru 1 pixela w sub-próbce w tablicy kolorów obrazka $pixel komendą $color = imagecolorat($pixel, 0,0)

5. Odczytujemy parametry (współrzędne rgb) koloru komendą imagecolorsforindex($pixel, $color)

6. Obliczamy 'odległość' w przestrzeni rgb pomiędzy wybranymi próbkami jako pierwiastek sumy kwadratów

W załączonym pliku znajdują się jeszcze funkcje do zapisu wyników każdego odczytu do pliku csv, czy też wysyłania maila przy zmianie statusu bramy.  Nie usuwałem tych linii kodu, jako że mogą się przydać przy testowaniu. Największa 'wykomentowana' część powoduje wygenerowania obrazu z naniesionymi kwadratami oznaczającymi obszary próbek i z wyliczeniami różnic między próbkami.  

Oto skrytp: cam.php