
Im Rahmen meiner anstehenden Hochzeit suchte ich nach günstigen, zunächst mietbaren, Photobooth Boxen.
Diverese Hochzeitsfotografen bieten diese Boxen an, jedoch für einen relativ hohen Preis. Dafür bekommt man jedoch
hochqualitative Fotos, denn häufig beinhalten die Boxen teure Spiegelreflexkameras, teure Software und/oder eingebaute Fotodrucker.
Da mir dies jedoch alles zu teuer war, suchte ich nach DIY Alternativen und stieß relativ schnell auf die Seite von Chris Evans (KLICK).
Er hatte auf Basis des Raspberry Pi, Raspbian und einem kleinen Pythonprogramm eine wirklich schlanke und einfache Photobooth Lösung gebaut, die meiner Vorstellung
einer solchen Box schon recht nah kam. Einen Raspberry hatte ich noch in der Schublade, es fehlte nur noch das Raspberry Kameramodul. Diesbezüglich war ich mir zunächst
nicht ganz sicher, denn ich hatte gelesen, dass die Kamera insbesondere bei wenig Licht sehr stark rauschen würde und die Qualität auch nicht wirklich toll sein sollte.
Meiner Ansicht nach, ist die Qualität der Fotos jedoch nicht das einzige bzw. ausschlaggebende Argument, welches es bei einer Box zu beachten gibt.
Ich bin der Ansicht, dass das Hauptaugenmerk auf dem Spass und witzigen Fotos liegen sollte, statt auf perfekt ausgeleuchteten, rauscharmen Fotos mit höchster Pixelzahl.
Also bestellte ich die Kamera und ich muss sagen, die Qualität ist völlig in Ordnung!
Natürlich kann man keine Wunder erwarten, aber für ein paar Fotos bei normalem Licht reicht die Kamera vollkommen aus und wichtiger noch: Sie ist schnell und einfach programmier- und bedienbar!
1. Modifikationen gegenüber der Originalbox im Überblick
1.1 Email und Tumblr Upload deaktiviert
1.2 Wasserzeichen im Bild
1.3 Countdown Overlay im Livebild
1.4 4-Fachdarstellung der geschossenen Bilder (Speicherung aller Einzelbilder und der 4er-Bilder)
1.5 Standby-Replay Modus (wenn keine Fotos gemacht wird, werden nach Zufallsprinzip gemachte Bilder gezeigt)
1.6 RGB LED Beleuchtung
1.7 Mini Webgallerie auf lokalem Webserver, erreichbar über
1.8 WiFi Accesspoint (WLAN Modul)
1.9 Shutdown/Reset Prevention Routine (System Shutdown/Reboot nur über Button-Longpress aktivierbar)
1.10 Externer Buzzer
1.11 Beleuchtete Auslöseschalter
1.12 Speicherung der Fotos auf USB Stick statt SD Karte
1.1 Email und Tumblr Upload deaktiviert
Anders als bei Chris, wollte ich die Bilder nicht zu Tumblr oder irgendeiner anderen Bildplattform hochladen und so konnte der gesamte Teil in meiner neuen Fotobox Software entfallen.
Zudem wollte ich den Raspberry auch nicht mit mobilem Internetzugang auststatten.
1.2 Wasserzeichen im Bild
Um den Bildern einen professionellen Touch zu geben, soll ein kleines Wasserzeichen bzw. Logo in der unteren linken Ecke der Bilder angezeigt werden. Um den Rechenprozess beim Erstellen
der 4-fach Ansicht zu beschleunigen, werden die Fotos direkt nach der Aufnahme und während des Countdowns im Hintergrund mit dem Logo versehen. Dies geschieht mittels eines System-Call
des ImageMagick Programms montage:
graphicsmagick = "composite -gravity southwest /home/pi/watermark3.png " + filename + " " + filename + "&"
os.system(graphicsmagick)
Wichtig ist hierbei besonders das "&" Symbol am Ende, welches die Hintergrundausführung des composite Kommandos ermöglicht, also während bereits neue Fotos gemacht werden.
1.3 Countdown Overlay im Livebild
Anders als in der originalen Version der Box wollte ich noch einen Countdown, der als Overlay über das Live-Kamerabild gelegt wird, sodass die Nutzer auch sehen können, wann das Foto geschossen wird.
Da im Originalcode sowieso eine kurze Pause zwischen den einzelnen Aufnahmen liegt, musste nur noch ein Bild zur richtigen Zeit ein- und ausgeblendet werden. Hierzu erstellte ich einige Grafiken, die
dann halbtransparent über das Kamera-Livebild gelegt werden. Als ich diesen Teil programmierte enthielt die picamera Bibliothek (1.8) noch einen Bug, der ein Memory Leak durch mehrfaches Hinzufügen und Entfernen von Overlays produzierte (Fixed a nasty memory leak in overlay renderers which caused the camera to run out of memory when overlays were repeatedly created and destroyed (#174)). Glücklicherweise wurde dieser mit Veröffentlichung der neuen Version behoben.
def countdown_overlay( camera ):
n=4
for i in range(1,n):
gc.collect()
img = Image.open(str(i)+'.png')
pad = Image.new('RGB', (
((img.size[0] + 31) // 32) * 32,
((img.size[1] + 15) // 16) * 16,
))
pad.paste(img, (0, 0))
o = camera.add_overlay(pad.tostring(), size=img.size)
o.alpha = 100 #128
o.layer = 3
sleep(1)
camera.remove_overlay(o)
del img
del pad
1.4 4-Fachdarstellung der geschossenen Bilder (Speicherung aller Einzelbilder und der 4er-Bilder)
Um den gesamten Fotoprozess zu beschleunigen und so mehreren Leuten die Möglichkeit zum Fotografieren zu geben,
entschied ich mich, anders als bei Chris die Bilder nicht einzeln sondern alle 4 Bilder gleichzeitig nach der Session auf dem Bildschirm darzustellen. Auch hier kommt wieder Imagemagick ins Spiel und kombiniert
die 4 Einzelbilder zu einem:
#Aus den 4 Einzelbildern 1 Bild montieren
graphicsmagick = "montage "+ file_path + now + "-01.jpg " + file_path + now + "-02.jpg " + file_path + now + "-03.jpg " + file_path + now + "-04.jpg -geometry 640x512+2+2 "+ file_path + now + "-montage.jpg "
os.system(graphicsmagick)
#Kopieren der Einzelbilder nach ./single und in Anschluss löschen
bilder_wech="cp "+ file_path + now + "-01.jpg " + file_path + now + "-02.jpg " + file_path + now + "-03.jpg " + file_path + now + "-04.jpg "+ file_path + "single/"
os.system(bilder_wech)
bilder_wech="rm -f "+ file_path + now + "-01.jpg " + file_path + now + "-02.jpg " + file_path + now + "-03.jpg " + file_path + now + "-04.jpg "
os.system(bilder_wech)
1.5 Standby-Replay Modus
Um den Bildschirm optimal auszunutzen sollen während der Fotopausen, d.h. wenn gerade keine Bilder gemacht werden, nach dem Zufallsprinzip Bilder angezeigt werden. Hierzu wird bei jedem Aufruf der Funktion das
Bildverzeichnis eingelesen und dann aus dieser Menge fortlaufend zufällig Bilder ausgewählt und angezeigt, bis ein Benutzer den Auslöseknopf drückt. So können sich Benutzer einfach bereits gemachte Bilder anschauen
und sich weitere Ideen für neue Fotos holen.
while not GPIO.event_detected(button1_pin) :
piclist = list()
x = 0
for infile in glob.glob(os.path.join(file_path,'*.jpg')):
piclist.append(infile)
print random.choice(piclist)
pygame.display.set_caption('Photo Booth Pics')
pygame.mouse.set_visible(False) #hide the mouse cursor
filename = random.choice(piclist)
del piclist
img=pygame.image.load(filename)
img = pygame.transform.scale(img,(transform_x,transfrom_y))
screen.blit(img,(offset_x,offset_y))
pygame.display.flip() # update the display
sleep(3)
#print "next pic..."
gc.collect()
pygame.quit()
print "killed random image process"
GPIO.remove_event_detect(button1_pin)
start_again = True
GPIO.output(led2_pin,False)
1.6 RGB LED Beleuchtung
Eine schöne optische Verbesserung mit positivem Nebeneffekt bietet der (die) RGB-LED Strip. Zum einen macht die Beleuchtung natürlich einen tollen Eindruck und unterstützt gleichzeitig in den Abendstunden oder bei
schlechten Lichtverhältnissen beim Fotografieren. Fernbedienung und IR Empfänger sind seitlich in der Wartungsklappe untergebracht, was einen schnellen Farbwechsel oder eine Anpassung der Helligkeit ermöglicht.
Um noch mehr Lichtleistung in den schmalen Schlitz zu bekommen, entschied ich mich 2 LED Streifen einzubauen. Einen, der nach oben strahlt und auf eine weiße und somit reflektierende Fläche trifft und einen anderen,
der direkt nach vorne strahlt. Durch das auf der Rückseite aufgerauhte Plexiglas wird die Scheibe diffus und matt und bietet so ein recht gleichmäßiges relativ blendfreies Licht.


1.7 Mini Webgallerie auf lokalem Webserver
Um den Gästen die Möglichkeit zu geben sich die Bilder mit dem Smartphone oder Tablet anzusehen, benötigte ich neben einem Webserver eine Galleriesoftware, die möglichst wenig Ressourcen benötigt und möglichst ohne große Konfiguration und zusätzliche Bibliotheken oder Datenbanken auskommt. Nach einiger Suche stieß ich auf MiniGal (http://www.minigal.dk/) Perfekt!
Nachdem der Server und die Gallerie aufgesetzt waren, stellte ich jedoch ein Problem fest welches mich davon abbrachte, diese Konfiguration produktiv einzusetzen: Die Generierung der Vorschaubilder in der Gallerie geschieht scheinbar ebenfalls mit Imagemagick - Eigentlich kein Problem, doch bei einer Vorschau von 8 Bildern, wurden ebenfalls auch 8 Prozesse gestartet, die die kleine CPU des Raspberry für kurze Zeit vollständig auslasteten. Da gerade bei vielen gleichzeitigen Zugriffen auf den Webserver die Lauffähigkeit des Photobooth Programms nicht sichergestellt werden kann, entschied ich mich dieses Feature zu deaktivieren.
1.8 WiFi Accesspoint
Eigentlich der Tatsache geschuldet, dass der Ethernetanschluss des Pi nur schlecht zu erreichen ist richtete ich einen WLAN Accesspoint, DHCP und DNS Server auf dem Raspberry ein. So ist eine schnelle und unkomplizierte Wartung per WLAN und Laptop, Handy oder Tablet möglich. Leider läuft der Accesspoint nicht wirklich stabil und ich habe häufiger Probleme mich mit dem WLAN zu verbinden. Nach ein paar Neustarts ist das Problem jedoch meist behoben. Ursache könnte der verwendete Stick oder aber ein Softwareproblem sein. Da der Zugriff aber i.d.R. nur bei Problemen oder Wartungen von Nöten ist, ist dies kein Problem.
1.9 Shutdown/Reset Prevention Routine
Nach einigen Stunden des Testens, stellte ich immer wieder fest, dass die Hardwarebuttons scheinbar ohne ersichtlichen Grund von Zeit zu Zeit schließen bzw. auslösen. Beim Auslösebutton ist dies zwar nicht besonders schlimm (man hat eben nur ein leeres Foto), bei den Knöpfen für Shutdown oder Reboot liegt das Problem jedoch auf der Hand. Leider konnte ich nicht wirklich herausfinden, was der Grund für das ungewollte auslösen der Buttons ist. In Supportforen habe ich Leute mit einem ähnlichen Problem, aber ohne eine vernünftige Lösung gefunden. Um nun also dieses ungewollte Drücken zu unterbinden, habe ich eine kleine Routine programmiert, die den Shutdown oder Reboot Befehl erst dann durchführt, wenn der Button längere Zeit gedrückt wird. Diese Lösung ist allerdings programmiertechnisch nicht sauber und eher experimentell, aber sie funktioniert (irgendwie… ;-) ).
def reset_event_detection_shutdown():
sleep(0.5)
GPIO.remove_event_detect(button2_pin)
sleep(0.1)
GPIO.add_event_detect(button2_pin, GPIO.FALLING, callback=shut_it_down, bouncetime=300)
def shut_it_down(channel):
sleep(0.5)
counter=0
while GPIO.input(channel) == GPIO.LOW :
counter=counter+1
sleep(0.1)
if (counter >= 8):
print str(counter) + "counter"
print "Shutting down..."
GPIO.remove_event_detect(button2_pin)
lightshow(1)
#GPIO.output(led1_pin,True);
#GPIO.output(led2_pin,True);
#GPIO.output(led3_pin,True);
#GPIO.output(led4_pin,True);
time.sleep(3)
os.system("sudo shutdown now -h")
else:
print "Press longer to shutdown!"
print str(counter) + "counter"
reset_event_detection_shutdown()
1.10 Externer Buzzer
Neben dem Auslöser an der Box wollte ich gerne noch eine Möglichkeit eines stehenden Buzzers realisieren, der etwas von der Box entfernt stehen sollte. Da ich beabsichtigt hatte den Buzzer später auch zu beleuchten, brauchte ich also eine 4-adriges Kabel und eine Möglichkeit ihn einfach von der Box an und abzukoppeln. Hier entschied ich mich auf ein USB Kabel zurückzugreifen, was sich m.E. hierfür prima eignet.
1.11 Beleuchtete Auslöseschalter
Um die Gäste zu animieren und das Aussehen optisch zu verbessern entschied ich mich die Buttons noch zu beleuchten. Standardmäßig sind die Arcardebuttons mit 12V Glühbirnchen versehen, was eine (An-)Steuerung mittels Raspberry und GPIO erschwerte, da dieser nur 5V liefert. Also entschloss ich mich die Beleuchtung komplett autonom zu steuern und verpasste dem Lampensystem ein eigenes 12V Netzteil welches ich mit einem Wechselblinker (Bausatz) koppelte. Sofern der Buzzer angeschlossen ist, blinkt der Auslöser am Gehäuse und der Buzzer im Wechsel, ansonsten ist die Lampe dauerhaft beleuchtet.
1.12 Speicherung der Fotos auf USB Stick statt SD Karte
Um zum einen Schreibzugriffe auf die SD Karte zu minimieren und das Kopieren der Fotos zu vereinfachen, habe ich einen USB Stick installiert, welcher beim Systemstart automatisch gemountet wird. Dieser ist FAT32 formatiert und kann also auch problemlos von Fremdbetriebsystemen wie MacOS oder Windows gelesen werden.
Der Stick kann beim Systemstart mit folgendem Eintrag in der /etc/fstab automatisch gemundet werden:
UUID=<UUID des USBSTICK> /var/www/photos vfat defaults,auto,umask=022,users,rw 0
Die UUID kann mit dem Befehl blkid
festgestellt werden.
Ich begann zunächst mit der Installation und Einrichtung des Raspbian Systems und begann dann mit dem Auf- und Nachbau der Elektronik auf einem Breadboard. Erste Tests funktionierten gut und so konnte ich mich dem Code widmen. Da ich nur wenig Erfahrung mit der Programmierung mit Python habe, war die Programmierung etwas holperig. Glücklicherweise findet sich überall gute Dokumentation im Netz und ich brauchte nicht viel neu zu programmieren und konnte so weite Teile von Chris‘ Code einfach recyclen.
Glücklicherweise verfügt mein verwendeter Monitor über eingebaute USB Schnittstellen, weswegen ein externes Netzteil für den Raspberry enfällt. Intern verwende ich eine 3fach Steckdose die mit Monitor, Lampennetzteil und LED Netzteil voll belegt ist.
Durch die interne Verwendung der 3er Dose hat die Box nur ein Stromkabel welches nach aussen geht.

Probleme
- Fehlendes Internet, daher keine Zeitsynchronisation --> keine bzw. falsche Zeitstempel bei Fotos
- Aufgrund (vermutlich) langer Kabel willkürliches ungewolltes Drücken der Buttons (siehe 1.9)
- WLAN Verbindungsprobleme (Verbindung mit Photobooth schlägt fehl)
Ideen für zukünftige Verbesserungen
- Mobiles Internet mit DynDNS Adresse für Wartungszwecke
- Ethernet Wartungsanschluss
- Sound (Auslösegeräusch, Countdown Ton)

Der komplette Code:
photobooth.py