12. Okt 2020
Lesedauer 11 Min.
Bildinhalte erfassen
OpenCV mit Python, Teil 2
Eine der Stärken von OpenCV ist die Geschwindigkeit der eingebauten Algorithmen.

Der erste Artikel über die OpenCV-Bibliothek [1] hat die einfachen Funktionen für die Bearbeitung von Bildern vorgestellt. Dazu gehören das Laden und Speichern, das Schärfen und das Transformieren von Bildinhalten. Diese Funktionalitäten sind die Grundvoraussetzungen für die weitere Bildverarbeitung, also das Ermitteln des Bildinhalts. So könnte man zum Beispiel feststellen, wie viele – und welche – Münzen auf einem Bild zu sehen sind. Oder man möchte die Schrauben und Muttern auf einem Fließband zählen. Es geht also darum, zu erkennen, was auf den Bildern abgebildet ist. Die erforderlichen Rechenalgorithmen sollen hier in diesem Artikel zumindest teilweise vorgestellt und in einfachen Szenarien angewendet werden.OpenCV (Open Computer Vision) soll natürlich auch mit bewegten Bildern schnell und zuverlässig funktionieren. So ist es sehr interessant für das autonome Fahren, ob am Straßenrand ein Auto parkt oder ein Mensch steht, der die Straße überqueren möchte. In diesem Fall spielt dann natürlich auch die Performance der Bibliothek eine sehr große Rolle, denn eine Bildanalyse ist ziemlich sinnlos, wenn das Ergebnis erst zehn Sekunden zu spät zur Verfügung steht.
Ecken entdecken
Im vorangegangenen Artikel [1] haben Sie schon einen Algorithmus kennengelernt, der Kanten in einem Bild entdecken kann. Im nächsten Beispiel wird es nun darum gehen, die Ecken der Objekte in einem Bild zu ermitteln.Das hierfür benutzte Verfahren ist der Harris-Algorithmus, der natürlich ebenfalls von der OpenCV-Bibliothek zur Verfügung gestellt wird. In den Downloads zum Artikel finden Sie im Unterverzeichnis Images zwei Bilddateien (Bild1.jpg und Bild2.jpg), die ein Abbild eines grauen und eines weißen Quaders enthalten. Wenn man die Sache zunächst einmal theoretisch betrachtet, dann hat ein Würfel acht Ecken, von denen in einem zweidimensionalen Bild nur sieben Ecken zu sehen sind. Listing 1 zeigt ein Python-Programm, das die sichtbaren Ecken der Quader-Objekte ermitteln soll.Listing 1: Ecken ermitteln
<span class="hljs-keyword">import</span> cv2 <br/><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np <br/><br/># Bild laden und Graubild erstellen <br/>img = cv2.imread(<span class="hljs-string">".\images\Bild1.jpg"</span>) <br/>#img = cv2.imread(<span class="hljs-string">".\images\Bild2.jpg"</span>) <br/>grauImg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) <br/>grauImg = np.float32(grauImg) <br/><br/># Harris Ecken-Algorithmus <br/>corner = cv2.cornerHarris(grauImg, blockSize = <span class="hljs-number">14</span>, <br/> ksize = <span class="hljs-number">5</span>, k = <span class="hljs-number">0.05</span>) <br/><br/># Eck-Pixel mit <span class="hljs-string">'dilate'</span> verstärken <br/>kernel = np.ones((<span class="hljs-number">5</span>, <span class="hljs-number">5</span>), np.float32) <br/>corner = cv2.dilate(corner, kernel, <span class="hljs-number">1</span>) <br/><br/># Ecken im Bild <span class="hljs-string">'img'</span> als rote Punkte markieren <br/>img[corner &gt; <span class="hljs-number">0.01</span> * corner.max()] = [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">255</span>] <br/><br/># Ergebnisbild ausgeben <br/>cv2.imshow(<span class="hljs-string">"Harris (scharfe Kanten)"</span>, img) <br/>cv2.waitKey(<span class="hljs-number">0</span>)
Das kleine Programm beginnt mit den erforderlichen import-Befehlen. Als Nächstes wird ein Farbbild geladen und mit cvtcolor in ein Schwarz-Weiß-Bild umgewandelt. Hier erhalten wir ein neues Image-Objekt grauImg. Das Farbbild wird später noch benötigt und bleibt in der Variablen img erhalten. An dieser Stelle kann man zwischen zwei Bildern wählen, um den Algorithmus zu testen. Bild1.jpg enthält einen grauen Quader vor einem hellen Hintergrund. Bild2.jpg zeigt einen weißen Quader mit einem dunklen Hintergrund.Nun konvertieren wir das Graubild in ein numpy-Array von Typ float32. Die Erzeugung und die verfügbaren Rechenmethoden dieser Arrays wurden bereits in einem früheren Artikel [2] ausführlich vorgestellt.Jetzt kann der Harris-Ecken-Algorithmus mit dem Funktionsaufruf cornerHarris angewendet werden. Die in Listing 1 angegebenen Parameter haben einen großen Einfluss auf das Ergebnis: Nach der Angabe des Image-Objekts wird der Parameter blockSize gesetzt. Dieser Wert bestimmt die Größe des Blocks mit seinen Nachbar-Pixeln, den es auszuwerten gilt. Je kleiner der Wert ist, desto feinere Strukturen im Bild führen zu einer Ecke. Wenn blockSize zu klein ist, erhält man also im Ergebnis auch einige „Ecken“, die gar keine sind. Dies wird gut erkennbar, wenn Sie mit Bild2.jpg den Parameter blockSize=6 setzen und die Analyse ausführen. Hier liefern einige Kratzer im Hintergrund eine „Ecke“, die gar keine ist. Auf der anderen Seite muss der Block der Nachbar-Pixel aber auch groß genug sein, um eine Ecke überhaupt zu erkennen.Die vom Algorithmus ermittelten „Ecken“-Pixel werden im Image-Objekt corner abgelegt. Der Parameter ksize gibt die Größe für den Sobel-Kernel an, der Kanten erkennen kann. Der letzte Parameter k ist der freie sogenannte Harris-Detektor-Parameter, der in die Formel eingeht, welche die Gradienten der Helligkeiten auswertet, um die Ecken zu ermitteln. Die Formel wird in der OpenCV-Dokumentation im Abschnitt der cornerHarris-Funktion vorgestellt [3].Als Nächstes sollen diese Pixel im Image corner mit der dilate-Funktion etwas verstärkt werden, damit man sie im finalen Ausgabebild besser erkennen kann. Die dilate-Funktion erhält das zu bearbeitende Image als ersten Parameter. Danach folgt eine Kernel-Matrix der Größe 5, die in den Diagonalelementen nur die Zahl „Eins“ enthält. Diese Matrix soll einmal (dritter Parameter) angewendet werden, um das Bild zu verstärken. Das Ergebnisbild wird wieder in der Variablen corner abgelegt.Nun soll das Ecken-Ergebnis corner mit dem Ursprungsbild img kombiniert werden. Dies lässt sich mit der folgenden Code-Zeile realisieren:
img[corner > <span class="hljs-number">0.01</span> * corner.max()] = [<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">255</span>]
Einerseits werden hier die vereinfachten Rechenmöglichkeiten mit numpy-Arrays benutzt. Andererseits wird in den eckigen Klammern ein Grenzwert festgelegt (hier: 0.01 * corner.max()). Immer wenn der Pixelwert im corner-Image größer als dieser Grenzwert ist, soll im Ergebnisbild img ein roter Pixel gesetzt werden. Schleifen sind hier nicht notwendig, da der Python-Interpreter die Befehle automatisch über alle Elemente des Arrays img laufen lässt.Nun müssen wir das Ergebnis nur noch mit imshow ausgeben und die waitKey-Funktion aufrufen. Bei der Betrachtung des Ergebnisses in Bild 1 sieht man sofort, dass bei unserer Parameterwahl zwei Ecken nicht gefunden werden. Hier sind die Grauunterschiede wahrscheinlich zu gering, sodass die Ecken nicht erkannt werden. Abhilfe kann zum Beispiel die Vergrößerung des Parameters blocksize schaffen.

Gefundene Eckendes grauen Quaders(Bild 1)
Autor
Wenn man das Beispielprogramm aus Listing 1 auf die Datei Bild2.jpg des ersten Artikels anwendet, kann man sehen, dass die Enden der Linien (rote Markierungen) sehr gut erkannt werden (vergleiche Bild 2). Der Kreis dagegen liefert natürlich keine Eckpunkte. Die Analyse eines Bildes mithilfe der Eckpunkte wird immer schwieriger, je mehr Details das Image enthält.
Formen erfassen

Eckenan Linienendenerkennen(Bild 2)
Autor
Im nächsten Schritt sollen nun einfache grafische Objekte (englisch: shapes) in einem Bild erkannt werden. Die Grundlagen dafür haben wir in den vorherigen Beispielen gelernt.Um ein grafisches Grundelement (Kreis, Rechteck, Banane …) zu identifizieren, muss man zunächst einmal den Umriss des jeweiligen Objekts ermitteln. Dies lässt sich mithilfe der bereits bekannten Kanten- und Ecken-Algorithmen erledigen. Bild 3 zeigt eine Zusammenstellung verschiedener grafischer Elemente.

Grundelementegrafischer Formen(Bild 3)
Autor
Auf der linken Seite des Bildes befindet sich die „Banane“, die identifiziert werden soll. Dazu benötigen wir zunächst ein Vergleichsbild für eine „Standardbanane“ (Bild 4).

Vergleichsbildder „Standardbanane“(Bild 4)
Autor
Der einfachste Algorithmus, der die Banane aus Bild 4 in Bild 3 entdeckt, funktioniert durch die Zählung der Pixel, die zu einem grafischen Objekt gehören. Das bedeutet, dass man zuerst die Umrisse aller Objekte ermittelt, dann die Pixel zählt, die zu dem jeweiligen Shape gehören, und schließlich prüft, welche ermittelte Pixelsumme der Standardbananen-Pixelsumme in Bild 4 am nächsten kommt.Diese einfache Variante ist aber nicht sonderlich genau. In Wirklichkeit ist die Sache also etwas komplizierter. Es werden die sogenannten Hu-Momente berechnet, die angeben, wie gut die Übereinstimmung zweier Konturen ist. Die Mathematik, die hinter der Hu-Moment-Berechnung steckt, wird sehr ausführlich in [4] erklärt. Die Berechnung des Moments I erfolgt prinzipiell folgendermaßen:
I = ∑ wi * pik
Hier sind pi die Pixel der Grafik in der Potenz k. wi sind die Wichtungen der einzelnen Pixel pi. Dabei handelt es sich in der Regel um Funktionen f(x, y), die zum Beispiel bestimmte Teile eines Grafikelements stärker bewerten können als andere Bereiche. Für das gesamte Moment I wird die Summe über alle Pixel i berechnet.Zum Glück stellt uns OpenCV die Funktion matchShapes zur Verfügung, der einfach einen skalaren Wert zurückgibt, der die Übereinstimmung zweier Grafikelemente bestimmt. Die Sache ist dann ganz einfach: Je kleiner der Rückgabewert, desto besser die Übereinstimmung (optimale Übereinstimmung ergibt den Wert 0.0).Jetzt aber los! Wir wollen die Grafik aus Bild 4 in Bild 3 finden. Das komplette Programm wird in Listing 2 gezeigt.Das Programm beginnt wie üblich mit den verwendeten Bibliotheks-Modulen. Danach erfolgt die Definition zweier grundlegender Funktionen: getAllContour analysiert ein Bild und sucht alle Konturen der grafischen Elemente. Die Funktion getRefContour ermittelt die Kontur der Grafik im Referenzbild und gibt die Konturfläche an den Aufrufer zurück.
Listing 2: Ein Grafikelement suchen … und finden
import cv2 <br/>import numpy as np <br/><br/># Alle Konturen in einem Image ermitteln <br/>def getAllContour(img): <br/> imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) <br/> ret, thresh = cv2.threshold(imgGray, 127, 255, <br/> cv2.THRESH_BINARY) <br/> contours, hierarchy = cv2.findContours(<br/> thresh.copy(), \ <br/> cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) <br/> return contours <br/><br/># Kontur im Referenzbild ermitteln <br/>def getRefContour(img): <br/> contours = getAllContour(img) <br/><br/> for contour in contours: <br/> area = cv2.contourArea(contour) <br/> imgArea = img.shape[0] * img.shape[1] <br/><br/> # Hier wird das Verhältnis von Gesamtfläche <br/> # des Bildes und des Grafikelements bestimmt <br/> if 0.05 &lt; area / float(imgArea) &lt; 0.8: <br/> return contour <br/><br/> return None <br/><br/>######### Hauptprogramm ################# <br/># Ein Referenzbild laden (Standardbanane) <br/>imgRef = cv2.imread(".\images\Bild4.png") <br/>#imgRef = cv2.imread(".\images\Bild5.png") <br/><br/># Das Testbild laden (mehrere Grafikelemente) <br/>imgTest = cv2.imread(".\images\Bild3.png") <br/><br/># Konturen ermitteln <br/>contRef = getRefContour(imgRef) <br/>contTest = getAllContour(imgTest) <br/><br/># Vergleich der Referenzkontur mit den <br/># im Bild gefundenen Konturen <br/>resultCont = None <br/>minDist = None <br/>i = 0 <br/>imgCont = imgTest.copy() <br/><br/># Alle Konturen in Rot einzeichnen <br/>cv2.drawContours(imgCont, contTest, -1, color=(<br/> 0, 0, 255), thickness=2) <br/>cv2.imshow("Gefundene Konturen", imgCont) <br/>cv2.imshow("Referenzfigur", imgRef); <br/><br/># Liste aller gefundenen Konturen abarbeiten <br/>for cont in contTest: <br/> i += 1 <br/> # Ermittlung der Übereinstimmung <br/> ret = cv2.matchShapes(contRef, cont, <br/> cv2.CONTOURS_MATCH_I3, 0.0) <br/> print("Kontur Nr. %d passt zu %f" % (i, ret)) <br/><br/> # Übereinstimmungswert und Kontur merken, wenn <br/> # besser <br/> if minDist is None or ret &lt; minDist: <br/> minDist = ret <br/> resultCont = cont <br/><br/># Ergebnisausgabe, gefundene Kontur in Grün markieren <br/>cv2.drawContours(imgTest, resultCont, -1, color=(0, <br/> 255, 0), thickness=4) <br/>cv2.imshow("Bester Treffer", imgTest) <br/><br/>cv2.waitKey(0) <br/>######## Ende des Hauptprogramms ##########
Die einzelnen Konturen in einem Bild werden mit der OpenCV-Funktion findContours gesucht. Vorher wird vom Originalbild ein Graubild erstellt und dann mit der Funktion threshold ein Bild generiert, das nur noch zwei Farbstufen enthält, zum Beispiel Weiß und Schwarz. Wenn der Wert im Graubild kleiner ist als der angegebene Grenzwert (zweiter Parameter), wird das Ergebnispixel auf 0 (schwarz) gesetzt, ansonsten auf den angegebenen Maximalwert (dritter Parameter). Die Funktion findContours ermittelt nun die Konturen und stellt sie als Liste zusammen.In der Funktion getRefContour erfolgt zunächst die Ermittlung aller vorhandenen Konturelemente. Nun wird die Fläche der Kontur festgestellt und ins Verhältnis zur Gesamtfläche des Bildes gesetzt. Ist dieser Wert größer als 0.05 und kleiner als 0.8, wird die Kontur als Referenzergebnis zurückgegeben.Kommen wir nun zum Hauptprogramm in Listing 4. Zunächst wird das Referenzbild (imgRef) geladen, danach das Testbild (imgTest), indem das Referenzobjekt gesucht werden soll. Danach sind die Konturen zu ermitteln. Nach der Initialisierung einiger Variablen wird ein Bild mit den gefundenen Konturen (imgCont) zur Kontrolle erstellt. Außerdem wird ein Bild der Referenzfigur (imgRef) ausgegeben.
Listing 4: Gesichter und Augen erkennen
import cv2 <br/>import numpy as np <br/><br/># Classifier instanzieren (Gesichter, Augen) <br/>faceCascade = cv2.CascadeClassifier(<br/> 'haarcascade_frontalface_default.xml') <br/>eyeCascade = cv2.CascadeClassifier(<br/> 'haarcascade_eye.xml') <br/><br/># Ein Bild mit Gesicht laden, Graubild erstellen <br/>img = cv2.imread('.\images\Bild6.jpg') <br/>#img = cv2.imread('.\images\Bild7.jpg') <br/>frameGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) <br/><br/># Gesichter ermitteln <br/>faceRects = faceCascade.detectMultiScale(<br/> frameGray, 1.3, 5) <br/><br/># Schleife über alle gefundenen Gesichter <br/>for (x,y,w,h) in faceRects: <br/> cv2.rectangle(img, (x,y), (x+w, y+h), (<br/> 0, 255, 0), 2) <br/> # Gesichtsausschnitt für Augensuche <br/> faceGray = frameGray[y:y+h, x:x+w] <br/> faceColor = img[y:y+h, x:x+w] <br/> # Augen ermitteln <br/> eyesRects = eyeCascade.<br/> detectMultiScale(faceGray) <br/><br/># Alle Rechtecke für Augen einzeichnen <br/> for (ex,ey,ew,eh) in eyesRects: <br/> cv2.rectangle(faceColor, (ex,ey), (<br/> ex+ew, ey+eh), (255, 0, 0), 2) <br/><br/># Fertiges Bild ausgeben <br/>cv2.imshow('Gesicht mit Augen', img) <br/><br/>cv2.waitKey(0) <br/>cv2.destroyAllWindows()
Nun folgt die Ermittlung der Übereinstimmungen der Referenzfigur mit den im Testbild gefundenen Figuren. Dies geschieht in einer einfachen for-Schleife mithilfe der OpenCV-Funktion matchShapes. Als Parameter übergeben werden die Referenzkontur, die zu untersuchende Kontur, die gewünschte Vergleichsmethode und ein eventuell erforderlicher Zusatzparameter (abhängig vom benutzten Algorithmus).Der Rückgabewert von matchShapes wird, ebenso wie die jeweilige Kontur, abgespeichert, wenn er kleiner als das bereits vorhandene Ergebnis ist.Zum Schluss wird die Kontur, die am besten zum Referenzbild passt, im Ursprungsbild mit einem grünen Rand versehen und dargestellt.Beim Ausführen des Programms sind nun drei Ausgabegrafiken zu sehen. Bild 5zeigt alle Konturen, die im Testbild ermittelt werden. Bild 6 zeigt die Kontur, die die beste Übereinstimmung mit dem Referenzbild bietet, mit grünem Rand.

Alle Konturenim Testbild(Bild 5)
Autor

Die als „Banane“gefundene Kontur(Bild 6)
Autor
Gesichter erkennen
Nun wird die Herausforderung etwas größer. Wir wollen „natürliche“ Elemente, wie zum Beispiel Gesichter oder Augen, auf einem Bild erkennen. Da nicht jeder Mensch die gleiche Gesichtsform hat oder einige Menschen eine Brille tragen, ist das nicht ganz so einfach.Hier kommen die sogenannten Cascaded Classifiers ins Spiel, die mit den OpenCV-Bibliotheken auf dem Rechner installiert werden. Diese XML-Dateien enthalten die notwendigen Daten, um Gesichter, Profile, Augen oder ein Lächeln zu erkennen. Den Algorithmus haben Paul Viola und Michael Jones im Jahr 2001 entwickelt [5]. Listing 3 zeigt die Vorgehensweise, um Gesichter auf einem Bild zu erkennen. Nach dem Import der erforderlichen Module wird der Klassifizierer für die Frontalansicht eines Gesichts instanziert (haarcascade_frontal_default.xml). Nun kann ein Bild geladen und in ein Graubild konvertiert werden. Im Beispielcode zum Artikel stehen zwei Bilder zur Verfügung: Die Datei Bild6.jpg enthält nur ein Gesicht, die Datei Bild7.jpg zeigt mehrere unterschiedlich große Gesichtsabbildungen.Listing 3: Gesichter erkennen
import cv2 <br/>import numpy as np <br/><br/># Cascaded Classifier instanzieren <br/>faceCascade = cv2.CascadeClassifier(<br/> 'haarcascade_frontalface_default.xml') <br/><br/># Bild mit (menschlichem) Gesicht laden <br/>img = cv2.imread(".\images\Bild6.jpg") <br/># Bild mit mehreren Gesichtern <br/>#img = cv2.imread(".\images\Bild7.jpg") <br/><br/># Graubild erstellen <br/>frameGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) <br/><br/># Alle Gesichter suchen <br/>faceRects = faceCascade.detectMultiScale(<br/> frameGray, scaleFactor=1.3, minNeighbors=5) <br/>print("Es wurde(n) ", faceRects.size // 4, <br/> " Gesicht(er) gefunden.") <br/><br/># Alle Gesichter mit grünen Rechtecken markieren <br/>for(x,y,w,h) in faceRects: <br/> cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, <br/> 0), 3) <br/># Ergebnisbild ausgeben <br/>cv2.imshow("Gesicht(er) suchen", img) <br/><br/>cv2.waitKey(0) <br/>cv2.destroyAllWindows()
Das konvertierte Graubild befindet sich in der Variablen frameGray und kann mit der Funktion detectMultiScale aus dem Klassifizierer faceCascade analysiert werden. Der erste Parameter übergibt das Bild frameGray an die Funktion, die beiden anderen Parameter sind optional und übergeben einen Verkleinerungsfaktor und einen minimalen Abstand, wenn mehrere Objekte gefunden werden. Als Ergebnis bekommt man ein numpy-Array faceRects, das die Eckpunkte der Rechtecke erhält, welche die gefundenen Gesichter umrahmen.Schließlich werden die gefundenen Gesichter noch im Ausgabebild eingezeichnet. Bild 7 zeigt das Ergebnis unserer Bemühungen. Da nun die Positionsdaten der Gesichter vorhanden sind, wäre es zum Beispiel sehr einfach, den Programmcode aus Listing 3 so zu erweitern, dass alle Gesichter unkenntlich gemacht werden. Das lässt sich einfach durch starkes Weichzeichnen im Gesichtsbereich realisieren.

Die erkannten Gesichterim Bild(Bild 7)
Autor
Der nächste Schritt ist ähnlich einfach. Um auch noch die Augen in einem Gesicht zu erkennen, benötigt man nur den entsprechenden Klassifizierer: haarcascade_eye.xml. Listing 4 zeigt ein vollständiges Beispielprogramm für die Erkennung von Gesichtern und Augen.Der Ablauf ist ähnlich wie im vorherigen Beispiel. Nach dem Import der Bibliotheken und der Instanzierung der beiden erforderlichen Klassifizierer (faceCascade und eyeCascade) lässt sich ein Bild laden und in Graustufen konvertieren (frameGray). Nun werden zuerst die Gesichter im Bild identifiziert. Die Funktion detectMultiScale des Klassifizierers faceCascade liefert die Rechtecke im numpy-Array faceRects. So weit ist alles wie gehabt.Nun wird in einer Schleife über alle Gesichts-Rechtecke iteriert. Zuerst erhält das Gesicht ein grünes Rechteck a. In diesem kleinen Rechteck (faceGray) wird nun ebenfalls mit detectMultiScale, aber mit dem Klassifizierer eyeCascade nach den Positionen der Augen gesucht. Für die Suche wird das Graubild benutzt. Je nach dem Ergebnis der Suche findet man kein, ein oder mehrere Rechteck(e). Das Array der Augen-Rechtecke wird nun in einer weiteren Schleife verarbeitet und im Ergebnisbild blau ausgegeben.
Bewegte Bilder aus der Webcam
In diesem Artikel wurden alle Beispiele mit statischen Bildern ausgeführt. Natürlich lassen sich mit OpenCV auch bewegte Bilder, zum Beispiel aus einer Webcam, analysieren. Hierfür muss die Kamera korrekt auf dem Rechner installiert sein, und die notwendigen Änderungen am Code sind geringfügig:import cv2
import numpy as np
# ...
# Video-Quelle definieren
capCam = cv2.VideoCapture(0)
# Ein Bild einlesen (in Schleife)
ret, frame = capCam.read()
# Zum Beispiel Gesichter erkennen
faceRects = faceCascade.detectMultiScale(frame, ...)
# ...
capCam.Release()
# ...
Nach der Definition der Bildquelle lässt sich ein Videobild mit der read-Funktion einlesen und ganz regulär wie ein statisches Bild weiterverarbeiten.Das Einlesen der Bilder aus einer Videokamera wird in der Regel in einer Endlosschleife durchgeführt. In solchen Fällen ist es natürlich besonders wichtig, dass die Bildanalyse sehr schnell erfolgt und die Ergebnisse zeitnah zur Verfügung stehen.
Zusammenfassung
In den beiden OpenCV-Artikeln konnte leider nur ein sehr kleiner Teil der Möglichkeiten dieser Bibliothek vorgestellt werden. Man kann hierzu problemlos noch zehn weitere Artikel über interessante Themen schreiben.
Gesichts- undAugen-erkennung(Bild 8)
Autor
Wir haben gesehen, wie man durch einfache Funktionsaufrufe grafische Grundelemente oder komplexe Bildelemente identifizieren kann. Die OpenCV-Funktionen kann man sehr gut und mit geringem Aufwand aus kleinen Python-Programmen aufrufen.Trotzdem ist die Bildanalyse nicht immer so einfach wie in den hier gezeigten Beispielen. Oft müssen die Bilder sehr aufwendig bearbeitet werden, damit eine sichere Erkennung der Bildelemente möglich ist. Manchmal können Bilder unscharf, zu dunkel, zu hell oder verrauscht sein, was die Bildanalyse sehr erschwert.Mittlerweile ist die Thematik Computer Vision aus Industrie, Fertigung, Fotografie, Objektüberwachung und vielen anderen Bereichen aber nicht mehr wegzudenken, und sie wird auch in der Zukunft sicherlich noch intensiv weiterentwickelt werden.
Fussnoten
- Bernd Marquardt, Bildinhalte erkennen und verarbeiten, dotnetpro 10/2020, Seite 84 ff., http://www.dotnetpro.de/A2010OpenCV
- Bernd Marquardt, Arrays mit Schleife, Mathematik mit Python, Teil 1, dotnetpro 12/2017, Seite 64 ff., http://www.dotnetpro.de/A1712Rechnen
- cornerHarris-Funktion, http://www.dotnetpro.de/SL2011OpenCV1
- Hu-Moment-Berechnung, http://www.dotnetpro.de/SL2011OpenCV2
- Cascaded Classifiers, http://www.dotnetpro.de/SL2011OpenCV3