USB-Webcam

Auf dem Raspberry Pi lässt sich relativ einfach eine USB-Webcam einrichten. Damit kann man dann zum Beispiel in regelmäßigen Abständen Bilder schießen und diese auf einen Webserver hochladen. Und genau das werde ich in diesem Artikel beschreiben.

Als OS setzte ich hier Raspbian vorraus, da ich eben diese Distribution verwende. Die Software, die wir für unser Vorhaben benötigen ist fswebcam und ncftp. Also kümmern wir uns zunächst darum, dass unsere Quellen und die Pakete aktuell sind:

sudo apt-get update && sudp apt-get upgrade

Dann können wir fswebcam installieren:

sudo apt-get install fswebcam

Und anschließend ncftp:

sudo apt-get install ncftp

Falls noch nicht geschehen sollte jetzt die Webcam mit einem USB-Port verbunden werden!

Wenn nur eine Webcam am Raspberry Pi hängt, dann sollte diese als /dev/video0 eingebunden sein. Dies ist allerdings nur von Interesse, wenn man mehrere Cams betreiben möchte oder für eine eventuelle Fehlersuche, denn fswebcam benutzt die erste Kamera, die es findet.

Ob fswebcam funktioniert überprüfen wir mit dem Aufruf fswebcam image.jpg

pi@raspcam ~ $ fswebcam image.jpg
--- Opening /dev/video0...
Trying source module v4l2...
/dev/video0 opened.
No input was specified, using the first.
Adjusting resolution from 384x288 to 352x288.
--- Capturing frame...
Captured frame in 0.00 seconds.
--- Processing captured image...
Writing JPEG image to 'image.jpg'.
pi@raspcam ~ $ 

Wie man sieht, wurde ein Bild als image.jpg gespeichert. Allerdings ist das nur in einer sehr bescheidenen Auflösung passiert (384 mal 288 Pixel). Das Programm verwendet für alle Einstellugen (sogenannte ‚controls‘) seine Default-Werte und das gilt auch für solche Einstellungen wie z.B. Helligkeit und Kontrast.
Nicht alle Kameras bieten die gleichen Einstellungsmöglichkeiten und für jede Kamera und Aufnahmesituation müssen diese Parameter erst gesetzt werden.
Einen Überblick, über die unterstützen controls findet man für seine Kamera mit dem Befehl fswebcam –list-controls heraus. Hier die Ausgabe für meine Kamera, eine Logitech HD Webcam C525:

pi@raspcam ~ $ fswebcam --list-controls
--- Opening /dev/video0...
Trying source module v4l2...
/dev/video0 opened.
No input was specified, using the first.
Available Controls        Current Value   Range
------------------        -------------   -----
Brightness                140 (54%)       0 - 255
Contrast                  33 (12%)        0 - 255
Saturation                32 (12%)        0 - 255
White Balance Temperature, Auto True            True | False
Gain                      16 (6%)         0 - 255
Power Line Frequency      60 Hz           Disabled | 50 Hz | 60 Hz
White Balance Temperature 6396 (97%)      2800 - 6500
Sharpness                 25 (9%)         0 - 255
Backlight Compensation    1               0 - 1
Adjusting resolution from 384x288 to 352x288.
--- Capturing frame...
Captured frame in 0.00 seconds.
--- Processing captured image...
There are unsaved changes to the image.
pi@raspcam ~ $ 

Damit man nicht jedes mal eine riesige Latte von Parametern beim Aufruf von fswebcam mitgeben muss, kann man sich eine Konfigurationsdatei erstellen und diese beim Programmaufruf einbinden. Nachfolgend seht Ihr meine erste Konfigurationsdatei:

pi@raspcam ~/conf $ cat .fswebcam
device /dev/video0
input 0
skip 50
resolution 1280x720
set brightness=55%
set contrast=13%
set sharpness=10%
jpeg 95

Interessant ist hier die Zeile ’skip 50′. Dies gibt an, dass die ersten 50 Bilder verworfen werden sollen und gibt der Kamera somit Zeit zum Fokussieren. Der Rest kann den man-pages zu fswebcam entnommen werden.

Damit kann nun aber fswebcam wie folgt aufgerufen werden:

fswebcam -c /home/pi/conf/.fswebcam image.jpg

Wobei ‚-c‚ den Pfad zur Konfigurationsdatei beschreibt.

Jetzt kommen wir zum automatisierten Knipsen und Hochladen:

Für das Erstellen der Bilder habe ich mir ein kleines Bash-Skript capture.sh geschrieben:

Dafür gebt Ihr in der Konsole folgendes ein:

nano capture.sh

Kopiert dann folgendes in die Datei:

#!/bin/bash

#set up the paths and file names
filename="image"
filepath="/home/pi/webcam"

#process the arguments
while getopts f:h? opt;
do
   case "$opt" in
      f) filename=$OPTARG;;
      h|?)
        echo "usage is [-f <filename>]" >&2
        exit 1
        ;;
      *)
        echo "Invalid option: -$OPTARG" >&2
        exit 1
        ;;
   esac
done

now=`date +"%Y%m%d_%H%M%S"`

filename+="_${now}.jpg"
partname="${filename}.part"
partpath="${filepath}/${partname}"
filepath+="/${filename}"

fswebcam -q -c /home/pi/conf/.fswebcam $partpath
mv $partpath $filepath
echo "[$(date +"%d.%m.%Y %H:%M:%S")] picture ${filename} taken"

Zum Speichern: Strg+X, Shift+Y und Enter

Kurz gesagt erstellt das Skript ein Bild mit dem Dateinamen im Format image_<Datum>_<Uhrzeit>.jpg.part und benennt es anschließen in <Dateiname>_<Datum>_<Uhrzeit>.jpg (ohne .part) um. Optinal kann man dem Skript noch mit dem Schalter -f <Dateiname> einen Namen mitgeben, der das ‚image‚ im Dateinamen ersetzt.

Den Wert der Variablen filepath (bei mir /home/pi/webcam) müsst Ihr auf Euren Speicherort für die Bilder abändern. Und ggf. müsst Ihr noch den Pfad zu Eurer Konfig-Datei für fswebcam anpassen.

Wenn Ihr Euch fragt, was das denn bitte mit dem ‚.part‘ soll… dazu kommen wir gleich noch.
Denn jetzt kommt das zweite Skript, welches uns per FTP ein Bild auf einen Webserver kopieren soll:

Wir bemühen wieder den nano-Editor und geben folgendes ein die Konsole ein:

nano upload.sh
#!/bin/bash

###
# This script takes the latest jpg-file from the source-path and
# creates a temporary copy in the same directory (uploadname).
# Once this is done the temp-file will be copied to a webserver
# using ncftpput.
# Temp-file will be cleaned at the begining and at the end of the script
# (see 'rm' commands).
# The full path to 'rm' and 'cp' is used to prefent using aliases of the commands. 
###

#set up the paths and file names
sourcepath="/home/pi/webcam"
sourcefile=$(ls -1t "$sourcepath"/*.jpg | head -n1)
uploadname="$sourcepath"/"webcam.jpg"
ftppath="/webcam"

echo "[$(date +"%d.%m.%Y %H:%M:%S")] uploading picture ${sourcefile}..."

/bin/rm -f "$uploadname"
/bin/cp -f "$sourcefile" "$uploadname"

ncftpput -V -S .tmp -u <user> -p <password> meinserver.de "$ftppath" "$uploadname"

/bin/rm -f "$uploadname"

echo "[$(date +"%d.%m.%Y %H:%M:%S")] picture uploaded as ${uploadname}"

Zum Speichern: Strg+X, Shift+Y und Enter

In dem Skript müssen sourcepath (zeigt bei mir auf /home/pi/webcam), der Name mit der die Datei auf dem Webserver landen soll (bei mir webcam.jpg) und der Pfad auf dem Server ftppath (bei mir /webcam) nach Euren Bedürfnissen angepasst werden. Außerdem müsst Ihr natürlich Eueren User, das Passwort und den Hostnamen Eures Webservers ergänzen.

ACHTUNG! Der sourcepath aus diesem Skript muss gleich dem filepath aus dem ersten Skript sein!

Die Funktionsweise diese Upload-Skripts ist folgende:
Es wird die neuste Datei mit der Endung ‚jpg‚ aus dem Verzeichnis geholt, in dem Ihr Eure Bilder ablegt (also sourcepath bzw. filepath) und anschließend auf den Webserver mit einem bestimmten Dateinamen hochgeladen. Weil ich immer die neueste Datei vom Typ jpg hole, gehe ich im ersten Skript auf Nummer Sicher und erzeuge erst die .part-Datei, die anschließend umbenannt wird. Denn ich möchte verhindern, dass fswebcam eine Datei eventuell noch nicht fertig geschrieben hat und das zweite Skript aber schon versucht diese Datei hochzuladen bzw. zu kopieren.

Das Ganze hört sich vielleicht etwas umständlich an, denn man könnte auch ein viel einfacheres Skript schreiben wie zum Beispiel das hier:

nano capture_upload.sh
#!/bin/bash

#set up the paths and file names
filename="image"
filepath="/home/pi/webcam"
uploadname="webcam.jpg"
uploadpath="/webcam"


#process the arguments
while getopts f:h? opt;
do
   case "$opt" in
      f) filename=$OPTARG;;
      h|?)
        echo "usage is [-f <filename>]" >&2
        exit 1
        ;;
      *)
        echo "Invalid option: -$OPTARG" >&2
        exit 1
        ;;
   esac
done

now=`date +"%Y%m%d_%H%M%S"`
tmpfile="${filepath}/${uploadname}"
filename+="_${now}.jpg"
filepath+="/${filename}"

fswebcam -q -c /home/pi/conf/.fswebcam $filepath
cp $filepath $tmpfile
echo "picture ${filename} taken"

ncftpput -V -u <user> -p <password> meinserver.de $uploadpath $tmpfile
echo "picture uploaded as ${uploadname}"

Zum Speichern: Strg+X, Shift+Y und Enter

Und dran denken, dass auch hier wieder filepath, uploadname und uploadpath, sowie User, Passwort und Host des Servers angepasst werden müssen!

Das Skript capture_upload.sh hat den Nachteil, dass immer ein Foto gemacht und dieses dann auch hochgeladen wird. Für meinen Anwendungsfall wollte ich allerdings alle 2 Minuten ein Bild machen, und nur alle 10 Minuten ein Bild an den Webserver schicken.

Wie das geht zeige ich Euch jetzt noch. Hierfür machen wir entsprechende Eintrage in die Crontab.
Diese editieren wir mit dem Aufruf:

crontab -e

Für die Variante mit den beiden separaten Skripte und meinem Anwendungsfall könnte die Crontab so aussehen:

#Edit this file to introduce tasks to be run by cron.
# 
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any'). 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command
*/2 7-20 * * 1-6 /home/pi/script/capture.sh >> /home/pi/webcam/capture.log   
*/10 7-20 * * 1-6 /home/pi/script/upload.sh >> /home/pi/webcam/capture.log

Hier wird alle 2 Minuten zwischen 7 und 20 Uhr von Montag bis Samstag das Skript capture.sh aufgerufen.
Das Skript upload.sh wird im gleichen Zeitraum aufgerufen, allerdings nur alle 10 Minuten.
Mit ‚>> /home/pi/webcam/capture.log‘ leite ich die Log-Ausgaben (die echo-Befehle) eine Log-Datei um.

Und hier ist noch ein Beispiel für einen Crontab-Eintrag der Ein-Skript-Variante. Es wird im gleichen Zeitraum wie oben (und in 10 Minuten Abständen) ein Bild aufgenommen und auf den Webserver geladen:

# Edit this file to introduce tasks to be run by cron.
# 
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any'). 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command
*/10 7-20 * * 1-6 /home/pi/script/capture_upload.sh >> /home/pi/webcam/capture.log   

Zum Schluß noch der Link zu meiner Webcam: http://oldzitterhand.de/webcam/

Viel Spaß!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

*

*