Blog (2)
Komentarze (21)
Recenzje (0)

BASH: Fotopułapka z Raspberry Pi

Strona główna@maciejkaczkowskiBASH: Fotopułapka z Raspberry Pi
11.05.2014 17:22

Fotopułpka to urządzenie pozwalające rejestrować obraz tylko w momencie wystąpienia zdarzenia. Może być używane np do obserwacji przyrody, ochrony obiektów (np domki jednorodzinne).

W tym wpisie przedstawię jak zbudować proste urządzenie tego typu w oparciu o Raspberry Pi wraz z modułem kamery rev 1.3, które będzie wykrywać zdarzenia i rejestrować kilkusekundowy film po ich wystąpieniu.

Algorytm całego procesu będzie wyglądać następująco:

bDUgAeYD
  • pobierz nowe zdjęcie z kamery
  • jeśli istnieje poprzednie, porównaj
  • jeśli różnice na zdjęciu przekraczają zadany próg, rozpocznij nagrywanie
  • powrót do początku

Przygotowanie karty

Jako podstawy użyjemy dystrybucji Raspian w wersji 2014-01-07 lub nowszej. Na początku należy ją wyczyścić ze zbędnych elementów takich jak środowisko graficzne, przestrzeń wymiany i innych dodatków dostarczonych do dystrybucji. W sumie ponad 1GB, które użyjemy do przechowywania nagrań. Ta część bazuje na artykule Minimalist Raspberry Pi Server Image.

Usuwamy GUI - ok 700MB środowiska graficznego. Podczas tego procesu zostaną usunięte moduły, które doinstalujemy w następnych krokach

bDUgAeYJ
sudo apt-get purge xserver.* x11.* xarchiver xauth xkb-data console-setup xinit lightdm lxde.* python-tk python3-tk scratch gtk.* libgtk.* openbox libxt.* lxpanel gnome.* libqt.* libxcb.* libxfont.* lxmenu.* gvfs.* xdg-.* desktop.* tcl.* shared-mime-info penguinspuzzle omxplayer gsfontssudo apt-get --yes autoremovesudo apt-get upgrade

Usuwamy pakiety dla deweloperów ok 150MB

sudo apt-get purge gcc-4\.[0-5].*sudo apt-get purge `sudo dpkg --get-selections | grep "\-dev" | sed s/install//` gcc-4\.[0-6].* python.*sudo apt-get --yes autoremove

Wyłączamy i usuwamy przestrzeni wymiany ok 100 MB

bDUgAeYK
sudo swapoff -asudo apt-get purge dphys-swapfilesudo rm /var/swap

Pozostałe dodatki

sudo rm -rf /usr/share/doc/* /opt/vc/src/hello_pi/hello_video/test.h264 /home/pi/python_gamesfind /usr/share/locale/* -maxdepth 0 -type d |grep -v en |xargs sudo rm -rffind /usr/share/man/* -maxdepth 0 -type d |grep -Pv 'man\d' |xargs sudo rm -rf

Instalacja programów

Na początku powinniśmy zaktualizować repozytoria używane przez apt-get, w przeciwnym razie system pakietów nadal będzie korzystać z wcześniejszych ustawień.

bDUgAeYL
sudo apt-get update

Do porównania obrazu użyjemy programu compare dostępnego w pakiecie ImageMagick. sudo apt-get install imagemagick

Aby ograniczyć liczbę zapisanych danych na karcie SD, poszczególne klatki zostaną zmniejszone do rozmiaru 64x64 pikseli i będą zapisane w RAM dysku. Funkcja ta jest dostępna w naszej dystrybucji, dodamy jednie obsługę systemu plików FAT, który umożliwi nam swobodne zaalokowanie dysku o rozmiarze 8MB lub mniejszym.

sudo apt-get install dosfstools
bDUgAeYM

W katalogu /home/pi tworzymy plik ramdisk.sh o następującej zawartości

#!/bin/bashmkfs.vfat /dev/ram1 8192mkdir -p /ramcachemount /dev/ram1 /ramcache

któremu nadajemy uprawnienia uruchamiania chmod +x ramdisk.sh

Dodatkowo należy dodać ten plik podczas uruchamiania systemu. Można to wykonać na wiele sposobów, najprościej jednak będzie dopisać go do cron'a:

sudo suecho "@reboot root /home/pi/ramdisk.sh" >> /etc/crontabexit

Wynik, czyli kilkusekundowe nagrania wideo, zostaną umieszczone na serwerze www. Do tego użyjemy programu lighttpd.

sudo apt-get install lighttpd

W podstawowej konfiguracji zawiera stronę powitalną, którą usuniemy

sudo rm /var/www/*.html

a następnie aktywujemy listowanie katalogów, w tym celu edytujemy plik lighttpd.conf

sudo nano /etc/lighttpd/lighttpd.conf

na końcu pliku należy dopisać dir-listing.activate = "enable"

następnie zamykamy edytor i wykonujemy restart serwera www sudo /etc/init.d/lighttpd restart

Ponieważ BASH nie pozwala na porównywanie zmiennoprzecinkowe, a takie liczby uzyskamy używając programu compare, musimy doinstalować odpowiednią aplikację:

sudo apt-get install bc

Rejestracja obrazu

Aby pobrać obraz z kamery należy zastosować program raspistill. Z odpowiednimi parametrami pozwoli zmniejszyć plik, a tym samym przyspieszyć operację porównywania. W poniższym przykładzie jest to 64x64 pikseli. Dodatkowo wprowadzone zostało niewielkie opóźnienie 10ms (-t 10), ponieważ przy niższych parametrach program może ulec zawieszeniu.

raspistill -t 10 -e bmp -o nowyplik.bmp -w 64 -h 64

Porównanie obrazu następuje przez wykonanie programu compare. Pełna specyfikacja tego modułu znajduje się na stronie programu. Użyjemy tylko jednego z podanych tam przykładów:

compare -metric PSNR rose.jpg reconstruct.jpg difference.png

Przy wykonaniu porównania w trybie pomiaru PSNR uzyskamy podobieństwo obrazów wyrażone w dB - im wyższa wartość tym bardziej podobne są do siebie zdjęcia, wynik inf będzie oznaczać nieskończoność (zdjęcia takie same). Jeżeli użyjemy większego obrazka, otrzymamy dokładniejszą wartość, ale spowoduje to, że powstaną większe opóźnienia pomiędzy kolejnymi klatkami. W gotowym programie jako próg ustawiona została wartość 27dB

Jeżeli wartość PSNR będzie mniejsza niż 27dB rozpoczynamy nagrywanie przez program raspivid

raspivid -t 30000 -w 1280 -h 720 -b 1500000 -fps 15 -o /var/www/plik.h264

parametr -t określa czas, po którym program automatycznie się zakończy, w tym przypadku jest to 30 sekund. Parametry -w -h to odpowiednio szerokość i wysokość. Parametr -b to bitrate, w zależności od szybkości karty możemy zmieniać parametry przepływności wideo. Wartość 1500000 odpowiada 1.5Mbps. FPS to liczba klatek na sekundę, a -o plik wynikowy, który w tym przypadku jest umieszczony bezpośrednio w katalogu serwera www. Warto tutaj zaznaczyć, że plik wynikowy to strumień h264 (nie kontener multimedialny). Pliki w tym formacie bez problemu odtworzymy w popularnym VLC.

Po zapętleniu w/w kroków otrzymamy prosty system rejestracji obrazów, wyzwalany w momencie wystąpienia zmiany w obrazie.

Całość w formie programu, wraz z funkcją okresowego czyszczenia karty, wygląda następująco:

#!/bin/bash#wartości początkowetmpfolder="/ramcache"tmpnewfile="$tmpfolder/newframe.bmp"tmpoldfile="$tmpfolder/oldframe.bmp"tmpdiffile="$tmpfolder/difframe.bmp"outdir="/var/www"# długość materiału wideo, zmienna tttt="30"ttt="$tt"000# czyszczenie dysku po przekroczeniu parametruusedspace="95"# funkcje pozyskiwania zdjęć i wideoexecphoto="raspistill -t 10 -e bmp -o $tmpnewfile -w 64 -h 64"execvideo="raspivid -t $ttt -w 1280 -h 720 -b 1500000 -fps 15 -o "

#usuń stare pliki rm $tmpnewfile rm $tmpoldfile rm $tmpdiffile #zamknij wszystkie procesy odpowiadające za kamerę killall -9 raspivid killall -9 raspistill

cleandisk() { # zajętość procentowa dysku used=df -h | grep rootfs | while read a b c d e f; do echo $e | sed "s/%//"; done # jeśli większa od zadeklarowanej stałej check=echo "$used>$usedspace" | bc if  "$check" == "1" ; then # usuń najstarsze ls -1 -tr $outdir | head -10 | while read fn; do  rm $outdir/$fn done  fi }

# pętla nieskończona while true; do  eval $execphoto # jeśli nie było wcześniej obrazu, to skopiuj nowy jako stary # a wynikiem porównania będzie "inf" if [ ! -f $tmpoldfile ]; then cp $tmpnewfile $tmpoldfile  fi

img=compare -metric PSNR $tmpnewfile $tmpoldfile $tmpdiffile 2>&1 # jeśli te same obrazy if  "$img" == "inf" ; then img='100' fi  # w bashu nie ma możliwości sprawdzenia liczb zmiennoprzecinkowych img=echo "$img<27" | bc if  "$img" == "1" ; then dt=date +%Y-%m-%d-%H-%M-%S cp $tmpnewfile $outdir/$dt.bmp eval "$execvideo $outdir/$dt.h264" # pobierz nowa klatkę, ponieważ w czasie tt mogło coś się zmienić eval $execphoto cleandisk fi  mv $tmpnewfile $tmpoldfile done /code

Powyższy kod możemy umieścić w pliku, który dodajemy do uruchamiania przy starcie. Przy każdym uruchomieniu naszego Raspberry Pi rozpocznie się nagrywanie.

bDUgAeZz