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.
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.
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]
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.
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
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.
yaw,roll,pitch Die Kopfhaltungsparameter Gieren, Rollen, Neigen sind wie folgt. (Wie ein Flugzeug)
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 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
Zum Schluss werfen Sie das gesamte Programm und beenden es. Danke für deine harte Arbeit.
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
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
Qiita Untersuchung der Schätzung der Gesichtsorientierung
Head Pose Estimation using OpenCV and Dlib dlib documentation Facial landmarks with dlib, OpenCV, and Python
Recommended Posts