Schätzung der Kopforientierung mit Python und OpenCV + dlib

Kopfrichtungsschätzung?

Head Pose Estimation in Englisch. Es ist ein Algorithmus, der die Richtung, in die das Gesicht zeigt, und die Neigung des Kopfes aus den eingegebenen Bildinformationen und Gesichtsmerkmalsdaten schätzt. In letzter Zeit wurde es häufig für die Entwicklung von Vtuber verwendet.

Methode zur Schätzung der Kopfrichtung

Qiita hat bereits mehrere Methoden zur Schätzung der Kopfrichtung eingeführt. Dies ist in Qiitas Artikel sehr gut organisiert. Untersuchung der Schätzung der Gesichtsorientierung

Ich denke, dies ist der Artikel, auf den Sie sich beziehen, über die Kopfschätzungsmethode mit Python und OpenCV + dlib. Head Pose Estimation using OpenCV and Dlib

Die Algorithmen zur Schätzung der Gesichtsorientierung werden im Abschnitt Funktionsweise von Posenschätzungsalgorithmen auf dieser Seite ausführlich beschrieben.

Ein Beispiel für ein Programm

Vorerst werde ich das im Artikel vorgestellte Programm schreiben. Sie können die Datendatei zur Gesichtserkennung hier herunterladen. [dlib.net] 68 Punkte gelernte Daten für die Gesichtserkennung [DL]

Modul laden

HeadPoseEstimation.py


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import cv2 #OpenCV:Bildverarbeitungsbibliothek
import dlib #Bibliothek für maschinelles Lernen
import imutils #OpenCV-Unterstützung
from imutils import face_utils
import numpy as np

Wir importieren OpenCV für die Bildverarbeitung, dlib für die Bilderkennung und Imutils als Hilfsmittel für die Anzeige auf dem Bildschirm.

Kamera- und Gesichtsdetektoreinstellungen

HeadPoseEstimation.py


DEVICE_ID = 0 #ID 0 der verwendeten Kamera ist eine Standard-Webkamera
capture = cv2.VideoCapture(DEVICE_ID)#Von dlib trainierte Daten lesen
predictor_path = ",,,/shape_predictor_68_face_landmarks.dat"
#Kopieren Sie den Pfad der gelernten Datendatei

detector = dlib.get_frontal_face_detector() #Gesichtsdetektor anrufen. Nur das Gesicht wird erkannt.
predictor = dlib.shape_predictor(predictor_path) #Geben Sie Orientierungspunkte wie Augen und Nase aus dem Gesicht aus

Detaillierte dlib-Funktionen finden Sie hier. dlib documentation

Inhalt der Kopfrichtungsschätzung

Es erfasst jeweils ein Bild von der Kamera und verarbeitet es.

HeadPoseEstimation.py


while(True): #Holen Sie sich kontinuierlich Bilder von der Kamera
    ret, frame = capture.read() #Nehmen Sie von der Kamera auf und fügen Sie ein Bild mit Bilddaten in das Bild ein
    
    frame = imutils.resize(frame, width=1000) #Passen Sie die Anzeigegröße des Rahmenbilds an
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #In Graustufen konvertieren
    rects = detector(gray, 0) #Gesicht von Grau erkennen
    image_points = None
     
    for rect in rects:
        shape = predictor(gray, rect)
        shape = face_utils.shape_to_np(shape)
        
        for (x, y) in shape: #Zeichnen Sie 68 Orientierungspunkte auf dem gesamten Gesicht
            cv2.circle(frame, (x, y), 1, (255, 255, 255), -1)

        image_points = np.array([
                tuple(shape[30]),#Nasenspitze
                tuple(shape[21]),
                tuple(shape[22]),
                tuple(shape[39]),
                tuple(shape[42]),
                tuple(shape[31]),
                tuple(shape[35]),
                tuple(shape[48]),
                tuple(shape[54]),
                tuple(shape[57]),
                tuple(shape[8]),
                ],dtype='double')
    
    if len(rects) > 0:
        cv2.FONT_HERSHEY_PLAIN, 0.7, (0, 0, 255), 2)
        model_points = np.array([
                (0.0,0.0,0.0), # 30
                (-30.0,-125.0,-30.0), # 21
                (30.0,-125.0,-30.0), # 22
                (-60.0,-70.0,-60.0), # 39
                (60.0,-70.0,-60.0), # 42
                (-40.0,40.0,-50.0), # 31
                (40.0,40.0,-50.0), # 35
                (-70.0,130.0,-100.0), # 48
                (70.0,130.0,-100.0), # 54
                (0.0,158.0,-10.0), # 57
                (0.0,250.0,-50.0) # 8
                ])

        size = frame.shape

        focal_length = size[1]
        center = (size[1] // 2, size[0] // 2) #Mittelkoordinaten des Gesichts

        camera_matrix = np.array([
            [focal_length, 0, center[0]],
            [0, focal_length, center[1]],
            [0, 0, 1]
        ], dtype='double')

        dist_coeffs = np.zeros((4, 1))

        (success, rotation_vector, translation_vector) = cv2.solvePnP(model_points, image_points, camera_matrix,
                                                                      dist_coeffs, flags=cv2.SOLVEPNP_ITERATIVE)
        #Rotierende Matrix und Jacobian
        (rotation_matrix, jacobian) = cv2.Rodrigues(rotation_vector)
        mat = np.hstack((rotation_matrix, translation_vector))

        #yaw,pitch,Rolle herausnehmen
        (_, _, _, _, _, _, eulerAngles) = cv2.decomposeProjectionMatrix(mat)
        yaw = eulerAngles[1]
        pitch = eulerAngles[0]
        roll = eulerAngles[2]
        
        print("yaw",int(yaw),"pitch",int(pitch),"roll",int(roll))#

        cv2.putText(frame, 'yaw : ' + str(int(yaw)), (20, 10), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 255), 2)
        cv2.putText(frame, 'pitch : ' + str(int(pitch)), (20, 25), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 255), 2)
        cv2.putText(frame, 'roll : ' + str(int(roll)), (20, 40), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 255), 2)

        (nose_end_point2D, _) = cv2.projectPoints(np.array([(0.0, 0.0, 500.0)]), rotation_vector,
                                                         translation_vector, camera_matrix, dist_coeffs)
        #/Anzeige des Gesichtsrichtungsvektors
        for p in image_points:
            cv2.drawMarker(frame, (int(p[0]), int(p[1])),  (0.0, 1.409845, 255),markerType=cv2.MARKER_CROSS, thickness=1)

        p1 = (int(image_points[0][0]), int(image_points[0][1]))
        p2 = (int(nose_end_point2D[0][0][0]), int(nose_end_point2D[0][0][1]))

        cv2.arrowedLine(frame, p1, p2, (255, 0, 0), 2)
    
    cv2.imshow('frame',frame) #Bild anzeigen
    if cv2.waitKey(1) & 0xFF == ord('q'): #Drücken Sie q, um zu brechen und zu beenden
        break


capture.release() #Beenden Sie die Videoaufnahme
cv2.destroyAllWindows() #Fenster schließen

Wenn es richtig funktioniert, wird es so sein. スクリーンショット 2019-11-24 23.32.58.png

Parametererklärungen und Hinweise

yaw,roll,pitch Die Kopfhaltungsparameter Gieren, Rollen, Neigen sind wie folgt. (Wie ein Flugzeug) IMG_0240.jpg

Gesichtsmerkmale verwendet werden

Die Position der diesmal definierten image_points finden Sie hier. Der diesmal verwendete Punkt ist ・ In den Augenbrauen (22,23) ・ In den Augen (40,43) ・ Nasenspitze (31) ・ Beide Seiten der Nase (32,36) ・ Beide Außenseiten des Mundes (49,55) ・ Unter den Lippen (58) ・ Chin (9) Es ist 11 Punkte von. Die Kopfrichtung kann algorithmisch mit 5 Punkten geschätzt werden, aber als ich es versuchte, als die Punktzahl klein war, drehte sich die Richtung des Vektors an der Nasenspitze um, also erhöhte ich die Punktzahl. (Liegt es daran, dass die trainierten Daten auf Westlern basieren ...) Facial landmarks with dlib, OpenCV, and Python facial_landmarks_68markup-1024x825.jpg Je häufiger Sie die Punkte auf der Außenseite des Gesichts verwenden, desto besser ist die Genauigkeit. Wenn jedoch die Augenbrauen usw. bei seitlicher Ausrichtung abgeschnitten werden, führt dies zu einer Fehleinschätzung des Merkmalsbetrags. Versuchen Sie daher, die Punkte in der Mitte des Gesichts so weit wie möglich zu verwenden. <img width = "638" alt = "IMG_18D234CF6CC9-1.jpeg " src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543519/9cc12aa3-958f-0940" -9737-84a999dfacbf.jpeg ">

Und das Problem ist model_points, das heißt, was soll ich mit den Positionskoordinaten der Teile meines Gesichts tun, aber ich habe es mit Gewalt aus dem folgenden Programm definiert. Die (x, y) -Koordinatendaten des Gesichts mit der Nasenspitze als Ursprung werden im Bild angezeigt. Stellen Sie daher die Kamera so gerade wie möglich, erweitern Sie Ihre Haltung und lesen Sie sie mit einem Geist. Ich vermute über die z-Koordinate. Finden Sie den Abstand zwischen Ihrer Nasenspitze und dem Bereich zwischen Ihren Augen und wenden Sie ihn auf die Höhe Ihrer Nase an. Halte durch!

HPEcal.py


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import cv2 #OpenCV:Bildverarbeitungsbibliothek
import dlib #Bibliothek für maschinelles Lernen
import imutils #OpenCV-Unterstützung
from imutils import face_utils
import numpy as np


#Ruft ein VideoCapture-Objekt ab
DEVICE_ID = 0 #ID 0 ist eine Standard-Webkamera
capture = cv2.VideoCapture(DEVICE_ID)#Von dlib trainierte Daten lesen
predictor_path = "/shape_predictor_68_face_landmarks.dat"

print("[INFO] loading facial landmark predictor...")
detector = dlib.get_frontal_face_detector() #Gesichtsdetektor anrufen. Nur das Gesicht wird erkannt.
predictor = dlib.shape_predictor(predictor_path) #Geben Sie Orientierungspunkte wie Augen und Nase aus dem Gesicht aus

while(True): #Holen Sie sich kontinuierlich Bilder von der Kamera
    ret, frame = capture.read() #Nehmen Sie von der Kamera auf und fügen Sie ein Bild mit Bilddaten in das Bild ein
    
    frame = imutils.resize(frame, width=2000) #Passen Sie die Anzeigegröße des Rahmenbilds an
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #In Graustufen konvertieren
    rects = detector(gray, 0) #Gesicht von Grau erkennen
    image_points = None
     
    for rect in rects:
        shape = predictor(gray, rect)
        shape = face_utils.shape_to_np(shape)
        #print(shape[30])#Nasenkoordinaten
        cal = shape-shape[30]
        print("######[X,Y]#######",
              "\n point18=",cal[17],
              "\n point22=",cal[21],
              "\n point37=",cal[36],
              "\n point40=",cal[39],
              "\n point28=",cal[27],
              "\n point31=",cal[30],
              "\n point32=",cal[31],
              "\n point49=",cal[48],
              "\n point58=",cal[57],
              "\n point9=",cal[8])
        
        for (x, y) in shape: #Zeichnen Sie 68 Orientierungspunkte auf dem gesamten Gesicht
            cv2.circle(frame, (x, y), 1, (255, 255, 255), -1)
            cv2.putText(frame,str((x, y)-shape[30]),(x,y), cv2.FONT_HERSHEY_PLAIN, 1.0, (0, 0, 255), 2)

    
    cv2.imshow('frame',frame) #Bild anzeigen
    if cv2.waitKey(1) & 0xFF == ord('q'): #Drücken Sie q, um zu brechen und zu beenden
        break

capture.release() #Beenden Sie die Videoaufnahme
cv2.destroyAllWindows() #Fenster schließen

Schließlich

Zum Schluss werfen Sie das gesamte Programm und beenden es. Danke für deine harte Arbeit.

Programm

HeadPoseEstimation.py


import cv2 #OpenCV:Bildverarbeitungsbibliothek
import dlib #Bibliothek für maschinelles Lernen
import imutils #OpenCV-Unterstützung
from imutils import face_utils
import numpy as np


#Ruft ein VideoCapture-Objekt ab
DEVICE_ID = 0 #ID 0 ist eine Standard-Webkamera
capture = cv2.VideoCapture(DEVICE_ID)#Von dlib trainierte Daten lesen
predictor_path = ".../shape_predictor_68_face_landmarks.dat"

detector = dlib.get_frontal_face_detector() #Gesichtsdetektor anrufen. Nur das Gesicht wird erkannt.
predictor = dlib.shape_predictor(predictor_path) #Geben Sie Orientierungspunkte wie Augen und Nase aus dem Gesicht aus

while(True): #Holen Sie sich kontinuierlich Bilder von der Kamera
    ret, frame = capture.read() #Nehmen Sie von der Kamera auf und fügen Sie ein Bild mit Bilddaten in das Bild ein
    
    frame = imutils.resize(frame, width=1000) #Passen Sie die Anzeigegröße des Rahmenbilds an
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #In Graustufen konvertieren
    rects = detector(gray, 0) #Gesicht von Grau erkennen
    image_points = None
     
    for rect in rects:
        shape = predictor(gray, rect)
        shape = face_utils.shape_to_np(shape)

        for (x, y) in shape: #Zeichnen Sie 68 Orientierungspunkte auf dem gesamten Gesicht
            cv2.circle(frame, (x, y), 1, (255, 255, 255), -1)

        image_points = np.array([
                tuple(shape[30]),#Nasenspitze
                tuple(shape[21]),
                tuple(shape[22]),
                tuple(shape[39]),
                tuple(shape[42]),
                tuple(shape[31]),
                tuple(shape[35]),
                tuple(shape[48]),
                tuple(shape[54]),
                tuple(shape[57]),
                tuple(shape[8]),
                ],dtype='double')
    
    if len(rects) > 0:
        model_points = np.array([
                (0.0,0.0,0.0), # 30
                (-30.0,-125.0,-30.0), # 21
                (30.0,-125.0,-30.0), # 22
                (-60.0,-70.0,-60.0), # 39
                (60.0,-70.0,-60.0), # 42
                (-40.0,40.0,-50.0), # 31
                (40.0,40.0,-50.0), # 35
                (-70.0,130.0,-100.0), # 48
                (70.0,130.0,-100.0), # 54
                (0.0,158.0,-10.0), # 57
                (0.0,250.0,-50.0) # 8
                ])

        size = frame.shape

        focal_length = size[1]
        center = (size[1] // 2, size[0] // 2) #Mittelkoordinaten des Gesichts

        camera_matrix = np.array([
            [focal_length, 0, center[0]],
            [0, focal_length, center[1]],
            [0, 0, 1]
        ], dtype='double')

        dist_coeffs = np.zeros((4, 1))

        (success, rotation_vector, translation_vector) = cv2.solvePnP(model_points, image_points, camera_matrix,
                                                                      dist_coeffs, flags=cv2.SOLVEPNP_ITERATIVE)
        #Rotierende Matrix und Jacobian
        (rotation_matrix, jacobian) = cv2.Rodrigues(rotation_vector)
        mat = np.hstack((rotation_matrix, translation_vector))

        #yaw,pitch,Rolle herausnehmen
        (_, _, _, _, _, _, eulerAngles) = cv2.decomposeProjectionMatrix(mat)
        yaw = eulerAngles[1]
        pitch = eulerAngles[0]
        roll = eulerAngles[2]
        
        print("yaw",int(yaw),"pitch",int(pitch),"roll",int(roll))#Extraktion von Kopfhaltungsdaten

        cv2.putText(frame, 'yaw : ' + str(int(yaw)), (20, 10), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 255), 2)
        cv2.putText(frame, 'pitch : ' + str(int(pitch)), (20, 25), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 255), 2)
        cv2.putText(frame, 'roll : ' + str(int(roll)), (20, 40), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 255), 2)

        (nose_end_point2D, _) = cv2.projectPoints(np.array([(0.0, 0.0, 500.0)]), rotation_vector,
                                                         translation_vector, camera_matrix, dist_coeffs)
        #Darstellung der bei der Berechnung verwendeten Punkte/Anzeige des Gesichtsrichtungsvektors
        for p in image_points:
            cv2.drawMarker(frame, (int(p[0]), int(p[1])),  (0.0, 1.409845, 255),markerType=cv2.MARKER_CROSS, thickness=1)

        p1 = (int(image_points[0][0]), int(image_points[0][1]))
        p2 = (int(nose_end_point2D[0][0][0]), int(nose_end_point2D[0][0][1]))

        cv2.arrowedLine(frame, p1, p2, (255, 0, 0), 2)
    
    cv2.imshow('frame',frame) #Bild anzeigen
    if cv2.waitKey(1) & 0xFF == ord('q'): #Drücken Sie q, um zu brechen und zu beenden
        break


capture.release() #Beenden Sie die Videoaufnahme
cv2.destroyAllWindows() #Fenster schließen

Nachtrag 2020/4/2

OpenCV funktioniert nicht mit Qt-bezogenen Fehlern!

Ich habe kürzlich diesen Fehler erhalten

qt.qpa.plugin: Could not find the Qt platform plugin "cocoa" in ""
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Es scheint, dass dieser Fehler auftritt, wenn ich neues openCV mit pip installiere. Es funktioniert, wenn die Version gesenkt wird.

pip3 install opencv-python==4.1.2.30

Referenzzusammenfassung

Qiita Untersuchung der Schätzung der Gesichtsorientierung

Extern

Head Pose Estimation using OpenCV and Dlib dlib documentation Facial landmarks with dlib, OpenCV, and Python

Recommended Posts

Schätzung der Kopforientierung mit Python und OpenCV + dlib
Erhalten und schätzen Sie die Form des Kopfes mit Dlib und OpenCV mit Python
Ich habe versucht, Objekte mit Python und OpenCV zu erkennen
[Ubuntu] [Python] Vergleich der Gesichtserkennung zwischen dlib und OpenCV
[Python] Verwenden von OpenCV mit Python (Basic)
Verwenden von OpenCV mit Python @Mac
Nehmen Sie Zeitraffer von einer PC-Kamera mit Python, OpenCV auf
[Python] Zugreifen auf und Zuschneiden von Bildpixeln mit OpenCV (für Anfänger)
Umgebungskonstruktion von Python und OpenCV
Leuchtendes Leben mit Python und OpenCV
[Ubuntu] [Python] Objektverfolgung mit dlib
[Python] Verwenden von OpenCV mit Python (Bildfilterung)
Neuronales Netzwerk mit OpenCV 3 und Python 3
Authentifizierung mit Tweepy-User-Authentifizierung und Anwendungsauthentifizierung (Python)
[Python] Verwenden von OpenCV mit Python (Bildtransformation)
[Python] Verwenden von OpenCV mit Python (Kantenerkennung)
Clustering und Visualisierung mit Python und CytoScape
[Bildverarbeitung] Poo-san ist durch Kantenerkennung mit Python und OpenCV nackt!
Erstellen und testen Sie mit Docker in wenigen Minuten eine OpenCV- und Python-Umgebung
Ausrichten gescannter Bilder von animiertem Videopapier mit OpenCV und Python
Hinweise zur Verwendung von cChardet und python3-chardet in Python 3.3.1.
Von Python bis zur Verwendung von MeCab (und CaboCha)
Erstellen Sie Python 3 und OpenCV unter Ubuntu 18.04
Verwenden von Python und MeCab mit Azure Databricks
[Ubuntu] [Python] Gesichtsorganerkennung mit dlib
Dlib-Gesichtserkennung und Blinkzähler von Python
Machen Sie einen Mario mit Numpy und OpenCV
Bilder mit Pupil, Python und OpenCV aufnehmen
Erstellen eines Markierungsblatts mit Python OpenCV (Tipps zum guten Lesen)
Einfache Einführung in die Python3-Serie und OpenCV3
Ich verwende Tox und Python 3.3 mit Travis-CI
Hallo Welt- und Gesichtserkennung mit OpenCV 4.3 + Python
Ich habe versucht, Web-Scraping mit Python und Selen
Hinweise zur Installation von Python3 und zur Verwendung von pip unter Windows7
Entwickeln und Bereitstellen von Python-APIs mit Kubernetes und Docker
Python-Entwicklungsablauf mit Poetry, Git und Docker
Installieren Sie OpenCV 4.0 und Python 3.7 unter Windows 10 mit Anaconda
Erstellen Sie eine Webmap mit Python und GDAL
[Python3] Automatische Texterzeugung mit janome und markovify
Versuchen Sie es mit Tensorflow. ① Erstellen Sie eine Python-Umgebung und führen Sie Tensorflow ein
Feature Matching mit OpenCV 3 und Python 3 (A-KAZE, KNN)
cv2-Funktionen und Datentypen (OpenCV-Python-Bindung)
Versuchen Sie, die ChatWork-API und die Qiita-API in Python zu verwenden
Python2.7 + CentOS7 + OpenCV3
Objektverfolgung mit OpenCV3 und Python3 (Verfolgung von Funktionspunkten, die mit der Maus mithilfe der Lucas-Kanade-Methode festgelegt wurden)
Starten Sie Python
OpenCV-Beispiele (Python)
[Hinweis] openCV + Python
Scraping mit Python
Grundeinstellungen für die Verwendung von Python3.8 und pip unter CentOS8
Durchsuchen von Pixiv-Tags und Speichern von Illustrationen mit Python
Erweiterbare Skelette für Vim mit Python, Click und Jinja2
Versuchen Sie, eine komprimierte Datei mit Python und zlib zu erstellen
Aggregieren Sie Git-Protokolle mit Git Python und analysieren Sie Assoziationen mit Orange
Autorenschätzung unter Verwendung von neuronalen Netzen und Doc2Vec (Aozora Bunko)
Versuchen Sie, die Bildkonvertierung mit OpenCV mit Python zu projizieren
Senden und empfangen Sie Google Mail über die Google Mail-API mit Python
Implementieren eines Generators mit Python> Link> Yield und next ()> Yield