Dieses Tutorial zeigt Ihnen, wie Sie mit OpenCV, Python und ImageMagick animierte GIFs erstellen. Kombinieren Sie dann diese Methoden, um einen Meme-Generator mit OpenCV zu erstellen!
Wir alle müssen von Zeit zu Zeit lachen. Und vielleicht ist der beste Weg, um Lulza zu finden, Meme. Einige meiner Favoriten:
- Kermit der Frosch: "Aber es geht mich nichts an"
- Mürrische Katze
- Epic Fail
- Guter Kerl Greg
Aber für mich persönlich kann keines dieser Memes mit dem Mem "Deal With It" ("Deal with it" oder "Understand it yourself") verglichen werden, dessen Beispiel am Anfang des Artikels angegeben ist.Es wird normalerweise in folgenden Fällen verwendet:
- Als Antwort oder Einspruch gegen jemanden, der etwas, das Sie getan / gesagt haben, nicht gutheißt („Beschäftige dich damit“)
- Setzen Sie Ihre Brille auf, als würden Sie gehen und lassen Sie die Person mit dem Problem allein („Verstehe es selbst“)
Vor einigen Jahren habe ich im Blog des Autors einen lustigen Artikel gelesen, in dem ich mich nicht erinnern kann, wie man solche Memes mit Computer Vision generiert. Letzte Woche konnte ich diesen Leitfaden nirgendwo finden. Als Blogger, Computer Vision-Experte und Experte für Memes habe ich beschlossen, selbst ein Tutorial zu schreiben! (Übrigens, wenn Sie versehentlich die Originalquelle kennen, lassen Sie es mich bitte wissen, damit ich dem Autor danken kann.
UPD: Ich habe gerade den Originalartikel aus Kirk Kaisers Blog
MakeArtWithPython gefunden. )
Durch die Entwicklung eines Meme-Generators auf OpenCV lernen wir eine Reihe wertvoller praktischer Fähigkeiten, darunter:
- Gesichtserkennung mit Deep-Learning-Techniken
- Verwenden der dlib-Bibliothek zum Erkennen von Gesichtspunkten und zum Extrahieren von Augenpartien
- Wie berechnet man den Drehwinkel zwischen den Augen basierend auf den empfangenen Informationen?
- Und schließlich, wie man mit OpenCV animierte GIFs generiert (mit ein wenig Hilfe von ImageMagick)
Dieser Leitfaden soll Spaß machen und unterhaltsam sein - und gleichzeitig wertvolle Computer Vision-Programmierkenntnisse vermitteln, die in der realen Welt nützlich sind.
Erstellen von GIFs mit OpenCV
Im ersten Teil des Handbuchs werden wir die notwendigen Bedingungen und Abhängigkeiten für dieses Projekt diskutieren, einschließlich der richtigen Konfiguration der Entwicklungsumgebung.
Betrachten Sie dann die Projekt- / Katalogstruktur für unseren OpenCV-GIF-Generator.
Sobald wir die Projektstruktur verstanden haben, werden wir Folgendes berücksichtigen: 1) unsere Konfigurationsdatei; 2) das Python-Skript, das für die Erstellung von GIFs mit OpenCV verantwortlich ist.
Schließlich werden wir die Ergebnisse des Programms auf dem beliebten Mem "Deal With It" auswerten.
Voraussetzungen und Abhängigkeiten
Abb. 1. Wir werden OpenCV, dlib und ImageMagick verwenden, um GIFs zu erstellenOpencv und dlib
OpenCV wird benötigt, um die Flächen im Rahmen und die grundlegende Bildverarbeitung zu bestimmen. Befolgen Sie eine meiner
OpenCV-Installationsanleitungen, wenn OpenCV nicht auf dem System installiert ist.
Wir verwenden Dlib, um Gesichtsmarkierungen zu erkennen, wodurch wir zwei Augen im Gesicht finden und eine Sonnenbrille aufsetzen können.
Mit dieser Anleitung können Sie
dlib installieren .
Imagemagick
Wenn Sie mit
ImageMagick nicht vertraut sind, dann vergebens. Es ist ein plattformübergreifendes Befehlszeilentool mit vielen Bildverarbeitungsfunktionen.
Möchten Sie PNG / JPG mit einem Befehl in PDF konvertieren? Kein Problem.
Es gibt mehrere Bilder, aus denen Sie ein mehrseitiges PDF erstellen müssen. Leicht.
Müssen Sie Polygone, Linien und andere Formen zeichnen? Und es ist möglich.
Wie wäre es mit einer Batch-Farbkorrektur oder einer Größenänderung aller Bilder mit einem Befehl? Dazu müssen Sie in Python für OpenCV nicht einige Zeilen schreiben.
ImageMagick generiert auch GIFs aus jedem Bild.
Um ImageMagick unter Ubuntu (oder Raspbian) zu installieren, verwenden Sie einfach apt:
Erstellen von GIFs mit OpenCVShell
$ sudo apt-get install imagemagick
Unter macOS können Sie HomeBrew verwenden:
$ brew install imagemagick
Imutils
In den meisten Artikeln, Kursen und Büchern verwende ich mein praktisches Bildverarbeitungspaket von
imutils . Es wird auf einem System oder einer virtuellen Umgebung mit pip installiert:
$ pip install imutils
Projektstruktur
Abb. 2. Die Projektstruktur enthält zwei Verzeichnisse, eine Konfigurationsdatei und ein Python-SkriptIn unserem Projekt gibt es zwei Kataloge:
images/
: Beispiele für Eingabebilder, für die wir ein animiertes GIF erstellen möchten. Ich habe einige Bilder bei mir gefunden, kann aber gerne eigene hinzufügen.assets/
: Dieser Ordner enthält unseren Gesichtsdetektor, Gesichtsmarkierungsdetektor und alle Bilder + zugehörigen Masken. Mit diesen Assets setzen wir Punkte und Text auf die Originalbilder aus dem ersten Ordner.
Aufgrund der großen Anzahl konfigurierbarer Parameter habe ich beschlossen, eine JSON-Konfigurationsdatei zu erstellen, die: 1) die Bearbeitung von Parametern erleichtert; 2) erfordert weniger Befehlszeilenargumente. Alle für dieses Projekt erforderlichen Konfigurationsparameter sind in
config.json
.
Betrachten Sie den Inhalt von
config.json
und
create_gif.py
.
Hinweis Per .: Projektcode und 17-seitiges Handbuch zu Computer Vision, maschinellem Lernen und OpenCV werden nach der Registrierung herausgegeben (Spiegel: Quellcode , Handbuch ).GIF-Generierung mit OpenCV
Fahren wir also fort und erstellen unseren OpenCV-GIF-Generator!
Inhalt der JSON-Konfigurationsdatei
Beginnen wir mit der JSON-Konfigurationsdatei und fahren dann mit dem Python-Skript fort.
Öffnen Sie eine neue Datei
config.json
und fügen Sie die folgenden Schlüssel / Wert-Paare ein:
Erstellen von GIFs mit OpenCVPython
{ "face_detector_prototxt": "assets/deploy.prototxt", "face_detector_weights": "assets/res10_300x300_ssd_iter_140000.caffemodel", "landmark_predictor": "assets/shape_predictor_68_face_landmarks.dat",
Dies sind
OpenCV-Gesichtsdetektor- Modelldateien
in Deep Learning .
Die letzte Zeile ist der Pfad zum dlib face Predictor.
Und jetzt haben wir einige Pfade zu den Bilddateien:
"sunglasses": "assets/sunglasses.png", "sunglasses_mask": "assets/sunglasses_mask.png", "deal_with_it": "assets/deal_with_it.png", "deal_with_it_mask": "assets/deal_with_it_mask.png",
Dies sind die Pfade zu unseren Sonnenbrillen, Texten und passenden Masken, die unten gezeigt werden.
Erstens eine schicke Sonnenbrille und eine Maske:
Abb. 3. Sie mögen keine Brille mit Pixeln? Ertrage es einfachAbb. 4. Sie verstehen nicht, warum Sie eine Maske für Sonnenbrillen benötigen? Lassen Sie es sich einfach gefallen - oder lesen Sie den Rest des Artikels, um die Antwort zu erhalten.Und jetzt lautet unser Text "DEAL WITH IT" und die Maske:
Abb. 5. Hassen Sie Helvetica Neue Condensed? Beschäftige dich damitAbb. 6: Mit dieser Maske können Sie einen Rahmen um den Text zeichnen. Oh, vielleicht willst du nicht, willst du eine Grenze? Nun, ertrage esMasken werden benötigt, um das entsprechende Bild auf dem Foto zu überlagern. Wir werden uns später darum kümmern.
Stellen Sie nun einige Parameter für den Meme-Generator ein:
"min_confidence": 0.5, "steps": 20, "delay": 5, "final_delay": 250, "loop": 0, "temp_dir": "temp" }
Hier sind die Definitionen für jeden der Parameter:
min_confidence
: minimal erforderliche Gesichtserkennungswahrscheinlichkeit.steps
: Anzahl der Frames in der endgültigen Animation. Jeder „Schritt“ bewegt die Sonnenbrille vom oberen Rand zum Ziel (dh zu den Augen).delay
: Verzögerung zwischen Frames in Hundertstelsekunden.final_delay
: Verzögerung des letzten Frames in Hundertstelsekunden (nützlich in diesem Zusammenhang, da der Text länger als der Rest der Frames angezeigt werden soll).loop
: Ein Nullwert gibt an, dass sich das GIF für immer wiederholt. Andernfalls geben Sie eine positive Ganzzahl für die Anzahl der Wiederholungen der Animation an.temp_dir
: Das temporäre Verzeichnis, in dem jeder der Frames gespeichert wird, bevor das endgültige GIF erstellt wird.
Memes, GIFs und OpenCV
Wir haben die JSON-Konfigurationsdatei erstellt und gehen nun zum eigentlichen Code über.
Öffnen Sie eine neue Datei, nennen Sie sie
create_gif.py
und fügen Sie den folgenden Code ein:
Hier importieren wir die notwendigen Pakete. Insbesondere werden wir imutils, dlib und OpenCV verwenden. Informationen zum Installieren dieser Abhängigkeiten finden Sie oben im Abschnitt Voraussetzungen und Abhängigkeiten.
Jetzt verfügt das Skript über die erforderlichen Pakete. Definieren
overlay_image
Funktion
overlay_image
:
def overlay_image(bg, fg, fgMask, coords):
Die Funktion
overlay_image
legt einen Vordergrund (
fg
) oben auf dem Hintergrundbild (
bg
) an den Koordinatenkoordinaten
( Koordinaten
(x, y) ) fest und realisiert Alpha-Transparenz über der Vordergrundmaske
fgMask
.
Lesen Sie
dieses Handbuch , um sich mit den Grundlagen von OpenCV vertraut zu machen, z. B. mit Masken.
Führen Sie eine Alpha-Mischung durch, um den Mischvorgang abzuschließen:
def alpha_blend(fg, bg, alpha):
Diese Alpha-Blending-Implementierung ist auch
im LearnOpenCV-Blog verfügbar.
Im Wesentlichen werden wir den Vordergrund, den Hintergrund und den Alphakanal in Gleitkommazahlen im Bereich
[0, 1] konvertieren. Dann führen wir eine Alpha-Überblendung durch, fügen den Vordergrund und den Hintergrund hinzu, um das Ergebnis zu erhalten, dass wir zur aufrufenden Funktion zurückkehren.
Wir werden auch eine Hilfsfunktion erstellen, mit der GIFs aus einer Reihe von Bildpfaden mit ImageMagick und dem Befehl
convert
generiert werden können:
def create_gif(inputPath, outputPath, delay, finalDelay, loop):
Die Funktion
create_gif
nimmt eine Reihe von Bildern auf und sammelt sie mit einer bestimmten Verzögerung zwischen Frames und Loops in GIF-Animationen. ImageMagick verarbeitet all dies - wir verpacken den Befehl
convert
einfach in eine Funktion, die verschiedene Parameter dynamisch verarbeitet.
Informationen zu den verfügbaren
convert
finden
Sie in der Dokumentation . Dort sehen Sie, wie viele Funktionen dieses Team hat!
Speziell in dieser Funktion haben wir:
- Nehmen Sie
imagePaths
. - Wählen Sie den Pfad des letzten Bildes, für das eine separate Verzögerung gilt.
imagePaths
zu, um den letzten Pfad auszuschließen.- Wir stellen einen Befehl mit Befehlszeilenargumenten zusammen und weisen das Betriebssystem an, ihn zu
convert
, um GIF-Animationen zu erstellen.
Weisen Sie dem Skript eigene Befehlszeilenargumente zu:
Wir haben drei Befehlszeilenargumente, die zur Laufzeit verarbeitet werden:
--config
: Pfad zur JSON-Konfigurationsdatei. Wir haben die Konfigurationsdatei im vorherigen Abschnitt überprüft.--image
: Pfad zu dem Eingabebild, --image
dessen die Animation erstellt wird (d. h. Erkennen eines Gesichts, Hinzufügen einer Sonnenbrille und dann Text).--output
: Pfad zum resultierenden GIF.
Jedes dieser Argumente ist erforderlich, wenn das Skript in der Befehlszeile / im Terminal ausgeführt wird.
Laden Sie die Konfigurationsdatei sowie die Brille und die entsprechende Maske herunter:
Hier laden wir die Konfigurationsdatei (die möglicherweise in Zukunft als Python-Wörterbuch verfügbar sein wird). Laden Sie dann die Sonnenbrille und die Maske.
Wenn etwas vom vorherigen Skript übrig bleibt, löschen Sie das temporäre Verzeichnis und erstellen Sie das leere temporäre Verzeichnis neu. Der temporäre Ordner enthält jeden einzelnen Frame aus der GIF-Animation.
Laden Sie nun den
OpenCV Deep Learning Face Detector in den Speicher:
Rufen Sie dazu
cv2.dnn.readNetFromCaffe
. Das
dnn
Modul ist nur in OpenCV 3.3 oder höher verfügbar. Ein Gesichtsdetektor erkennt das Vorhandensein von Gesichtern im Bild:
Abb. 7. Betrieb des Gesichtsdetektors mit OpenCV DNNLaden Sie dann den
dlib face Landmark Predictor . Damit können Sie einzelne Strukturen lokalisieren: Augen, Augenbrauen, Nase, Mund und Kinnlinie:
Abb. 8. Die von dlib entdeckten Orientierungspunkte überlagern mein GesichtSpäter in diesem Skript extrahieren wir nur die Augenpartie.
Lassen Sie uns das Gesicht finden:
In diesem Block machen wir folgendes:
- Laden Sie das Originalbild herunter.
- Wir konstruieren einen
blob
, der an den Gesichtsdetektor eines neuronalen Netzwerks gesendet wird. Dieser Artikel beschreibt, wie blobFromImage
von OpenCV funktioniert. - Führen Sie die Gesichtserkennung durch.
- Wir finden die Person mit dem höchsten Wahrscheinlichkeitswert und vergleichen sie mit der minimal akzeptablen Wahrscheinlichkeitsschwelle. Wenn die Kriterien nicht erfüllt sind, beenden Sie einfach das Skript. Andernfalls fahren Sie fort.
Jetzt werden wir das Gesicht extrahieren und die Orientierungspunkte berechnen:
Um das Gesicht zu extrahieren und Gesichtspunkte zu finden, gehen wir wie folgt vor:
- Wir extrahieren die Koordinaten des Begrenzungsrahmens um das Gesicht.
- Erstellen Sie ein
rectangle
in dlib und wenden Sie die Gesichtslokalisierung an. - Wir
leftEyePts
die (x, y) -Koordinaten von leftEyePts
bzw. rightEyePts
ab.
Anhand der Koordinaten der Augen können Sie berechnen, wo und wie Sie eine Sonnenbrille platzieren:
Zuerst berechnen wir die Mitte jedes Auges, dann den Winkel zwischen den Schwerpunkten. Der gleiche Vorgang wird mit horizontaler
Ausrichtung der Fläche im Rahmen ausgeführt .
Jetzt können Sie die Brille drehen und ihre Größe ändern. Beachten Sie, dass wir
die Funktion rotate_bound verwenden und nicht nur
rotate
, damit OpenCV keine Teile schneidet, die nach der affinen Konvertierung nicht sichtbar sind.
Die gleichen Vorgänge, die auf die Brille angewendet wurden, gelten auch für die Maske. Aber zuerst müssen Sie es in Graustufen konvertieren und binärisieren, da Masken immer binär sind. Dann drehen wir die Maske und ändern ihre Größe auf die gleiche Weise wie bei einer Brille.
Hinweis: Beachten Sie, dass beim Ändern der Maskengröße die Interpolation für die nächsten benachbarten Punkte verwendet wird, da die Maske nur zwei Werte haben sollte (0 und 255). Andere Interpolationsmethoden sind ästhetischer, aber für Masken nicht geeignet. Hier erhalten Sie zusätzliche Informationen zur Interpolation an den nächstgelegenen Nachbarpunkten.Die verbleibenden drei Codeblöcke erstellen Frames für die GIF-Animation:
Brillen fallen von oben auf das Bild. Auf jedem Bild werden sie näher am Gesicht angezeigt, bis sie ihre Augen bedecken. Mit der Variablen
"steps"
in der JSON-Konfigurationsdatei generieren wir y-Koordinaten für jeden Frame. Dazu verwenden wir ohne großen Aufwand die
linspace
Funktion von NumPy.
Die Linien mit einer leichten Verschiebung nach links und oben mögen etwas seltsam erscheinen, aber sie werden benötigt, um sicherzustellen, dass die Brille das gesamte Auge bedeckt und sich nicht nur bis zu dem Punkt bewegt, an dem sich die Mitte des Auges befindet. Ich habe empirisch Prozentsätze bestimmt, um den Versatz entlang jeder Achse zu berechnen. Die nächste Zeile stellt keine negativen Werte sicher.
Mit der Funktion
overlay_image
generieren
overlay_image
den endgültigen
output
.
Wenden Sie nun den Text "DEAL WITH IT" mit einer anderen Maske an:
Im letzten Schritt setzen wir den Text durch, der in Wirklichkeit ein anderes Bild ist.
Ich habe mich für ein Bild entschieden, da die Renderfunktionen von OpenCV-Schriftarten sehr begrenzt sind. Außerdem wollte ich dem Text einen Schatten und einen Rahmen hinzufügen, was OpenCV wiederum nicht weiß, wie.
Im Rest dieses Codes laden wir sowohl das Bild als auch die Maske und führen dann eine Alpha-Überblendung durch, um das Endergebnis zu generieren.
Es bleibt nur, jeden Frame mit der anschließenden Erstellung der GIF-Animation auf der Festplatte zu speichern:
Wir schreiben das Ergebnis auf die Festplatte. Nachdem wir alle Frames generiert haben, rufen wir die Funktion
create_gif
auf, um die GIF-Animationsdatei zu erstellen. Denken Sie daran, dass dies eine Shell ist, die Parameter an das ImageMagick-
convert
übergibt.
Löschen Sie abschließend das temporäre Ausgabeverzeichnis und einzelne Bilddateien.
Ergebnisse
Nun zum lustigen Teil: Mal sehen, was unser Meme-Generator erstellt hat!
Stellen Sie sicher, dass Sie
den Quellcode, Beispielbilder und Deep-Learning-Modelle
herunterladen . Öffnen Sie dann ein Terminal und führen Sie den folgenden Befehl aus:
$ python create_gif.py --config config.json --image images/adrian.jpg \ --output adrian_out.gif [INFO] loading models... [INFO] computing object detections... [INFO] creating GIF... [INFO] cleaning up...
Abbildung 9. Mit OpenCV und ImageMagick mit diesem Python-Skript generierte GIF-AnimationHier sehen Sie das mit OpenCV und ImageMagick erstellte GIF. Die folgenden Aktionen werden darauf ausgeführt:
- Richtige Erkennung meines Gesichts.
- Lokalisierung der Augen und Berechnung ihrer Zentren.
- Brille fällt richtig auf das Gesicht.
Die Leser meines Blogs wissen, dass ich ein großer Nerd im Jurassic Park bin und erwähnen dies oft in meinen Büchern, Kursen und Studienführern.
Magst du
Jurassic Park nicht ?
Ok, hier ist meine Antwort:
$ python create_gif.py --config config.json --image images/adrian_jp.jpg \ --output adrian_jp_out.gif [INFO] loading models... [INFO] computing object detections... [INFO] creating GIF... [INFO] cleaning up...
Abb. 10. OpenCV GIF-Animation basierend auf einem Foto aus der jüngsten Vorführung von Jurassic World 2Hier bin ich bei der Show "Jurassic World: 2" in einem thematischen T-Shirt, mit einem Glas Licht und einem Sammelbuch.
Lustige Geschichte:
Vor fünf oder sechs Jahren besuchten meine Frau und ich den Themenpark Epcot Center in Disney World, Florida.
Wir beschlossen, einen Ausflug zu machen, um den harten Wintern in Connecticut zu entfliehen, und brauchten dringend Sonnenlicht.
Leider hat es in Florida die ganze Zeit geregnet und die Temperatur hat 10 ° C kaum überschritten.
In der Nähe der kanadischen Gärten machte Trisha ein Foto von mir: Sie sagt, ich sehe aus wie ein Vampir mit blasser Haut, dunkler Kleidung und Kapuze vor dem Hintergrund der üppigen Gärten dahinter:
$ python create_gif.py --config config.json --image images/vampire.jpg \ --output vampire_out.gif [INFO] loading models... [INFO] computing object detections... [INFO] creating GIF... [INFO] cleaning up...
Abb. 11. Mit OpenCV und Python können Sie dieses Mem oder ein anderes animiertes GIF erstellenAm selben Abend veröffentlichte Trisha ein Foto in sozialen Netzwerken - ich musste es ertragen.
Diejenigen unter Ihnen, die an der PyImageConf 2018 teilgenommen haben (
lesen Sie die Rezension ), wissen, dass ich immer offen für Witze bin. Hier ist ein Beispiel:
Frage: Warum überquert der Hahn die Straße? $ python create_gif.py --config config.json --image images/rooster.jpg \ --output rooster_out.gif [INFO] loading models... [INFO] computing object detections... [INFO] creating GIF... [INFO] cleaning up...
Abb. 12. , OpenCV: — ., .
, .
:
$ python create_gif.py --config config.json --image images/pupper.jpg \ --output pupper_out.gif [INFO] loading models... [INFO] computing object detections... [INFO] creating GIF... [INFO] cleaning up...
Abb. 13. . ? « »!, ? .
AttributeError?
Keine Sorge!
:
$ python create_gif.py --config config.json --image images/adrian.jpg \ --output adrian_out.gif ... Traceback (most recent call last): File "create_gif.py", line 142, in <module> (lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"] AttributeError: module 'imutils.face_utils' has no attribute 'FACIAL_LANDMARKS_IDXS'
… imutils:
$ pip install --upgrade imutils Collecting imutils ... Successfully installed imutils-0.5.1
Warum?
imutils.face_utils
68- , dlib ( ).
5- , imutils. imutils ( ).
Zusammenfassung
, GIF OpenCV.
, OpenCV GIF- “Deal With It”, ( ), .
:
, GIF OpenCV ImageMagick.
, !
, , .
, , . ;)