Gesichtserkennung mit OpenCV

Nachdem wir im letzten Kapitel ein ganz simples eigenes KNN mit Python programmiert haben, möchten wir jetzt mit einer vorhandenen Bibliothek eine echte Anwendung programmieren. Wir verwenden OpenCV und werden eine Gesichtserkennung (im Sinn von face detection programmieren. (Gesichter einer Person zuordnen ist etwas komplizierter, hier spricht man von face recognition.)

Der Code dieses Kapitels basiert mit Modifikationen auf einem Artikel von Nagesh Singh Chauhan

Gesichtserkennung mit OpenCV

OpenCV liefert alles was wir benötigen um in Bildern menschliche Gesichter zu erkennen. Wir werden den «Haar»-Klassifikator verwenden, um Gesichter zu erkennen. OpenCV bietet bereits trainierte Daten in Form von xml-Dateien zur Verfügung.

Vorbereitung

  1. Projekt-Verzeichnis anlegen
  2. Bilder sammeln
    • 2-3 Bilder im Projekt-Verzeichnis abspeichern
    • mit einem oder mehreren Gesichtern, 1x ohne Gesicht
    • Dateiendung jpg
  3. Bibliotheken installieren
    • Thonny starten
    • Packages installieren: numpy, matplotlib, opencv-python

Python-Code

import cv2
import numpy as np
from matplotlib import pyplot as plt
import glob

COLOR_FACE = (255, 0, 255)    # Farbe für Rahmen ums Gesicht

image_files = glob.glob("*.jpg")   # Alle jpg-Dateien im aktuellen Verzeichnis in Liste speichern

# Für jedes Bild Gesichtserkennung machen
for file in image_files: 
    img_bgr = cv2.imread(file, cv2.IMREAD_COLOR)   # Die Bilddatei farbig einlesen 
    b,g,r = cv2.split(img_bgr)                    # Die Farbwerte auslesen (cv2 erstellt BGR-Bild)
    img_rgb = cv2.merge([r,g,b])                  # Aus den BGR-Farbwerten ein RGB-Bild machen
    img_gray = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2GRAY)    # Ein Graustufenbild für die Erkennung machen

    # Gesichts-Klassifikatoren aus Datei laden
    # (im Python-Modul sind die Standard-xml-Dateien bereits enthalten)
    face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")

    # eigentliche Gesichtserkennung ausführen
    faces = face_cascade.detectMultiScale(img_gray, scaleFactor=1.2, minNeighbors=5)

    print("Anzahl erkannte Gesichter:", len(faces))   # Anzahl erkannte Gesichter ausgeben

    # Erkannte Gesichter durchgehen.
    # Die erkannten Gesichter werden durch ein umrahmendes Redchteck gegebn:
    # (x, y, w, h) stellen Koordinaten, Breite und Höhe des Rechtecks dar
    for (x, y, w, h) in faces:
        # das Gesicht durch ein farbiges Rechteck im Bild markieren
        cv2.rectangle(img_rgb, (x, y), (x+w, y+h), COLOR_FACE, 2)

    plt.axis('off')         # Diagramm-Achsen ausblenden
    plt.imshow(img_rgb)     # Dem Diagramm das Bild hinzufügen
    plt.title(file)         # Titel des Diagramms setzen
    plt.show()              # Diagramm anzeigen

exit()
  1. Lies den obenstehenden Python-Code und alle Kommentare durch.
  2. Kopiere den Code in dein Projektverzeichnis und führe ihn aus.
  3. Versuche den Code zu optimieren, indem du mit den Werten scaleFactor und minNeighbors in der Methode detectMultiScale spielst. Versuche zu verstehen was diese Parameter machen. Lies dazu auch die beiden verlinkten stackoverflow-Beiträge durch.

Augen erkennen

Für erkannte Gesichter können wir nun auch die Augen erkennen. Das Prinzip ist das selbe wie bei der Gesichtserkennung. Wir gehen wie folgt vor:

  1. Wir erstellen einen neuen Klassifikator für die Augen. Die Trainingsdaten finden wir in der Datei haarcascade_eye.xml.
  2. Für jedes erkannte Gesicht erstellen wir ein neues Bild, welches nur das Gesicht beinhaltet.
  3. Auf diesem Bild führen wir die Augenerkennung durch.
  4. Wir markieren im Gesamtbild die erkannten Augen durch einen farbigen Rahmen.

Die in OpenCV geladenen Bilder sind zweidimensionale Listen. Wir können mit der Range-Auswahl von Python ein Rechteckiges Bild aus einem grösseren Bild ausschneiden.

Das folgende Beispiel schneidet im Bild img ein Rechteck an den Koordinaten (x,y) mit einer Breite w und einer Höhe h aus und speichert das ausgeschnittene Bild in einem neuen Array face.

img = cv2.imread("testbild.jpg", cv2.IMREAD_COLOR)
face = img[y:y+h, x:x+w]

Speichere deine Python-Datei unter einem neuen Dateinamen ab und füge der Gesichtserkennung eine Augenerkennung hinzu. Gehe dabei gemäss den 4 oben besprochenen Schritten vor. Versuche wiederum die Erkennung zu optimieren.

Füge den Augen Make-Up hinzu, indem du um die Augen herum etwas Farbe aufträgst. OpenCV-Zeichenbefehle

Baue eine automatische Zensur. Du kannst eine oder beide Zensurvarianten umsetzen:

Variante A
Finde alle Gesichter und «verpixele» sie oder wende einen «Weichzeichner» an. cv2.blur()
Variante B
Verbinde die beiden Augen eines Gesichtes mit einem schwarzen Balken, also einem sogenannten Zensurbalken.
Variante A
Finde Augen und spiegle diese horizontal. cv2.flip()
Variante B
Finde ein Gesicht mit zwei Augen. Vertausche die beiden Augen!

andere Dinge erkennen

Im Repo von OpenCV finden wir weitere Trainingsdaten für den Haar-Klassifikator: https://github.com/opencv/opencv/tree/master/data/haarcascades. Einige Mögliche Anwendungsbeispiele:

  • haarcascade_fullbody.xml – Fussgänger erkennen für ein selbstfahrendes Auto
  • haarcascade_smile.xml – Bei Gesichtern ein Lächeln erkennen, z.b. für eine Kamera die erst auslöst wenn alle Personen lächeln.
  • haarcascade_profileface.xml – hinzufügen zu unserer Gesichtserkennung um auch Personen von der Seite her zu erkennen.

Wähle einen der im Repo verfügbaren Haar-Klassifikator aus und versuche damit eine Anwendung zu erstellen:

  • passende Bilder sammeln
  • das Python-Skript mit den neuen Trainingsdaten ausstatten
  • Die Objekt-Erkennung testen und optimieren
  • Etwas «sinnvolles» mit den erkannten Objekten anstellen