OLYMPUS DIGITAL CAMERA

Photobooth Verleih

Ich wollte nur mal erwähnen, dass ich die/das/den Photobooth die Fotobox auch gerne verleihe…

Wer nicht weiß, worum es geht kurz gesagt: Ein Kasten, der auf Knopfdruck Fotos macht und zu einer Collage zusammensetzt, anzeigt und ggf. ausdruckt.

2016-02-23 18_46_21-Antje&Boris (711).JPG ‎- Fotos

Hier noch meine Blogposts zum Bau:
Tinkering Tuesday – Photobooth im Selbstbau Teil 1 – Planung und Setup
Tinkering Tuesday – Photobooth im Selbstbau Teil 2 – Ablaufsteuerung
Tinkering Tuesday – Photobooth im Selbstbau Teil 3 – In der Praxis

Allgemeine Bedingungen

  • grundsätzlich erstmal nur an Verwandte und Bekannte, evtl. auch Bekannte von Verwandten/Bekannten, einfach mal fragen…
  • ggf. ohne den Fotodrucker: Da dieser nur eine Kapazität von 30 Drucken pro Kassette hat ist es entweder ein entsprechender Aufwand die Kassette zu wechseln (es muss immer die Kartusche gewechselt und neues Papier eingelegt werden) bzw. zu prüfen, wann gewechselt werden muss. Bei meiner Hochzeit wurden einige Kassetten nur halb genutzt, da ich Nachschub vor Ort liegen hatte und jeder wechseln konnte. Dadurch waren letztlich die Druckkosten höher (normal ca. 30ct pro Druck). Also entweder eigenen Drucker (da sollte jeder Drucker funktionieren, den man unter Linux betreiben kann), oder eben unter den gegebenen Voraussetzungen
  • Entweder bin ich eingeladen (sowieso beste Option 😉 oder jemand mit zumindest ein bisschen technischem Verständnis braucht eine kurze Einweisung (es gibt allerdings auch eine kleine Anleitung auf der Innenseite der Tür)
  • Die Box hat einen Flansch für ein Boxenstativ um sie auf entsprechender Höhe aufzustellen. Ich hab allerdings (noch) kein eigenes 😉

Kosten

  • Grundsätzlich erstmal keine
  • Verbrauchsmaterial (Drucker) müsste entsprechend in ausreichender Menge besorgt werden (bei Nutzung meines Fotodruckers: Canon KP 108IN, ca. 30ct pro Ausdruck)

Individualisierungsmöglichkeiten

  • Ich hatte einfache weiße Collagen, es können aber auch eigene Vorlagen relativ einfach erstellt werden (Grafiken oder Text mit auf den Ausdruck, lasst euch im Internet inspirieren)
  • Die Anzahl der Bilder ist natürlich anpassbar, ebenso ggf. Effekte wie Schwarz-Weiß-Konvertierung, solange unter Linux per Shell-Commando oder sonstwie programmatisch lösbar
  • Theoretisch kann, wie in den Blog Posts beschrieben, die Frontplatte getauscht werden. Man könnte z.B. einen entsprechenden Ausruck auf eine Platte kleben… Dann könnte man je nach Lichtverhältnissen oder anderen Möglichkeiten (z.B: externer Blitz) auch den Blitzrahmen weglassen
  • Im Extremfall könnte man das Ganze natürlich auch in einen anderen Kasten verpacken. Das ist aber ordentlich Aufwand 😉
  • Ein paar interessante Erweiterungsgedanken hab ich mir auch gemacht, die je nach Lust, Laune, Zeit und Geldbeutel auch umsetzbar wären:
    • Man könnte einen WLAN-Hotspot einrichten, wo jeder einfach mit seinem Smartphone auf die Bilder zugreifen kann
    • Ebenso kann man die Bilder automatisch ins Internet hochladen, öffentlich oder in ein privates Album, je nach exhibitionistischer Veranlagung der Gäste
    • Mittlerweile habe ich eine neue Kamera, auf der die Bilder direkt per WLAN abgerufen werden könnten (übrigens eine Olympus OM-D E-M10 Mark II)
    • Man könnte das Auslösen und die Anzeige auch über ein Tablet lösen… Bräuchte dann aber eine stabile Aufstellung (oder Aufhängung)
    • … was das Herz begehrt… wir können drüber reden
2016-02-21 16.23.51-1

Xiaomi Mi Band 1S – Schlaftracking

Tja, gleich vorweg, das war ein Schuss in den Ofen. Ich hatte mir ja erhofft, dass ich ein wenig tieferen Einblick in meine Schlafgewohnheiten mit dem Mi Band bekomme. Bis auf „Wann bin ich schlafen gegangen?“ und „Wann bin ich wieder aufgewacht?“ kann mir das Band leider keine Informationen liefern. Die Erkennung der Schlafphasen ist einfach totaler Blödsinn. Auch mit aktiviertem Schlafassistenten, der den Herzfrequenzsensor für die Analyse nutzt, sind die Ergebnisse sehr ernüchternd.

Es gibt vier Dinge, die mir aufgefallen sind:
1.) Die Tiefschlafphasen sind viel zu kurz und zu oft:
2016-02-10 15.59.16 2016-02-09 07.22.53

Gerade im ersten Screenshot sieht man 12 Tiefschlafphasen in einer Frequenz von 15-20 Minuten. Etwas unglaubwürdig.

2.) Nochmal die Tiefschlafphasen. Und zwar zeigt mir die App sehr oft Tiefschlafphasen um die Afustehzeiten meiner Frau herum. Ich garantiere, dass ich dann definitiv nicht im Tiefschlaf bin.

3.) Die Ergebnisse ändern sich. Das ist ein Phänomen, was auch im Internet sehr oft anzutreffen ist: Beim ersten Abruf zeigt die App ein Ergebnis, nach ein paar Minuten oder Stunden (nicht verlässlich nachvollziehbar), ändern sich die Ergebnisse.

Im folgenden Beispiel sieht man die Ergebnisse einer einzigen Nacht. Einmal beim ersten Abruf um 7:10 Uhr, dann um 7:53 völlig andere Ergebnisse.
2016-02-11 06.10.13 2016-02-11 06.53.16

Das selbe tritt auf, wenn man manuell die Einschlafzeit verstellt. Das habe ich einmal gemacht, weil die App gedacht hat, ich wäre eingeschlafen, als ich auf dem Sofa lag. Zumindest hat es erkannt, als ich dann tatsächlich aufgestanden bin um mich ins Bett zu begeben. Da hat es eine Wachphase angezeigt.

4.) Ein weiteres Problem ist, dass sich die Ergebnisse nicht gut analysieren lassen. Zum einen gibt es keinen Export (wohl nur mit root-Rechten machbar), auch die Synchronisierung mit Google Fit bezieht sich nur auf den Schrittzähler. Zum anderen sind die Detailinfos nur am Folgetag einsehbar, danach gibt es nur noch die Zusammenfassung im Verlauf zu sehen:

2016-02-21 15.23.34

Fazit:

Ich hatte mir zumindest ein paar bessere Ergebnisse erwartet. Ich hab gleichzeitig auch ein Schlaftagebuch angefangen, das bringt mir wahrscheinlich bessere Ergebnisse.

Jemand Interesse an einem fast neuen Xiaomi Mi Band 1S? 😉

2016-02-21 16.23.51-1

OLYMPUS DIGITAL CAMERA

Tinkering Tuesday – Photobooth im Selbstbau Teil 3 – In der Praxis

So, diese Woche gibt es dann endlich den fertigen Kasten. Ich hatte mir vorab eine grobe Skizze gemacht, wie das Ding auszusehen hat und ohne große Umwege hier einmal das Ergebnis:
OLYMPUS DIGITAL CAMERA

Da ich den Drucker gerade verlegt habe sind die Bilder alle ohne den Fotodrucker. Dieser wird aber ganz normal per USB-Kabel angeschlossen, das, genau wie das Stromkabel, dann zurück in den Kasten geführt wird. Also denkt euch einfach noch ein paar mehr Kabel dazu.

Der Monitor ist wie schon erwähnt ein alter 17 Zoll Monitor. Darüber sieht man die Öffnung für die Kamera. Ich hatte da noch eine Holzverkleidung drum, aber die ist wieder abgefallen. Schlecht geklebt… Dadrüber wiederum ist der Blitzdiffusor. Hier hab ich die ganz günstige Version genommen: Ein normales Blatt 80g DIN A4-Papier. Reicht auf die Distanz. Immerhin hab ich mir bei der Verkleidung des Randes Mühe gegeben und ein Plastikprofil zurecht geschnitten.

Der obere Teil steht etwas hervor, das liegt daran, dass dieser Teil abnehmbar ist. Mittels 4 Schrauben aus dem Inneren zu lösen, kann man den Teil theoretisch austauschen und mit verschiedenen Designs ausstatten. Fand ich wohl irgendwie eine gute Idee, als ich den Kasten konzipiert hab. Ehrlich gesagt habe ich keine Ahnung, warum ich das so gebaut hab. Irgendwie hatte ich gedacht, dass ich sonst das Beziehen (weißes Kunstleder übrigens! Hatte ich noch von meinem Sofa-Umbau übrig, den gibt es vielleicht auch demnächst mal hier). Sieht auf jeden Fall etwas „aufgesetzt“ aus. Heute würde ich es anders machen, aber immerhin kann ich so theoretisch das Design komplett anpassen 😉
OLYMPUS DIGITAL CAMERA

Auf dem rechten Bild sieht man dann den eingeschalteten Kasten mit der Slideshow. Es gibt einen einzigen Stecker, der zur Steckdose führt und den Schalter, der mittels Mono-Cinch-Kabel angeschlossen ist (ich bin Fan von Cinch-Kabeln, wird man später noch sehen 😉
OLYMPUS DIGITAL CAMERA

Die Rückseite habe ich auch ganz ansehnlich mit einer Schranktür (aus der Max Bahr Insolvenz damals), die ich weiß lackiert habe, gelöst. Mit zwei Scharnieren angebracht voll funktional. Unten ein kleiner Spalt, der zum Einen der Breite der verwendeten Holzleisten unten und oben geschuldet ist, zum Anderen aber natürlich komplett absichtlich für die Durchführung der Kabel so gelassen wurde:
OLYMPUS DIGITAL CAMERA OLYMPUS DIGITAL CAMERA

Hier dann das geöfnete Türchen mit all seinem Chaos dahinter. Es kann alles im Kasten zum Transport verstaut werden. Mehr oder weniger sicher. Man sieht unten den Platz für den Monitor und den Laptop. Daneben eine angeschraubte Steckdosenleiste mit genau 4 Steckplätzen: für Monitor, Laptop, Kamera und (der freie) für den Drucker. Oben dann der Platz für die Kamera und dort auch die restlichen Komponenten.

OLYMPUS DIGITAL CAMERA OLYMPUS DIGITAL CAMERA

Ab jetzt ein paar mehr Details. Hier sieht man die Kamera-Ebene von unten. Eine einfache A4-Bastelspanplatte auf einfachen Holzlatten am Rahmen festgeschraubt. Darunter erkenn man zum Einen die Stativ-Schraube zur Fixierung der Kamera (die war etwas lang, daher ein „paar“ Unterlegscheiben). Zum Anderen sieht man die improvisierte Monitorhalterung. Ich musste den Standfuß abnehmen und ohne kippt der Monitor schnell. Außerdem muss er fest an seinem Platz sitzen. Also Latte angeschraubt, Metallplatte als Stütze, fertig ist die Laube.

OLYMPUS DIGITAL CAMERA

Oben dann die Kamera vor dem Diffusor. Links daneben die angeschlossene TV-Karte (der Adapter für die TV-Karte hat einige Anschlüsse und die für die Kamera auch, daher das Gewirr). Mit den roten Cinch-Verbindern angeschlossen ist der Kamera-Auslöser (wie gesagt, ich mag Cinch-Verbindner, so kann man die Länge der Leitung beliebig anpassen). Die Schaltung für den Auslöser sieht man recht unten auf dem linken Bild. Der Experte wird einen Drehpoti entdecken. Der war nachträglich dran gebaut, da ich Probleme hatte den Auslöser zum Laufen zu bekommen. Letztlich war allerdings ein Tausch der Verbindung zum Cinch-Stecker zielführend… „Natürlich hab ich die Kabel richtig rum angeschlossen“… für’n Ar…
OLYMPUS DIGITAL CAMERA OLYMPUS DIGITAL CAMERA

Hier dann noch der Arduino mit der Verbindung zur Kameraschaltung und zum Auslöse-Schalter. Der Schalter ist ein einfacher Baumarkt-Unterputzschalter (auch aus der Max Bahr Insolvenz). Den habe ich in einen selbstgebastelten Holzkasten eingesetzt, der ebenfalls mit weißem Kunstleder verkleidet ist.

OLYMPUS DIGITAL CAMERA OLYMPUS DIGITAL CAMERA

Und nun, das worauf jeder wartet, ein Video indem ich das Ganze vorführe und wo es dämliche Bilder von mir zu sehen gibt 😉

Es startet mit der Slideshow. Nach drücken des Schalters startet das Livebild und der Countdown. Ich schaue eigentlich die ganze Zeit in die Kamera. Bei der Aufnahme des letzten Bilds sieht man aber mal den Unterschied von „in die Kamera schauen“ und „auf den Monitor schauen“. Das ist auch leider ein Problem gewesen, viele haben halt die ganze Zeit auf den Monitor geschaut. Beim nächsten Mal würde ich das Live-Bild eher ausblenden und irgendwie einen Hinweis oder sonstiges machen, wo das Vögelchen kommt.

Nach den 4 Aufnahmen startet wieder die Slideshow, zunächst ohne die neue Collage. Den Neustart der Slideshow erkennt man, als für kurze Zeit der Mauszeiger oben links auftaucht. Normalerweise schiebe ich den immer aus dem Bild, aber hier war er ganz hilfreich um das zu demonstrieren. Dann setzt die Slideshow wieder per Zufall ein und das Bild wird dann auch am Ende des Videos angezeigt.

Ich muss zugeben, ich hab mir relativ wenig Mühe mit dem Video gegeben. Zu merken an der schlechten Ausleuchtung, dem schiefen Bild, dem fehlenden Ton (Youtube lässt einen den Ton ersetzen, was ganz praktisch war 😉 Vlogger werde ich wohl in absehbarer Zukunft eher nicht…

Letzten Endes gab es als ich den Kasten nach längerem Rumstehen für die Doku hier wieder reaktiviert habe noch ein kleines „Ochnöö…“:
OLYMPUS DIGITAL CAMERA

Das ist leider kein cooles Hintergrundbild. Allerdings funktioniert alles noch, sogar der Touchscreen-Touch. Und ich habe ja vorne den Monitor noch im Kasten…

2016-02-02 21.39.55

Fitnesstracker Mi Band 1S

Ich hab das Mi Band 1s bei Gearbest am [Datum] bestellt. Lieferzeit wurde schon bis zu 50 Tage avisiert.

Nach kurzer Zeit hatte ich schon eine Bestellbestätigung in der Inbox also dachte ich, kann ja dann nicht mehr so lange dauern. Naja, Mitte Januar ist mir dann wieder eingefallen „Hm, da war doch noch was“, aber die Trackingnummer half auch nichts. Am 2.2. hatte ich dann ganz unverhofft ein kleines Päckchen im Briefkasten mit einem „Gift“ im Wert von 11,93 Euro, naja, ein wenig geschummelt. Ich weiß zwar nicht warum, weil das Ding so oder so unter der Zollfreigrenze läuft…

Aber erstmal kurz, was will ich überhaupt damit? Gute Frage. Ich laufe eh zu wenig, daran hat weder ein normaler Schrittzähler im Rahmen der Gesundheitswochen meines Arbeitgebers, noch die S-Health-Schrittzähler-App was geändert. Also das ist weniger mein Beweggrund. Hauptsächlich interessiert mich eigentlich die Analyse meines Schlafes. Wie viel Schlafe ich, wie gut schlafe ich (zumindest theoretisch). Dafür ist mir das die paar Euro wert, nicht aber den Preis eines Fitbit oder sonstigen deutlich teureren Gerätes.

Das Mi Band kommt in einem schlichten Karton daher.
2016-02-02 21.39.55
Die erste Amtshandlung ist natürlich die Bedienungsanleitung zu lesen… leider nur auf Chinesisch. Aber die Abbildungen sind recht selbsterklärend und außerdem gibt es ja noch Internet bzw. das „Einfach-mal-ausprobieren“. Erstmal aber mit dem niedlichen Adapter an die USB-Buchse und geladen. Das ging auch recht fix, ich schätze mal 2 Stunden, dann waren alle 3 Lampen an.

2016-02-02 21.35.55

Dann ins Armband eingesetzt und erstmal die offizielle App „Mi Fit“ im PlayStore installiert. Die Bewertungen sind nicht so und es soll auch Alternativen geben, aber ich möchte erstmal mit der offiziellen Version starten. Mal sehen. Nach der Installation die erste Überraschung: die App ist sogar auf deutsch! Über https://account.xiaomi.com/pass/register hab ich mir dann erstmal einen Account angelegt (soll wohl besser per Browser gehen…).

Dann geht es an die Einrichtung. Nach Namen, Geschlecht (blau für männlich, pink für weiblich… ist das gender-konform?), Geburtsmonat, Größe und Gewicht geht es dann ans Pairing.

2016-02-02 20.52.44 2016-02-02 20.53.18 2016-02-02 20.54.22

2016-02-02 20.54.32 2016-02-02 20.54.41 2016-02-02 20.54.52

2016-02-02 20.55.00 2016-02-02 20.55.11

Der erste Versuch das Band mit meinem Smartphone zu verbinden lieferte „Zu viele Gräte in Reichweite“. Ich hatte heute Mittag Fisch zu Essen, hat das damit zu tun? Beim nächsten Versuch haben dann die LEDs abwechselnd geleuchtet und ich wurde aufgefordert den Metallsensor zu berühren. Nach einigem Streicheln wieder die Fehlermeldung. Beim dritten Versuch mal mit mehr Kraft „draufgepatscht“, da hat es funktioniert.

2016-02-02 20.55.45 2016-02-02 20.56.58 2016-02-02 20.58.37

Man hat auch einige Einstellmöglichkeiten, die ich erstmal wie folgt vorgenommen habe. Mal sehen.

2016-02-02 21.03.56 2016-02-02 21.05.33

Geht man zurück auf den Home-Bildschirm wird erstmal ein Update eingespielt. Das geht aber auch innerhalb von einer Minute. Dann wird der Puls genommen. Auch recht fix. Es gibt zwar irgendwie kein Ergebnis, aber ein manuelles Starten der Messung ergibt dann einen Anfangspuls von 72. Sehr gut.

2016-02-02 21.06.14 2016-02-02 21.06.59 2016-02-02 21.08.50

Das war am ersten Abend. Die erste Nacht hat auch gleich gute Ergebnisse mit sich gebracht. 8,5h Schlaf, davon über 5 im Tiefschlaf. Wer weiß, ob’s stimmt?!? Ich werde das über die Zeit mal beobachten.

2016-02-03 14.20.19

012716_1748_TinkeringTu1.png

Tinkering Tuesday – Photobooth im Selbstbau Teil 2 – Ablaufsteuerung

Eigentlich passt dieser Post sowohl in den Tinkering Tuesday, als auch in den Programming Pursday, da es hier um den Programmablauf geht. Da der Programming Pursday allerdings erstmal für mein Android-Projekt reserviert sein soll (mit dem ich im Moment nicht so richtig weiterkomme), gibt es den Post als Tinkering Tuesday.

Also, nachdem das grundlegende Setup steht, geht es also an die Steuerung des Ganzen. Da ich mir nicht mit irgendeiner Programmiersprache großen Overhead einbrocken wollte (dazu vielleicht mal mehr, wenn ich meinen Hamstertacho vorstelle, da hab ich alles in Java gemacht und das auf einem Raspberry Pi laufen lassen… war erstmal ein ganz schöner Krampf…) und die meisten Programme, die ich steuern wollte sowieso sehr gut von der Shell zu bedienen sind, hab ich mich für ganz einfache Shell-Skripte entschieden.

Start Photobooth

Das Skript zum Starten hat folgende Schritte:

Hier das Ganze im Skript:

echo stopping mplayer
bash /home/boris/Dokumente/photobooth/shellscripts/kill_mplayer.sh
echo stopping slideshow
bash /home/boris/Dokumente/photobooth/shellscripts/kill_slideshow.sh
echo stopping Eye-Fi Server
bash /home/boris/Dokumente/photobooth/shellscripts/kill_eyefi_server.sh
echo stopping Booth Listener
bash /home/boris/Dokumente/photobooth/shellscripts/kill_booth_listener.sh
echo stopping collage maker
bash /home/boris/Dokumente/photobooth/shellscripts/kill_collage_maker.sh
killall inotifywait

Check Devices

Im ersten Skript, check_devices.sh wird erstmal gecheckt, ob überhaupt alle notwendigen Geräte angeschlossen und unter dem bekannten Namen zu finden sind. Der Arduino sollte unter dem Device /dev/ttyACM0, die TV-Karte unter /dev/video1 zu finden sein. Fehlt der Arduino, wird das Programm abgebrochen, da weder der Schalter, noch der Kameraauslöser funktionieren würden. Die TV-Karte ist optional und führt nur zur Warnung, dass kein Mirroring möglich ist. Den Drucker hab ich nicht extra abgefragt (zum Testen hatte ich ihn meist eh nicht angeschlossen, da ich nicht immer Fotopapier verschwenden wollte).

if find /dev/ttyACM0; then echo Arduino connected; else echo Arduino not connected; exit 1; fi
if find /dev/video1; then echo TV card connected; else echo TV card not connected - no mirroring; fi
exit 0

Serielle Verbindung zum Arduino

Dann wird die Serielle Verbindung zum Arduino mit 9600 Baud hergestellt. Fragt mich bitte nicht mehr, was die anderen Parameter alle sollen, ich bin in dem Fall nur einem Tutorial gefolgt. Das Lesen und Schreiben direkt von der Shell funktioniert bei mir übrigens nicht so richtig, daher ist das später über ein Python-Skript gelöst. Aber dazu später mehr.

Slideshow

Dann wird auch schon die Slideshow gestartet. Da habe ich den Quick Image Viewer QIV genutzt. Der ist sehr flexibel und sehr schnell. Genau richtig für meine Zwecke. Wie man im Skript sieht, wird die Slideshow als Hintergrundprozess gestartet und die Prozess ID (PID) in eine Datei geschrieben. So kann ich später den Prozess ganz einfach wieder beenden.

qiv -f -m -t -i -C -s -S -r /home/boris/Bilder/collagen/  &
echo $! > /home/boris/slideshow_process.pid

Dann kommen die beiden Hauptprozesse, die beide ebenfalls als separate Prozesse gestartet werden.

Collage Maker

Der erste prüft, ob der Collage Maker nicht bereits läuft und startet ihn dann. Dieser überwacht im Grunde nur den Zielordner für die Collagen und wartet auf vier neue Dateien. Sind die angekommen, startet er mit diesen das Skript um die Collage zu erstellen. Da das Programm in einer Endlosschleife läuft, wird sich auch hier die PID gemerkt. So kann ich später mit dem Kill-Skript alles sauber beenden.

Ordnerüberwachung

Hier das Skript für die Ordnerüberwachung, die ich mit inotifywait realisiert hab. Das ist sehr viel effektiver, als ständig den Ordner nach neuen Dateien abzufragen. Man sieht, dass ich noch den Eye-Fi-Ordner nutze. Da war ich zu faul um das zu ändern. Außerdem ist der Eye-Fi Server ebenfalls noch eingerichtet, so kann ich schnell umbauen, falls ich eine andere Kamera nutzen möchte, die Eye-Fi vielleicht besser verarbeitet.

count=1
inotifywait --excludei ".tar" -m --format '%f' -e moved_to -e create /home/boris/Bilder/eyefi | while read line
do
	echo $count
	if [[ $count -eq 4 ]]
		then 
			files=$files,$line
			echo $files
			bash /home/boris/Dokumente/photobooth/shellscripts/make_photocollage.sh $files
			count=$(($count - 3 ))
		else
			if [[ $count -eq 1 ]]
				then
					files=$line
				else
					files=$files,$line
			fi
			echo $files
			count=$(($count + 1 ))

	fi
done

Make Photocollage

Das Skript ist dann dafür zuständig die 4 gefundenen Einzelbilder in eine Photocollage zu verwandeln. Damit das nicht immer gleich und so langweilig aussieht, hab ich 3 verschiedene Layouts erstellt, aus denen mit einem Random-Generator ausgewählt wird. Es ist jeweils das erste Bild in groß dargestellt, die anderen 4 werden in verschiedenen Positionen darum herum positioniert:

collage_t1 collage_t2 collage_t3

Danach werden die vier Bilder zunächst in das passende Format umgewandelt und in einen temp-Ordner gespeichert. Das erste Bild wird auf 666×500 Pixel, die anderen auf 220×165 Pixel verkleinert. Wozu der Crop ist, weiß ich ehrlich gesagt nicht mehr. Mit dem Befehl composite wird dann das entsprechende Bild an die entsprechende Position gesetzt. Dazu habe ich als Ausgangsbasis ein Template im Druckformat für 10×15 bereitgestellt. In meinem Fall habe ich mich für ein einfaches Weiß entschieden. Also kein großes Design-Brimborium drumherum, da wir die entstehenden Photos ja direkt ausdrucken lassen und von den Gästen in ein Album kleben lassen wollten. Dazu lagen dann diverse Stifte bereit, mit denen dann eine Widmung und Deko selbst gemalt werden konnte.

Das fertige Bild wurde dann zum Drucker geschickt (mit dem lp-Befehl) und nochmal in ein anderes weißes Template mittig eingebunden, da der Monitor ein anderes Seitenverhältnis hat. So wurde oben und unten nochmal weiß aufgefüllt.

Im letzten Schritt wird die Slideshow neu gestartet, damit auch das neue Bild mit in die Rotation aufgenommen wird.

arr=$(echo $1 | tr "," "\n")
count=1

rnd=$(($RANDOM%3+1))
echo Vorlage $rnd
if [[ rnd -eq 1 ]]
then
	posImg1="+20+20"
	posImg2="+660+230"
	posImg3="+420+415"
	posImg4="+660+415"
elif [[ rnd -eq 2 ]]
then
	posImg1="+20+50"
	posImg2="+660+20"
	posImg3="+660+218"
	posImg4="+660+415"
elif [[ rnd -eq 3 ]]
then
	posImg1="+117+20"
	posImg2="+20+415"
	posImg3="+340+415"
	posImg4="+660+415"
fi


for x in $arr
do
	if [[ $count -eq 1 ]]
	then 
		first=$x
		convert -gravity Center -crop 613x460+1+0 -resize 666x500  /home/boris/Bilder/eyefi/$x /home/boris/Bilder/temp/$x.png
		composite -geometry  $posImg1 /home/boris/Bilder/temp/$x.png /home/boris/Vorlagen/template_600.jpg /home/boris/Bilder/temp/collage_$first
		count=$(($count + 1 ))
	elif [[ $count -eq 2 ]]
	then 
		convert -gravity Center -crop 613x460+1+0 -resize 220x165 /home/boris/Bilder/eyefi/$x /home/boris/Bilder/temp/$x.png
		composite -geometry $posImg2 /home/boris/Bilder/temp/$x.png /home/boris/Bilder/temp/collage_$first /home/boris/Bilder/temp/collage_$first
		count=$(($count + 1 ))
	elif [[ $count -eq 3 ]]
	then 
		convert -gravity Center -crop 613x460+1+0 -resize 220x165 /home/boris/Bilder/eyefi/$x /home/boris/Bilder/temp/$x.png
		composite -geometry $posImg3 /home/boris/Bilder/temp/$x.png /home/boris/Bilder/temp/collage_$first /home/boris/Bilder/temp/collage_$first
		count=$(($count + 1 ))
	elif [[ $count -eq 4 ]]
	then 
		convert -gravity Center -crop 613x460+1+0 -resize 220x165 /home/boris/Bilder/eyefi/$x /home/boris/Bilder/temp/$x.png
		composite -geometry $posImg4 /home/boris/Bilder/temp/$x.png /home/boris/Bilder/temp/collage_$first /home/boris/Bilder/temp/collage_$first
	fi
done
lp /home/boris/Bilder/temp/collage_$first > /home/boris/Dokumente/print.log
composite -geometry +0+60 /home/boris/Bilder/temp/collage_$first /home/boris/Vorlagen/template_720.png /home/boris/Bilder/collagen/collage_$first

if $(kill  $(cat /home/boris/slideshow_process.pid)); then echo Slideshow wird neu gestartet; bash /home/boris/Dokumente/photobooth/shellscripts/start_slideshow_qiv.sh; else echo Slideshow läuft nicht; exit 1; fi

Booth Listener

Der Booth Listener war ursprünglich ein Shell-Skript, welches die Abfrage vom Arduino und die Steuerung selbst übernehmen sollte (siehe auskommentierte Befehle), wurde dann aber durch ein Python-Skript ersetzt. Da war ich wieder faul und hab den Aufruf einfach nur weitergeleitet. Nicht schön, funktioniert aber 😉 Das Skript ruft also letztlich auch nur das Python-Skript im Hintergrund auf und schreibt die PID in eine Datei.

# Kill any existing cat commands logging the terminal
#exec  ps ax | grep "cat /dev/ttyACM0" | grep ? | awk '{system("kill " $1)}'
# Connect the terminal to logging to a file by appending
# cat /dev/ttyACM0 > ardulog &
#cat /dev/ttyACM0 | while read x
#x=$(/home/boris/arduino-serial -b 9600 -p /dev/ttyACM0 -d 2000 -r)
#echo $x
#bash /home/boris/Dokumente/photobooth/shellscripts/start_booth_sequence.sh &
#exit

python /home/boris/Dokumente/photobooth/shellscripts/booth_listener.py &
echo $! > /home/boris/booth_listener_process.pid

Hier dann das dazugehörige Python:

import subprocess
import serial
varStopListeningTemp = 0
try:
	arduino = serial.Serial('/dev/ttyACM0', 9600)
except:
	print "Failed to connect to arduino"
while True:
	var1 = arduino.readline()
	if var1[0] == "1":
		print "Start Booth Sequence"
		subprocess.call("/home/boris/Dokumente/photobooth/shellscripts/start_booth_sequence.sh",shell=True)
		arduino.flushInput()
	else:
		print "Wrong input",var1

Hier wird zunächst die Verbindung getestet. Ansonsten wird auf eine „1“ aus dem Arduino gewartet (die wird übertragen, wenn der Knopf gedrückt wird, siehe Arduino-Sketch). Wird die erkannt, wird über subprocess das Skript start_booth_sequence.sh aufgerufen (nicht im Hintergrund, das heißt das Programm wartet mit der weiteren Ausführung bis das Skript fertig ist. Das verhindert, dass während der Booth-Sequenz ein erneutes Auslösen des Schalters alles durcheinander bringt) und der Input geflusht, sodass auf einen neuen Input gewartet werden kann. Das Ganze auch wieder in einer Endlosschleife.

Booth Sequence

Das Herzstück ist dann die eigentliche Booth Sequenz. Hier kommt es ganz speziell auf das Timing an. Es soll ein Countdown eingeblendet werden, damit man sich erstmal in Position bringen kann, dann muss die Kamera ausgelöst werden. Dann muss im richtigen Moment ein Screenshot des Video-Inputs gemacht werden. Das Ganze vier mal. Hier der komplette Ablauf:

Und hier das dazugehörige Skript:

echo Starting video input
bash /home/boris/Dokumente/photobooth/shellscripts/start_mplayer_composite_input.sh
sleep 2
echo Stopping slideshow...
bash /home/boris/Dokumente/photobooth/shellscripts/kill_slideshow.sh
echo Showing OSD...
bash /home/boris/Dokumente/photobooth/shellscripts/show_osd.sh
echo Trigger cam
python /home/boris/Dokumente/photobooth/shellscripts/trigger_camera.py
sleep 3
xdotool key s
sleep 1
echo Showing OSD...
bash /home/boris/Dokumente/photobooth/shellscripts/show_osd.sh
echo Trigger cam
python /home/boris/Dokumente/photobooth/shellscripts/trigger_camera.py
sleep 3
xdotool key s
sleep 1
echo Showing OSD...
bash /home/boris/Dokumente/photobooth/shellscripts/show_osd.sh
echo Trigger cam
python /home/boris/Dokumente/photobooth/shellscripts/trigger_camera.py
sleep 3
xdotool key s
sleep 1
echo Showing OSD...
bash /home/boris/Dokumente/photobooth/shellscripts/show_osd.sh
echo Trigger cam
python /home/boris/Dokumente/photobooth/shellscripts/trigger_camera.py
sleep 3
xdotool key s
sleep 1
echo Starting slideshow...
bash /home/boris/Dokumente/photobooth/shellscripts/start_slideshow_qiv.sh
sleep 2
echo Stopping video input
bash /home/boris/Dokumente/photobooth/shellscripts/kill_mplayer.sh

Start Video Input

Zuerst wird also der Video-Input gestartet und 2 Sekunden gewartet, damit ich sicher bin, dass dieser funktioniert:

cd /home/boris/Bilder/eyefi
mplayer -fs -vf screenshot -tv driver=v4l2:input=1:device=/dev/video1:norm=NTSC:chanlist=us-bcast:channel=3:alsa=1:adevice=hw.2:audiorate=4800 0:immediatemode=0:amode=1 tv://1 > /dev/null 2>&1 &
echo $! > /home/boris/mplayer_process.pid

Dazu habe ich den mplayer genutzt, der zudem auch gleich eine Screenshot-Funktion mitbringt. Wieder als Hintergrundprozess mit Wegschreiben der PID.

Kill Slideshow

Erst dann wird die Slideshow gekillt, damit nicht aus Versehen der Desktop zwischendurch zu sehen ist (sicherheitshalber habe ich diesen aber auch weiß gemacht und alle Icons und die Startleiste ausgeblendet).

kill -TERM $(cat  /home/boris/slideshow_process.pid)

Ein einfacher Kill-Befehl. In einem separaten Skript, da ich das des Öfteren wiederverwende.

On Screen Display

Hier habe ich zwei Varianten getestet. osd_cat war leider nicht wirklich zuverlässig, was die Anzeige anging, daher habe ich versucht mit sleep-Befehlen einigermaßen das Timing zu bekommen. War aber auch nicht zufriedenstellend. Darum habe ich mich nach Alternativen umgesehen und bin auf aosd_cat gestoßen und das funktioniert performant und sehr gut. Lediglich mit der Skalierung der Schrift hatte ich etwas zu kämpfen. Hier braucht man einen installierten Font, der auf die Größe skaliert werden kann. Am besten bin ich dann mit „bitstream bold 100“ gefahren. Der Countdown wird am oberen Bildrand (da ist der Weg zur Kameralinse kürzer) in rot angezeigt.

echo "5" | aosd_cat -R red --font="bitstream bold 100" --x-offset=620 --y-offset=-820 --transparency=2 --fade-full=500
echo "4" | aosd_cat -R red --font="bitstream bold 100" --x-offset=620 --y-offset=-820 --transparency=2 --fade-full=500
echo "3" | aosd_cat -R red --font="bitstream bold 100" --x-offset=620 --y-offset=-820 --transparency=2 --fade-full=500
echo "2" | aosd_cat -R red --font="bitstream bold 100" --x-offset=620 --y-offset=-820 --transparency=2 --fade-full=500
echo "1" | aosd_cat -R red --font="bitstream bold 100" --x-offset=620 --y-offset=-820 --transparency=2 --fade-full=500

Der Vollständigkeit halber hier mein Skript für osd_cat:

echo "5" | osd_cat --pos=top --color=red --delay=1 --age=0 --align=left --font="-*-clean-*-*-*-*-175-*-*-*-*-*-*-*" --shadow=5 --shadowcolour=black &
sleep 0.8
echo "4" | osd_cat --pos=top --color=red --delay=1 --age=0 --align=left --font="-*-clean-*-*-*-*-175-*-*-*-*-*-*-*" --shadow=5 --shadowcolour=black &
sleep 0.8
echo "3" | osd_cat --pos=top --color=red --delay=1 --age=0 --align=left --font="-*-clean-*-*-*-*-175-*-*-*-*-*-*-*" --shadow=5 --shadowcolour=black &
sleep 0.8
echo "2" | osd_cat --pos=top --color=red --delay=1 --age=0 --align=left --font="-*-clean-*-*-*-*-175-*-*-*-*-*-*-*" --shadow=5 --shadowcolour=black &
sleep 0.8
echo "1" | osd_cat --pos=top --color=red --delay=1 --age=0 --align=left --font="-*-clean-*-*-*-*-175-*-*-*-*-*-*-*" --shadow=5 --shadowcolour=black &

Kamera auslösen

Danach wird dann die Kamera ausgelöst. Da ich wieder mit dem Arduino kommunizieren muss, wieder über ein Python-Skript:

import serial

try:
	arduino = serial.Serial('/dev/ttyACM0', 9600)
except:
	print "Failed to connect to arduino"
arduino.write('1')

Auch recht einfach gehalten, es wird lediglich eine „1“ an den Arduino gesendet (der wartet darauf und löst dann die Kamera aus, siehe Arduino-Sketch).

Auf dem Arduino läuft folgendes Sketch:

#include <Metro.h>

int PIN_CAMERA_SONY = 2;
int PIN_CAMERA_PANASONIC = 8;

int buttonPin = 11;
int buttonState = 0;
unsigned long lastMeasureTimeButton = 0;
unsigned long measureTimeButton = 0;

unsigned long debounceDelay = 200;    // the debounce time
int cameraPin = PIN_CAMERA_PANASONIC;


void setup() 
{ 
  
  pinMode(buttonPin, INPUT);           // set pin to input
  digitalWrite(buttonPin, HIGH);       // turn on pullup resistors
  Serial.begin(9600);
  
  pinMode(cameraPin, OUTPUT);
  digitalWrite(cameraPin, LOW);
} 
 
 
void loop() 
{ 
  // Eingabe von PC erwartet
  if ( Serial.available()) // Prüfen, ob mindestens ein Zeichen vorhanden ist
  {
    char ch = Serial.read();
    if( isDigit(ch) ) // ASCII-Zeichen zwischen 0 und 9?
    {
       switch (ch) {
        case '0':    
          //
          break;
        case '1':    
          // trigger camera
          
          //Serial.println("trigger");
          digitalWrite(cameraPin, HIGH);
          delay(2000);
          digitalWrite(cameraPin, LOW);
          break;
        case 2:    
          //
          break;
        case 3:    
          //
          break;
        case 4:    
          //
          break;
        default:
            //Serial.println("default");
          ;//do nothing
       } 
    }
  }
  
  // Eingabe über Schalter erwartet
  int readingButton = digitalRead(buttonPin);
  if(readingButton != buttonState) {
    buttonState=readingButton;
    if(buttonState==LOW) {
      measureTimeButton=millis();
      if( (measureTimeButton - lastMeasureTimeButton) > debounceDelay ) {
          Serial.println("1"); //Button pushed debounced
      }
      lastMeasureTimeButton = millis();
    }
  }
}

Im Setup werden die Input-/Output-Pins bereit gemacht und die serielle Verbindung auf 9600 Baud eingestellt.

Im Loop wird dann geprüft, ob ein serieller Input verfügbar ist. Ist dem so, wird es eingelesen und geprüft um was es sich handelt. Wie schon beschrieben wird auf eine „1“ gewartet und dann der Kamera-Pin für kurze Zeit auf High gesetzt. Weiterhin wird der Button überwacht. Hier ist noch ein debouncing eingebaut. Wenn das alles normal funktioniert hat, wird eine „1“ an den PC gesendet.

Hier noch das Skript mit dem ich es über die Shell versucht habe (funktioniert glaube ich genau einmal, dann nicht mehr. Hatte glaube ich was mit dem Flush zu tun oder so…):

/home/boris/arduino-serial -b 9600 -p /dev/ttyACM0 -d 2000 -s 1

Screenshot

Mit dem Tool xdotool kann man ganz einfach Tastatureingaben simulieren. Da der mplayer mit der Taste „s“ einen Screenshot macht, wird einfach im richtigen Abstand zur Auslösung die Taste „s“ gesendet.

Ende der Sequenz

Am Ende wird einfach wieder die Slideshow mit dem o.g. Skript start_slideshow_qiv.sh gestartet (hier ist das neue Bild noch nicht erstellt, das passiert parallel im Hintergrund und nach erfolgter Erstellung wird ja die Slideshow neugestartet, wie oben beschrieben) und danach der Video-Input wieder beendet:

echo Shutting down mplayer...
if $(kill  $(cat /home/boris/mplayer_process.pid)); then echo Shutdown successful; exit 0; else echo Shutdown failed; exit 1; fi

Stop Photobooth

Das Stop-Skript führt im Grunde nur alle Kill-Skripte aus und beendet dann zur Sicherheit auch noch alle inotifywait-Prozesse. Die Skripte für die Slideshow und den MPlayer sind ja schon bekannt, hier also nur noch der Rest:

echo stopping mplayer
bash /home/boris/Dokumente/photobooth/shellscripts/kill_mplayer.sh
echo stopping slideshow
bash /home/boris/Dokumente/photobooth/shellscripts/kill_slideshow.sh
echo stopping Eye-Fi Server
bash /home/boris/Dokumente/photobooth/shellscripts/kill_eyefi_server.sh
echo stopping Booth Listener
bash /home/boris/Dokumente/photobooth/shellscripts/kill_booth_listener.sh
echo stopping collage maker
bash /home/boris/Dokumente/photobooth/shellscripts/kill_collage_maker.sh
killall inotifywait
#if $(ps ax | pgrep -f start_booth_listener > /home/boris/booth_listener.pid); then echo Booth Listener is running; else echo Booth Listener is not running; exit 0; fi
#echo Shutting down...
#if $(kill  $(cat /home/boris/booth_listener.pid)); then echo Shutdown successful; exit 0; else echo Shutdown failed; exit 1; fi
echo Shutting down booth listener...
if $(kill  $(cat /home/boris/booth_listener_process.pid)); then echo Shutdown successful; exit 0; else echo Shutdown failed; exit 1; fi
if $(ps ax | pgrep -f start_collage_maker > /home/boris/collage_maker.pid); then echo collage_maker is running; else echo collage_maker is not running; exit 0; fi
echo Shutting down...
if $(kill  $(cat /home/boris/collage_maker.pid)); then echo Shutdown successful; exit 0; else echo Shutdown failed; exit 1; fi

Eye-Fi

Da ich mit Eye-Fi auch schon recht weit gekommen bin, bis mich das Abstürzen der Lumix aufgehalten hat, will ich die entsprechenden Skripte nicht für mich behalten:

if $(ps ax | pgrep -f rifec > /home/boris/eyefiserver/rifec-master/rifec.pid); then echo Eye-Fi Server already running; exit 0; else echo Eye-Fi Server is not running; fi
if $(/home/boris/eyefiserver/rifec-master/rifec.pl --config=/home/boris/eyefiserver/rifec-master/rifec.config -d); then exit 0; else exit 1; fi

Hier wird nur geprüft ob der Eye-Fi Server bereits läuft (wie im vorherigen Post schon beschrieben benutze ich hier Rifec), ansonsten wird er gestartet.

Und auch das Kill-Skript ist recht einfach gehalten:

if $(ps ax | pgrep -f rifec > /home/boris/eyefiserver/rifec-master/rifec.pid); then echo Eye-Fi Server is running; else echo Eye-Fi Server is not running; exit 0; fi
echo Shutting down...
if $(kill  $(cat /home/boris/eyefiserver/rifec-master/rifec.pid)); then echo Shutdown successful; exit 0; else echo Shutdown failed; exit 1; fi

Fazit

Wie man sieht, habe ich viel in eigene Skripte gekapselt und mich um Flexibilität und Wiederverwendbarkeit bemüht. Allerdings wird mein Setup wohl so ein Sonderfall sein, dass damit wohl eh niemand anderes direkt 1:1 etwas anfangen kann 😉 Aber vielleicht gibt es ja den ein oder anderen Denkanstoß.

Im nächsten Teil gibt es dann wieder weniger technisches mit dem dritten Teil, dem Bau des eigentlichen Kastens. Je nachdem wie lang der wird, wird dann das fertige Produkt in einem weiteren Teil detaillierter vorgestellt.