Staumeldung durch KI-Bilder
Natürlich kann man morgens ins Web schauen, um sich ein Bild von der Verkehrslage zu machen. Oder man blickt auf diesen KI-Bilderrahmen neben der Tür: Der Raspberry Pi darin holt sich täglich per TomTom-API-Schnittstelle die aktuelle Fahrzeit ins Büro und lässt diese durch DALL-E in ein künstlerisches Bild verwandeln. Delphine und Düsenjäger auf dem Bild stehen für schnelles Durchkommen; erblickt man Buddha oder Schnecken, muss man mehr Zeit einplanen.
Spätestens als der Papst in gefakter weißer Balenciaga-Jacke viral ging, konnte man sehen, wozu das von OpenAI entwickelte KI-Bildgenerierungsprogramm DALL-E in der Lage ist: aus einfachen Texteingaben beeindruckende Bilder mit genau dem gewünschten Inhalt erzeugen, die sowohl fotorealistisch aussehen können, aber auf Wunsch auch beispielsweise wie ein Gemälde von Vincent van Gogh.
Statt diese Texteingaben (oder Prompts, wie sie auch heißen) von Hand einzutippen, kann man sie auch von Programmen erzeugen und die Bilder über die Programmierschnittstelle (API) von OpenAI abrufen. Noch einen Schritt weiter geht man, wenn die Bilder-Prompts aus Live-Daten erzeugt werden, die man über Webservices oder andere APIs abruft, so wie in diesem Projekt. Konkret wird im Folgenden gezeigt, wie man mit relativ geringem Aufwand automatisch aus den Daten von TomTom die voraussichtliche Fahrzeit ins Büro ermittelt, daraus DALL-E ein kreatives Bild erzeugen lässt, das auf einem selbstgebauten Display-Rahmen erscheint, in dem auch der Raspberry Pi steckt, auf dem alle nötigen Skripte laufen. Das aktuelle Verkehrslage-Bild wird einmal am Tag passend zur Pendelzeit erzeugt, ein Bewegungsmelder schaltet das Display ab, wenn niemand davor steht. Nachts wird das ganze per Zeitschaltuhr herunter- und morgens wieder hochgefahren.
In diesem Artikel tasten wir uns vom ersten API-Testaufruf bis zum fertigen Rahmen in nachvollziehbaren Schritten heran, sodass sich Teile aus meinem Projekt auch für andere Vorhaben nutzen lassen, in denen KI-Bilder erzeugt werden. Denn das Prinzip lässt sich natürlich auf alle anderen Datenquellen übertragen, seien es Aktienkurse, Feinstaubwerte, der Netzwerk-Traffic im LAN oder die Zahl der Likes in Social Media. Dabei kann man mehrere Aspekte durchaus in einem Bild kombinieren: So lässt sich die Verkehrsanzeige mit wenigen Ergänzungen im Code mit der Darstellung der Wetterlage als Hintergrund kombinieren.
Natürlich muss man manchmal etwas Fantasie entwickeln, um das Bild richtig zu interpretieren – der DALL-E-Staumelder ist ein KI-Kunstprojekt, kein Präzisionsmessinstrument. Aber er ist jeden Tag ein schicker und manchmal überraschender Hingucker.
Start mit DALL-E
Um Bilder mit DALL-E zu generieren – sei es über die Web-Oberfläche oder per API – ist eine Registrierung bei OpenAI notwendig (alle Links in der Kurzinfo). Die Schritte zur Anmeldung hatten wir bei der ChatGPT-Schreibmaschine im vorletzten Heft ausführlich beschrieben, deshalb hier nur ganz kurz: Nach der Registrierung bei OpenAI kann unter „Personal/View API keys“ ein API-Schlüssel für die Kommunikation zwischen dem Raspberry Pi und DALL-E erzeugt werden. Bei der ersten Anmeldung bei OpenAI bekommt man initial ein in der Menge und zeitlich begrenztes Budget an Credits, es ist unter „Manage Account“ einsehbar. Für den API-Aufruf zum Erstellen der ersten Bilder reicht der Betrag anfangs gut aus. Will man die Visualisierung auf Dauer benutzen, muss man zahlen – mehr dazu steht im Kasten.
Jetzt aber her mit den Bildern: Gibt man DALL-E per API oder übers Eingabefeld der Website zum Beispiel „muppet“ als Prompt vor, generiert die KI ein paar nette Bilder nach dieser Vorgabe.
Um aber ein wirklich gutes Bild zu bekommen, sollte man weitere Eingaben hinzufügen, die beispielsweise den Stil, den Hintergrund, Stimmung, Kamerawinkel und ähnliches beschreiben. Das ist inzwischen eine Kunst für sich, nennt sich „prompt design“ (manche sagen auch „prompt engineering“). Etliche YouTube-Videos zum Beispiel geben hierfür detaillierte Hinweise. Wir versuchen mal folgendes: „professional photo of a happy muppet character, on a ship deck, high detail, 300mm telephoto lens”. Schon besser, oder?
DALL-E per API
In meinem Display-Rahmen, den ich später zur Anzeige der Stau-Visualisierungen verwende, wurde ein Raspberry Pi 3B verbaut. Der Nachbau geht natürlich auch mit anderen Raspberry-Modellen mit WLAN; die im Folgenden gezeigten API-Zugriffe mittels Python funktionieren darüber hinaus von beliebigen anderen Systemen mit Netzzugang.
Ich habe erst einmal mit dem Pi Imager das Raspberry Pi OS (32-Bit) auf die SD-Karte aufgepielt (Links zum Download und Anleitungen siehe URL in der Kurzinfo) und dann anschließend die Karte in den Raspi gesteckt. Nach der initialen Konfiguration und dem Update der Programme sollte bei den „Einstellungen/Pi Konfiguration/Schnittstellen/VNC“ angeschaltet werden. Das hilft sehr, um den digitalen Rahmen später vom PC aus fernsteuern zu können. Rechts unten im Tray ist ein VNC-Icon, dort steht dann auch die IP-Adresse des Raspis. Das VNC-Programm für Windows gibt es zum kostenlosen Download (siehe Kurzinfo-Link).
Im nächsten Schritt wird das Python-Paket openai auf dem Raspi installiert:
pip install openai
Um als ersten Test ein Bild mit Python zu generieren, kopiert man den Python-Code im Kasten in das auf dem Raspberry Pi vorinstallierte Tool Thonny.
n ist hierbei die Anzahl der zu erstellenden Varianten, size gibt die Pixelgröße des Bilds an. Thonny gibt anschließend unten in der Shell den URL-Link zum Ergebnis aus, das man dann über den Browser abrufen kann.
Soll nun das Bild auf dem Desktop gesichert werden, ergänzen wir den Code unten um:
import urllib.request urllib.request.urlretrieve( image_url, "/home/pi/Desktop/Bild.jpg")
Das fertige Programm kann man nun auf dem Desktop etwa unter dem Namen Dalle_generate.py speichern. Um das Programm später automatisch ausführbar zu machen, setzt man per Terminaleingabe die nötigen Rechte:
chmod +x
/home/pi/Desktop/Dalle_generate.py
Anfrage per Zufall gestalten
Damit DALL-E abwechslungsreiche Bilder generiert, können dem Aufruf per Zufall Parameter für das dargestellte Objekt, den Stil oder die Umgebung mitgegeben werden. Das erweiterte Programm Dalle_generate.py sieht dann aus wie im gleichnamigen Kasten. Das Programm gibt es auch über den Link in der Kurzinfo zum Download.
Fahrzeitprognose
Jetzt sollen aber keine zufälligen Bilder erzeugt werden, sondern solche, die die voraussichtliche Fahrzeit auf der morgendlichen Pendelstrecke symbolisieren. Diese Darstellung ist sicher nichts für Menschen, die Wert auf exakte Angaben legen. Zahlen oder Buchstaben kann DALL-E nämlich (noch) nicht sinnvoll ausgeben. Stattdessen sieht mein Programm deshalb Schwellwerte für die Fahrzeit vor (unter 15 Minuten, unter 20 etc.) und hat für jedes Intervall zwischen Schwellwerten eine Liste von Objekten, aus denen es per Zufall eines wählt, das es dann zur Bildgenerierung an DALL-E schickt. Ist beispielsweise die ermittelte Fahrzeit von unter 15 Minuten für den Weg ins Büro morgens recht kurz, dann wählt das Programm aus der Liste z.B. einen Delphin. Werden hingegen lange 27 Minuten prognostiziert, dann kann das Bild auch mal eine Schnecke zeigen (siehe Listing Intervalle).
Um die aktuelle Fahrzeit zu ermitteln, werden die GPS-Koordinaten vom Start- und Zielpunkt an TomTom geschickt. Für die Kommunikation mit TomTom wird wiederum ein API Key benötigt, den man kostenlos erstellen kann (Link in der Kurzinfo). Außerdem braucht man noch die genauen GPS-Koordinaten in dezimaler Schreibweise, auch dafür haben wir bei den Links einen Webdienst im Angebot.
Ein einfaches Programm zum Testen des API-Zugriffs zeigt der Kasten TomTom.py.
Jetzt wird die ermittelte Fahrzeit totalTime durch die Schwellwerte ins richtige Intervall sortiert und aus der jeweiligen Liste zufällig ein entsprechendes Objekt ausgewählt. Dann genügt morgens ein Blick auf den digitalen Rahmen, um zu sehen, ob die Fahrt ins Büro heute flott geht oder mal wieder länger dauert. Dabei ist natürlich jedem selbst überlassen, welche und wie viele Objekte man definiert – Hauptsache, man behält sein eigenes System im Kopf.
Den so ergänzten Code von Dalle_generate.py gibt es über den Link in der Kurzinfo zum Download.
In den Rahmen bringen
Die Visualisierung der aktuellen Fahrzeit funktioniert jetzt soweit. Nun muss das ganze noch alltagstauglich verpackt und automatisiert werden.
Aktuell kann DALL-E nur quadratische Bilder mit den Größen "256x256", "512x512" oder "1024x1024" Pixel erzeugen. Das erklärt auch, warum ich in meinem Bilderrahmen ein altes 4:3-Display verbaut habe – bei einem 16:9-Display bliebe zu viel ungenutzte Bildfläche links und rechts am Rand. Und außerdem gibt es bei eBay solche alten Laptop-Displays schon für kleines Geld, falls die Bastelkiste keines mehr zu bieten hat.
Zum Ansteuern des Displays wird dann ein spezifisches HDMI-VGA-Display-Controller-Board für um die 25 Euro benötigt. In der Regel laufen die Display-Controller-Boards mit 12V, die Stromversorgung des Raspi aber nur mit 5V, sodass noch ein DC-DC-Step-Down-Converter zum Einsatz kommt.
Für die Anzeige auf dem Display benötigen wir ein weiteres Skript, das auf dem Desktop unter dem Namen Dalle_display.py gespeichert wird (siehe Kasten). Hier sorgt pygame für die Anpassung der Bildgröße an das Display. Wie zuvor wird dieses Programm mit
chmod +x
/home/pi/Desktop/Dalle_display.py
ausführbar gemacht. Führt man das Skript in Thonny über Run aus, sollte nun das zuvor auf dem Desktop gespeicherte Bild für fünf Sekunden als kleines Fenster mit 300 mal 300 Pixeln auf dem Display angezeigt werden.
Bewegungsmelder und Button
Wenn das soweit funktioniert, wird der Bewegungsmelder eingebaut (Anschluss an GPIO 23), damit das Display nur angeht, wenn jemand am Rahmen vorbeiläuft. Den HDMI-Ausgang am Raspi schaltet man durch
vcgencmd display_power 0
aus und durch
vcgencmd display_power 1
an. Der Befehl funktioniert allerdings erst nach einer Konfigurationsänderung mittels
sudo nano /boot/config.txt
In dieser Datei ersetzt man den Eintrag
dtoverlay=vc4-kms-v3d
durch
dtoverlay=vc4-fkms-v3d
Danach ist ein Reboot fällig.
Ergänzt habe ich auch noch einen Button (Anschluss an GPIO 24) zum manuellen Generieren eines neuen Bilds, falls das automatisch erzeugte mal wirklich gar nicht gefällt. Dazu drückt man während der Bildanzeige auf den Taster und das Programm Dalle_generate.py wird als Unterprozess aufgerufen und damit ein neues Bild erzeugt.
Den vollständigen Code dieses Setups gibt es über den Link in der Kurzinfo zum Download. Es empfiehlt sich, die Anzeigedauer erstmal kürzer als die dort vorgesehenen 60 Sekunden einzustellen, und sich von den 300 Pixeln Kantenlänge sukzessive an die optimale Größe und Position des Bilds auf dem Display ranzutasten (mehr dazu in den Kommentaren im Code).
Autostart
Zum automatischen Starten des Display-Programms wird PM2 genutzt, ein Prozessmanager für Node.js. Dazu sind im Terminal ein paar Installationen fällig (nodejs, npm und schließlich pm2 selbst):
sudo apt update sudo apt install nodejs sudo apt-get install npm sudo npm install pm2 -g
Weil ich meinen Rahmen nachts mittels Zeitschaltuhr abschalte, muss dafür gesorgt werden, dass PM2 beim Neustart wieder läuft:
pm2 startup
Zum Schluss muss auch noch ein Pfad gesetzt werden, wie von PM2 vorgegeben (alles in eine Zeile tippen oder vom Terminal kopieren):
sudo env PATH=\$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u pi --hp /home/pi
Anschließend mit reboot neu starten und das Display-Programm bei PM2 registrieren:
pm2 start
/home/pi/Desktop/Dalle_display.py
Achtung: das Display-Programm wird jetzt gestartet und setzt das Display sofort auf display_power 0. Damit man wieder etwas sieht, kurz den Bewegungsmelder aktivieren und während der Bildanzeige irgendeine Taste drücken. Damit wird das Programm in PM2 erst einmal gestoppt.
Noch Abspeichern, damit nach einem Boot das Programm wieder automatisch gestartet wird:
pm2 save
Das Display-Programm läuft nun immer im Hintergrund und reagiert auf die Bewegung und den Button.
Mit pm2 list kann man sehen, ob das Programm aktuell läuft, und, falls mehrere Programme in PM2 registriert sind, unter welcher ID (siehe Screenshot). Der aktuelle Status von Dalle_display ist dort stopped. Starten geht mittels:
pm2 start 0
Bilder holen mit Crontab
Damit der Raspi jeden Morgen ein neues Bild erzeugt, speichern wir per Terminal einen Eintrag in Crontab:
crontab -e
Ganz unten hinein kommt dann die neue Zeile (in einer Zeile eintippen):
15 8 * * * python /home/pi/Desktop/Dalle_generate.py
Nach speichern (Ctrl+O) und verlassen (Ctrl+X) läuft nun jeden Tag um 8:15 Uhr das Python-Skript Dalle_generate.py. Das ist für mich genau rechtzeitig, bevor es morgens ins Büro geht.
Und jetzt: Das Wetter
Falls nun im Hintergrund noch die Wettervorhersage auf dem Bild erscheinen soll, kann man diese bei OpenWeatherMap (OWM) per API abrufen (siehe Link in der Kurzinfo). Das läuft ähnlich wie bei TomTom, also erst registrieren und dann den eigenen API-Key erzeugen.
Von den zurückgelieferten detaillierten Wetterdaten wird für mein DALLE-E Bild nur die Variable descr für die Beschreibung der Wetterlage verwendet; wer möchte, kann aber andere Daten ins Bild einfließen lassen, der Kreativität sind hier kaum Grenzen gesetzt. Der komplette Code von Dalle_generate.py inklusive Wettervorhersage ist ebenfalls bei den Downloads hinterlegt.
Schauen wir mal was der Rahmen heute morgen sagt (siehe Titelbild dieses Artikels): Aha, einiger Stau und leichte Bewölkung. Dann mal los! —pek