Heute werde ich euch den Aufbau unsere AI Komponenten näherbringen und auf ihre Kommunikation untereinander eingehen. Dafür möchte ich zu Beginn die drei Hauptmodule, die wir nutzen, erläutern: Opencv3, Zbar und Face Recognition.
„Opencv3“ ist eine Library zur Bild Analyse in C++. Ihre Stärke liegt dabei im real-time Computer Vision Bereich. In unserem Projekt nutzen wir diese Library zur Modulation der Farben des von der PiCamera aufgenommenen Bildes und zur Bewegungserkennung.
Auf die Bewegungserkennung als solches möchte ich an dieser Stelle eingehen. So läuft diese wie folgt ab: Es werden die drei zuletzt aufgenommenen Bilder miteinander verglichen. Zu Beginn werden die Bilder in Schwarzweiß umgewandelt (die Farbinformationen würden nur stören und den Vergleich der Bilder erschweren) und in „Numpy Arrays“ konvertiert. Im Anschluss daran wird jeweils zwischen Bild 1 und 2, sowie zwischen 2 und 3 die absolute Differenz gebildet (von den Subtraktionsergebnissen wird der Betrag genommen), um die Veränderungen zwischen den Aufnahmen festzustellen. Abschließend wird nun eine bitweise Addition durchgeführt, um den Durchschnitt der Veränderung zu bestimmen, dies sorgt für eine robustere Erkennung; „Fehlalarme“ werden minimiert. Nachdem der Vergleich abgeschlossen ist, werden in dem verknüpften „Numpy Array“ die Zahlen, die nicht null sind, gezählt. Dieser Wert stellt nun die Veränderung dar. Ist dieser größer als ein von uns gesetzter Threshold wird eine Nachricht abgesetzt.
Abbildung 1: Code Movement Detection
„Zbar“ ist eine Library, die es ermöglicht QR-Codes und Strich-Codes auszulesen. Der Einsatz ist dabei extrem einfach. Es bedarf lediglich einer Zeile Code, um die Funktionalität zu nutzen. „Zbar“ übernimmt dabei nicht nur das Auslesen des Codes sondern auch die Erkennung jenes auf einem Bild.
Abbildung 2: Code QR Detection
In der decQR Variable wird nun im Falle der Erkennung eines QR- bzw. Strich-Codes die Daten des selbigen in einer Objektstruktur gespeichert.
Als letztes möchte ich noch auf die Gesichtserkunngslibrary eingehen. Wir haben uns ausdrücklich gegen Haar Cascade entschieden, da diese zwar über eine guter Performance verfügt, aber eine schlechtere Erkennungsrate, verglichen mit der von uns genutzen auf dlib basierenden „Face Recognition“ Library besitzt. So weist der von uns genutzte Algorithmus eine Trefferquote von 99.38% bei dem „Labeled Face in the Wild“ Benchmark.
Abbildung 3: Code Facial Detection
Der Code ist dabei denkbar einfach. So beziehen wir in Zeile 35 ein Bild aus einer Pipe, welches wir in Zeile 36 in Graustufen umwandeln. Dank dieser Transformation sind in der Regel höhere Erkennungsraten möglich. Zusätzlich fallen die Farbinformationen weg, was die Performance verbessert. Im letzten Schritt wird nun die Library genutzt, um Gesichter zu identifizieren. Diese gibt ein Objekt zurück, welches die Koordinaten der einzelnen Gesichter enthält.
Insgesamt zeigt sich, dass es durch die Librarys sehr einfach ist, die Möglichkeiten von „Artificial Inteligence“ zu nutzen. Die Komplexität in unserem Projekt entsteht dabei durch das Zusammenspiel bzw. die Parallelisierung dieser drei Komponenten und der Pipes sowie Queue, die den Datenaustausch regeln. Auf dieses Konstrukt möchte ich im Folgenden näher eingehen. Dabei ist es wichtig, zuerst die zentralen Unterschiede zwischen Pipes und Queue zu betrachten (Es wird sich hier auf die Implementierung im Multiprocessing Module von Python bezogen, andere Umsetzungen können stark davon abweichen). Zwar eignen sich beide zum Transfer von Daten, allerdings sind Pipes ca. 1.5 bis 2-mal schneller als Queues. Mit Pipes ist es lediglich möglich zwei Prozesse zu verbinden, auf Queues können beliebig viele zugreifen. Auch ist es möglich bei Queues einen Buffer einzustellen, also wie viele einzelne Datenteile (Objekt, primitiver Datentyp) sich in der Queue befinden dürfen, bei Pipes ist es ausschließlich ein Element.
Abbildung 4: Aufbau der Thread-Kommunikation
Es wurde bei der Darstellung darauf verzichtet, die Pipes bzw. Queue zu vermerken, die nur dazu dienen einzelne Threads zu beenden (in dem Returns getriggert werden). Nun möchte ich auf die einzelnen Elemente eingehen. „GlobalCom“ ist wie der Name bereits vermuten lässt, der zentrale Kommunikationshub. Über diese Queue tauschen alle Threads Informationen aus. Beispielsweise, wenn eine Bewegung erkannt wurde, meldet Movement Detektion „movement“. Daraufhin startet Central die Face Detection, diese wiederum meldet bei der Registrierung eines Gesichtes „Face Detected“. Die Pic Queue ist dafür zuständig, die erkannten Gesichter und QR-Codes zurück an Central zu schicken, wo diese dann über Intercom (mittels Unix Pipes) an das Node-Backend weitergeleitet werden. Der Pictureprovider hat die Aufgabe alle drei Detektoren mit Bildern zu versorgen. Dies geschieht im Falle von QR und Facial mittels Pipes für schnellere Zugriffszeiten (Auch kann mittels Pipes einfacher gewährleistet werden, dass sich kein Bild mehr in der Verbindung zwischen den Threads befinden und ggf. zu einem Öffnen der Tür führen würde, ohne dass jemand davorsteht bzw. nicht dazu berechtigt ist) und bei der Movement Detection mittels einer Queue zur Pufferung.
Das erstellte Gesamtkonstrukt sieht wie folgt aus:
Ich hoffe, ich konnte euch einen kleinen Überblick über unsere AI Landschaft und ihren Betrieb vermitteln. Falls es Fragen geben sollte, stehe ich gerne zur Verfügung.