Estimation de la pose de la tête en anglais. Il s'agit d'un algorithme qui estime la direction dans laquelle le visage fait face et l'inclinaison de la tête à partir des informations d'image d'entrée et des données de caractéristiques du visage. Récemment, il a été largement utilisé pour le développement de Vtuber.
Qiita a déjà introduit plusieurs méthodes pour estimer la direction de la tête. Ceci est très bien organisé dans l'article de Qiita. Enquête sur l'estimation de l'orientation du visage
Je pense que c'est l'article auquel vous faites référence sur la méthode d'estimation de la tête utilisant Python et OpenCV + dlib. Head Pose Estimation using OpenCV and Dlib
Les algorithmes d'estimation de l'orientation du visage sont décrits en détail dans la section Comment fonctionnent les algorithmes d'estimation de pose? De cette page.
Pour le moment, j'écrirai le programme présenté dans l'article. Vous pouvez télécharger le fichier dat pour la reconnaissance faciale à partir d'ici. [dlib.net] 68 points de données apprises pour la reconnaissance faciale [DL]
HeadPoseEstimation.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import cv2 #OpenCV:Bibliothèque de traitement d'image
import dlib #Bibliothèque d'apprentissage automatique
import imutils #Assistance OpenCV
from imutils import face_utils
import numpy as np
Nous importons OpenCV pour le traitement d'image, dlib pour la reconnaissance d'image et imutils comme aide à l'affichage à l'écran.
HeadPoseEstimation.py
DEVICE_ID = 0 #L'ID 0 de la caméra utilisée est une webcam standard
capture = cv2.VideoCapture(DEVICE_ID)#Lecture des données entraînées par dlib
predictor_path = ",,,/shape_predictor_68_face_landmarks.dat"
#Copiez le chemin du fichier dat appris
detector = dlib.get_frontal_face_detector() #Détecteur de visage d'appel. Seul le visage est détecté.
predictor = dlib.shape_predictor(predictor_path) #Sortez les repères tels que les yeux et le nez du visage
Veuillez vous référer ici pour les fonctions dlib détaillées. dlib documentation
Il acquiert une image à la fois de la caméra et la traite.
HeadPoseEstimation.py
while(True): #Obtenez des images en continu de la caméra
ret, frame = capture.read() #Capturez à partir de l'appareil photo et placez une image de données d'image dans le cadre
frame = imutils.resize(frame, width=1000) #Ajuster la taille d'affichage de l'image du cadre
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #Convertir en échelle de gris
rects = detector(gray, 0) #Détecter le visage du gris
image_points = None
for rect in rects:
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
for (x, y) in shape: #Tracez 68 points de repère sur tout le visage
cv2.circle(frame, (x, y), 1, (255, 255, 255), -1)
image_points = np.array([
tuple(shape[30]),#Pointe du nez
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) #Coordonnées centrales du visage
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)
#Matrice rotative et jacobienne
(rotation_matrix, jacobian) = cv2.Rodrigues(rotation_vector)
mat = np.hstack((rotation_matrix, translation_vector))
#yaw,pitch,Sortez le rouleau
(_, _, _, _, _, _, eulerAngles) = cv2.decomposeProjectionMatrix(mat)
yaw = eulerAngles[1]
pitch = eulerAngles[0]
roll = eulerAngles[2]
print("yaw",int(yaw),"pitch",int(pitch),"roll",int(roll))#Extraction des données de posture de la tête
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)
#Tracé des points utilisés dans le calcul/Affichage du vecteur de direction du visage
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) #Afficher l'image
if cv2.waitKey(1) & 0xFF == ord('q'): #Appuyez sur q pour interrompre et quitter pendant
break
capture.release() #Quitter la capture vidéo
cv2.destroyAllWindows() #Fermer la fenêtre
Si cela fonctionne correctement, ce sera comme ça.
yaw,roll,pitch Les paramètres de posture de la tête: lacet, roulis, tangage sont comme ça. (Identique à un avion)
Veuillez vous référer ici pour la position de image_points définie cette fois. Le point utilisé cette fois est ・ À l'intérieur des sourcils (22,23) ・ Dans les yeux (40,43) ・ Pointe de nez (31) ・ Les deux côtés du nez (32,36) ・ Les deux extérieurs de la bouche (49,55) ・ Sous les lèvres (58) ・ Menton (9) C'est 11 points de. La direction de la tête peut être estimée avec 5 points de manière algorithmique, mais quand je l'ai essayé, lorsque le score était petit, la direction du vecteur au bout du nez s'est retournée, j'ai donc augmenté le score. (Est-ce parce que les données formées sont basées sur des occidentaux ...) Facial landmarks with dlib, OpenCV, and Python Plus vous utilisez les points à l'extérieur du visage, meilleure sera la précision, mais si les sourcils, etc. sont coupés lorsqu'ils sont tournés de côté, cela entraînera une mauvaise appréciation de la quantité de traits, alors essayez d'utiliser les points au centre du visage autant que possible. <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 ">
Et le problème est model_points, c'est-à-dire que dois-je faire avec les coordonnées de position des parties de mon visage, mais je l'ai défini par la force à partir du programme suivant. Les données de coordonnées (x, y) du visage avec le bout du nez comme origine apparaîtront dans l'image, alors veuillez faire face à la caméra aussi droit que possible, étendez votre posture et lisez avec esprit. Je devine la coordonnée z. Trouvez la distance entre le bout de votre nez et la zone entre vos yeux et appliquez-la à la hauteur de votre nez. Accrochez-vous!
HPEcal.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import cv2 #OpenCV:Bibliothèque de traitement d'image
import dlib #Bibliothèque d'apprentissage automatique
import imutils #Assistance OpenCV
from imutils import face_utils
import numpy as np
#Obtient un objet VideoCapture
DEVICE_ID = 0 #L'ID 0 est une webcam standard
capture = cv2.VideoCapture(DEVICE_ID)#Lecture des données entraînées par dlib
predictor_path = "/shape_predictor_68_face_landmarks.dat"
print("[INFO] loading facial landmark predictor...")
detector = dlib.get_frontal_face_detector() #Détecteur de visage d'appel. Seul le visage est détecté.
predictor = dlib.shape_predictor(predictor_path) #Sortez les repères tels que les yeux et le nez du visage
while(True): #Obtenez des images en continu de la caméra
ret, frame = capture.read() #Capturez à partir de l'appareil photo et placez une image de données d'image dans le cadre
frame = imutils.resize(frame, width=2000) #Ajuster la taille d'affichage de l'image du cadre
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #Convertir en échelle de gris
rects = detector(gray, 0) #Détecter le visage du gris
image_points = None
for rect in rects:
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
#print(shape[30])#Coordonnées du nez
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: #Tracez 68 points de repère sur tout le visage
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) #Afficher l'image
if cv2.waitKey(1) & 0xFF == ord('q'): #Appuyez sur q pour interrompre et quitter pendant
break
capture.release() #Quitter la capture vidéo
cv2.destroyAllWindows() #Fermer la fenêtre
Enfin, lancez tout le programme et terminez-le. Je vous remercie pour votre travail acharné.
HeadPoseEstimation.py
import cv2 #OpenCV:Bibliothèque de traitement d'image
import dlib #Bibliothèque d'apprentissage automatique
import imutils #Assistance OpenCV
from imutils import face_utils
import numpy as np
#Obtient un objet VideoCapture
DEVICE_ID = 0 #L'ID 0 est une webcam standard
capture = cv2.VideoCapture(DEVICE_ID)#Lecture des données entraînées par dlib
predictor_path = ".../shape_predictor_68_face_landmarks.dat"
detector = dlib.get_frontal_face_detector() #Détecteur de visage d'appel. Seul le visage est détecté.
predictor = dlib.shape_predictor(predictor_path) #Sortez les repères tels que les yeux et le nez du visage
while(True): #Obtenez des images en continu de la caméra
ret, frame = capture.read() #Capturez à partir de l'appareil photo et placez une image de données d'image dans le cadre
frame = imutils.resize(frame, width=1000) #Ajuster la taille d'affichage de l'image du cadre
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #Convertir en échelle de gris
rects = detector(gray, 0) #Détecter le visage du gris
image_points = None
for rect in rects:
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
for (x, y) in shape: #Tracez 68 points de repère sur tout le visage
cv2.circle(frame, (x, y), 1, (255, 255, 255), -1)
image_points = np.array([
tuple(shape[30]),#Pointe du nez
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) #Coordonnées centrales du visage
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)
#Matrice rotative et jacobienne
(rotation_matrix, jacobian) = cv2.Rodrigues(rotation_vector)
mat = np.hstack((rotation_matrix, translation_vector))
#yaw,pitch,Sortez le rouleau
(_, _, _, _, _, _, eulerAngles) = cv2.decomposeProjectionMatrix(mat)
yaw = eulerAngles[1]
pitch = eulerAngles[0]
roll = eulerAngles[2]
print("yaw",int(yaw),"pitch",int(pitch),"roll",int(roll))#Extraction des données de posture de la tête
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)
#Tracé des points utilisés dans le calcul/Affichage du vecteur de direction du visage
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) #Afficher l'image
if cv2.waitKey(1) & 0xFF == ord('q'): #Appuyez sur q pour interrompre et quitter pendant
break
capture.release() #Quitter la capture vidéo
cv2.destroyAllWindows() #Fermer la fenêtre
J'ai récemment eu cette erreur
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.
Il semble que cette erreur apparaisse lorsque j'installe un nouvel openCV avec pip. Cela fonctionne lorsque la version est abaissée.
pip3 install opencv-python==4.1.2.30
Qiita Enquête sur l'estimation de l'orientation du visage
Head Pose Estimation using OpenCV and Dlib dlib documentation Facial landmarks with dlib, OpenCV, and Python
Recommended Posts