| 

.NET C# Java Javascript Exception

7
TL;DR: Wer einfach nur RaspiFastCamD haben will: Hier gibt es die (mglw. veraltete Binärversion). Wow, der letzte Teil ist schon wieder lange her. Aber ich war nicht untätig, für die weitere Arbeit an meinem Roboter musste erst ein Software-Problem behoben ...

TL;DR: Wer einfach nur RaspiFastCamD haben will: Hier gibt es die (mglw. veraltete Binärversion).

Wow, der letzte Teil ist schon wieder lange her. Aber ich war nicht untätig, für die weitere Arbeit an meinem Roboter musste erst ein Software-Problem behoben werden:

Ich habe mir ja die Rasperry Camera gekauft, und diese sollte für die Navigation benutzt werden. Dazu muss natürlich irgendwie das Kamera-Bild ausgewertet werden. Nach ein wenig Suchen habe ich dann OpenCV gefunden, eine Bibliothek, die genau dafür gemacht wurde (CV steht für „Computer Vision“). Nur wie das Bild der Kamera in OpenCV bekommen? Bei USB-Kameras, die V4L (Video for Linux) unterstützen, ist das recht einfach, dort kann OpenCV die Bilder einfach abholen.

Leider unterstützt die Rasperry Camera überhaupt kein standardisiertes Protokoll, sondern es werden nur zwei Anwendungen mitgeliefert, die mit der Kamera sprechen können, raspistill und raspivid. Die erste macht JPEG-Fotos, die zweite H.264-Videos. Das funktioniert auch tadellos, ist aber nicht wirklich zu gebrauchen: Ein komplettes Video mit 30fps kann ich nicht gebrauchen, ich brauch auf Anfrage genau einen Frame. Leider ist raspistill aber viel zu langsam: Bei jeden Foto wird die Verbindung zu Kamera neu aufgebaut, und danach wieder getrennt. Zudem muss jedes mal die Belichtung neu berechnet werden. Damit kommt man maximal auf ein Bild pro Sekunde, und das ist einfach zu wenig.

Auftritt RaspiFastCamD: Doch der Source-Code von raspistill ist auf GitHub, also machen wir es einfach selber besser! Ich habe mich also die letzte Zeit damit beschäftigt, raspistill umzuschreiben, damit es meinen Anforderungen besser entsprach. Ich hatte vor allem zwei Anforderungen:

  • Nicht jedes Mal die Verbindung zur Kamera neu aufbauen
  • Möglichst viele Bilder pro Sekunde, aber auf Abruf, nicht automatisch

Das Konzept hinter RaspiFastCamD ist recht einfach:

  • Das Programm läuft im Hintergrund (als Dämon, daher das „d“ im Namen) und hält die Verbindung zu Kamera offen
  • Wenn der Benutzer ein USR1 Signal an den Prozess schickt wird ein Foto gemacht
  • Bei einem KILL oder INT Signal wird die Verbindung abgebaut und der Prozess beendet.

Ich habe RaspiFastCamD als Fork von RaspiStill entwickelt, im Grunde habe ich nur eine Menge unnötiger Funktionen ausgebaut (wie EXIF-Tags), und das Programm so umgeschrieben, dass es dauerhaft im „Timeleapse“ Modus ist (der schon in raspistill enthalten ist), aber vor jedem Foto auf ein USR1 Signal wartet. Wer sich dafür interessiert, wie das genau funktioniert möge sich den Code ansehen, der unten verlinkt ist. Ich weise darauf hin, dass ich keine große Ahnung von C habe, das meiste ist trial und error gewesen… (Das war sogar mein erstes Linux Programm!)

Dennoch finde ich die Ergebnisse recht beeindruckend: Um die Latenzzeit des Programms zu bestimmen, habe ich mit einem kleinen C# Programm über SSH den Befehl zum Foto machen an die Kamera geschickt, und gleichzeitig eine Uhr auf dem Bildschirm hoch zählen lassen. Auf diese Weise konnte ich auf dem Foto ungefähr die Latenz der Kamera ablesen. Die Ergebnisse:

  • RaspiStill: ~500ms
  • RapiFastCamD: <10ms

Test mit raspistillTatsächlich war RaspiFastCamD so schnell, dass der Zähler noch gar nicht gestartet war! Da ich die Latenz von C#->Bildschirm auf ~10ms schätzen würde (eher weniger) und davon noch die Latenz der Auslösung, die über SSH und WLAN(!) passierte, abgeht, ist die Verzögerung schon beeindruckend gering. Mit besserem Equipment könnte man die sicher noch besser messen. Vielleicht sind hier sogar noch ganz andere Anwendungszwecke möglich?

So, genug geredet, wo ist das Ding den nun? Der komplette Code ist ist auf BitBucket als Fork des userland-Repos zu finden, und zwar hier: RaspiFastCamD-Source. Wer den Code selber übersetzen möchte, benutze diese Schritte (auf dem Pi):

sudo apt-get install git gcc build-essential cmake
git clone https://bitbucket.org/niklas_rother/rasperry-pi-userland.git
cd userland
mkdir build
cd build
sudo cmake -DCMAKE_BUILD_TYPE=Release ..
sudo make

Das ganze dauert ca. ein halbe Stunde, danach liegt die Executable unter ./bin. (Die nötigen Änderungen, damit sich der Code auf dem Pi kompilieren lässt, sind bereits drin). Leider war ich nicht sehr intelligent, und habe direkt im master-Branch weiter gemacht, daher gibt es momentan evtl. ein kleines Problem weil es ein paar Änderungen in den #include Dateien im Repo auf GitHub gab (die ich schon abgerufen habe). In diesem Fall einfach die Binärversion von unten benutzen, oder im Git ein paar Commits zurückgehen :)

Wer RaspiFastCamD einfach nur benutzen möchte: Im Repo liegt auch eine (getestete), direkt lauffähige Binärversion, zusammen mit ein paar Helper-Scripts.

Die Binär-Version auf BitBucket.

Wow, das war mal wieder ein langer Blog-Eintrag. Ich habe auch lange an RaspiFastCamD gesessen, vor allem, weil ich immer nur sporadisch Zeit hatte, aber ich denke wirklich, dass mir da etwas nützliches gelungen ist. Ich weiß, dass viele Leute versuchen, OpenCV mit der Raspberry Camera zusammen zu bringen, aber ich habe noch nicht wirklich viele positive Ergebnisse im Netz gesehen. Nur Pierre Raufast scheint da schon etwas geschafft haben (womit er es schon auf den Raspberry Pi Blog geschafft hat!). Auch er hat eine der Demo-Anwendung umgeschrieben, in seinem Fall RaspiVid. Bei seinem Ansatz werden die Daten direkt im Speicher von MMAL an OpenCV weitergereicht, was wohl recht gut funktioniert (auch wenn mal noch die Farbräume auf der CPU konvertieren muss). Das ganze hat aber den Nachteil, dass der komplette OpenCV Code direkt mit RaspiVid verbunden wird, und daher in C geschrieben werden muss. Ich wollte das ganze lieber ein wenig modularer haben, auch weil ich OpenCV gerne über Python ansteuern möchte. Vielleicht lassen sich die beiden Ansätze auch noch kombinieren, bis jetzt habe ich noch nicht ausprobiert, wie viele FPS ich wirklich schaffe (10 sollten aber drin sein, ich empfehle die Daten nach /dev/shm zu schreiben, dann landen sie direkt im RAM und nicht erst auf der SD Karte).

Ich würde mich über eine Rückmeldung freuen, wenn etwas aus meiner Software wird! Patches welcome :)

programmieren tipps-und-tricks python meine-programme c raspberry-pi camera fischerpi opencv raspifastcamd
Schreibe einen Kommentar:
Themen:
raspifastcamd opencv fischerpi camera raspberry-pi c meine-programme python tipps-und-tricks programmieren
Entweder einloggen... ...oder ohne Wartezeit registrieren
Benutzername
Passwort
Passwort wiederholen
E-Mail