Blog (2)
Komentarze (36)
Recenzje (0)
@maciejkaczkowskiBASH: Fotopułapka z Raspberry Pi

BASH: Fotopułapka z Raspberry Pi

11.05.2014 17:22, aktualizacja: 11.05.2014 20:07

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:

  • 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

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 gsfonts
sudo apt-get --yes autoremove
sudo 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

sudo swapoff -a
sudo apt-get purge dphys-swapfile
sudo rm /var/swap

Pozostałe dodatki

sudo rm -rf /usr/share/doc/* /opt/vc/src/hello_pi/hello_video/test.h264 /home/pi/python_games
find /usr/share/locale/* -maxdepth 0 -type d |grep -v en |xargs sudo rm -rf
find /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ń.

sudo apt-get update

Do porównania obrazu użyjemy programu compare dostępnego w pakiecie ImageMagick. [code=bash]sudo apt‑get install imagemagick[/code]

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

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

#!/bin/bash
mkfs.vfat /dev/ram1 8192
mkdir -p /ramcache
mount /dev/ram1 /ramcache

któremu nadajemy uprawnienia uruchamiania [code=bash]chmod +x ramdisk.sh[/code]

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 su
echo "@reboot root /home/pi/ramdisk.sh" >> /etc/crontab
exit

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ć [code=bash]dir-listing.activate = "enable"[/code]

następnie zamykamy edytor i wykonujemy restart serwera www [code=bash]sudo /etc/init.d/lighttpd restart[/code]

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ątkowe
tmpfolder="/ramcache"
tmpnewfile="$tmpfolder/newframe.bmp"
tmpoldfile="$tmpfolder/oldframe.bmp"
tmpdiffile="$tmpfolder/difframe.bmp"
outdir="/var/www"
# długość materiału wideo, zmienna tt
tt="30"
ttt="$tt"000
# czyszczenie dysku po przekroczeniu parametru
usedspace="95"
# funkcje pozyskiwania zdjęć i wideo
execphoto="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

clean_disk()
{
  # 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
    clean_disk
  fi
  mv $tmpnewfile $tmpoldfile
done

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.

Wybrane dla Ciebie
Komentarze (23)