Utilisez la fonction OpenCV solvepnp() pour résoudre le problème PnP
- Comprendre le problème PnP
-
Utilisez la fonction
opencv.solvepnp()
pour résoudre le problème PnP - Conclusion
La bibliothèque OpenCV est une bibliothèque open source développée pour faciliter les tâches de vision par ordinateur. Cette bibliothèque est compatible avec Python et peut être utilisée pour implémenter et résoudre différents problèmes de traitement d’image.
Ce tutoriel démontrera l’utilisation de la fonction solvepnp()
de la bibliothèque OpenCV en Python. Cette fonction est utilisée pour résoudre le problème d’estimation de pose.
Comprendre le problème PnP
Le problème PnP est très courant en vision par ordinateur et représente le problème Perspective n-Points. Dans ce problème, nous ne pouvons pas déterminer la pose d’un objet par rapport à la caméra après avoir reçu les coordonnées 2D et 3D.
Cela peut être compris avec l’exemple du suivi du visage lors d’un examen en ligne. La pose d’un objet par rapport peut changer avec le changement de direction.
Les deux types de mouvements suivants facilitent ce changement :
- Le premier type de mouvement est le mouvement de translation, qui peut se produire le long de l’un des trois axes. L’objet se déplace dans un mouvement uniforme dans n’importe quelle direction particulière, modifiant ainsi ses coordonnées.
- Le deuxième type de mouvement est le mouvement de rotation, dans lequel l’objet peut tourner autour de l’un des trois axes.
Utilisez la fonction opencv.solvepnp()
pour résoudre le problème PnP
La fonction solvepnp()
de la bibliothèque OpenCV est utilisée pour l’estimation de la pose d’un objet donné par rapport à la caméra, résolvant ainsi le problème PnP. Il renvoie des vecteurs de rotation et de translation.
Il utilise les coordonnées 2D et 3D de l’objet avec la matrice de la caméra. Les coordonnées fournies sont celles des différentes caractéristiques du visage.
Ces caractéristiques sont le nez, les coins de la bouche, le menton et les deux yeux.
Discutons de tous les paramètres nécessaires à l’utilisation de cette fonction.
- Le paramètre
objectPoints
prend les points 3D de toutes les entités mentionnées précédemment. - Le paramètre
imagePoints
permet de spécifier les points 2D des caractéristiques de l’objet. - Le
cameraMatrix
est utilisé pour spécifier la valeur intrinsèque de la caméra. Cette matrice est créée à l’aide du point central et de la distance focale de l’appareil photo. - Pour lutter contre la distorsion soulevée par la caméra, on utilise le paramètre
distCoeffs
. Ce vecteur peut être NULL s’il y a une distorsion négligeable dans la caméra. - Nous pouvons utiliser le résultat de sortie pour les calculs initiaux en utilisant le paramètre
useExtrinsicGuess
, qui peut être vrai ou faux. A part ça, il n’y a que le paramètreflags
.
Les vecteurs de rotation et de translation renvoyés par cette fonction peuvent être utilisés pour tracer la ligne de pose de l’objet.
Par exemple, nous déterminerons la pose de l’image suivante.
Le code pour déterminer la pose de cette image est indiqué ci-dessous.
import cv2
import numpy as np
img = cv2.imread("img.jpg")
size = img.shape
image_points_2D = np.array(
[
(196, 141), # Nose tip
(190, 202), # Chin
(196, 124), # Left eye corner
(236, 128), # Right eye corner
(186, 175), # Left mouth
(214, 177), # Right mouth
],
dtype="double",
)
figure_points_3D = np.array(
[
(0.0, 0.0, 0.0), # Nose tip
(0.0, -330.0, -65.0), # Chin
(-225.0, 170.0, -135.0), # Left eye left corner
(225.0, 170.0, -135.0), # Right eye right corne
(-150.0, -150.0, -125.0), # Left Mouth corner
(150.0, -150.0, -125.0), # Right mouth corner
]
)
distortion_coeffs = np.zeros((4, 1))
focal_length = size[1]
center = (size[1] / 2, size[0] / 2)
matrix_camera = np.array(
[[focal_length, 0, center[0]], [0, focal_length, center[1]], [0, 0, 1]],
dtype="double",
)
success, vector_rotation, vector_translation = cv2.solvePnP(
figure_points_3D, image_points_2D, matrix_camera, distortion_coeffs, flags=0
)
nose_end_point2D, jacobian = cv2.projectPoints(
np.array([(0.0, 0.0, 1000.0)]),
vector_rotation,
vector_translation,
matrix_camera,
distortion_coeffs,
)
for p in image_points_2D:
cv2.circle(img, (int(p[0]), int(p[1])), 3, (0, 0, 255), -1)
point1 = (int(image_points_2D[0][0]), int(image_points_2D[0][1]))
point2 = (int(nose_end_point2D[0][0][0]), int(nose_end_point2D[0][0][1]))
cv2.line(img, point1, point2, (255, 255, 255), 2)
cv2.imshow("Final", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Production:
Beaucoup de choses se passent dans le code mentionné ci-dessus. Comprenons-le étape par étape.
Tout d’abord, nous lisons l’image requise à l’aide de la fonction imread()
. Les points pour les traits du visage sont mentionnés en 2D et 3D.
Les points et la matrice de la caméra sont fournis à la fonction solvepnp()
qui renvoie les vecteurs de rotation et de translation pour les coordonnées 3D de la pose.
Après avoir tracé visuellement la ligne pour la pose. Tout d’abord, nous traçons les traits du visage.
Nous utilisons les points 2D et traçons chaque point à l’aide de la fonction circle()
.
projectPoints()
est utilisé pour déterminer la projection des vecteurs renvoyés par la fonction solvepnp()
sur le plan image. Nous devons également passer le paramètre de la caméra dans cette fonction pour obtenir la projection.
Nous traçons une ligne à partir du nez du visage en ligne avec les points projetés à l’aide de la fonction line()
pour visualiser la pose déterminée par la méthode solvepnp()
.
Conclusion
Ce tutoriel nous a appris à utiliser la fonction solvepnp()
pour résoudre le problème PnP dans Computer Vision. Nous devons connaître les paramètres requis pour utiliser cette méthode.
Les principaux paramètres sont les points 2D et 3D des traits du visage de l’image et la matrice de la caméra. En utilisant ces valeurs, il renvoie les vecteurs qui déterminent les points 3D de la pose.
On obtient une projection de ces points en 2D par rapport à la caméra grâce à la fonction projectPoints()
. Enfin, nous traçons une ligne pour représenter la pose déterminée dans l’image en utilisant ces points.
Manav is a IT Professional who has a lot of experience as a core developer in many live projects. He is an avid learner who enjoys learning new things and sharing his findings whenever possible.
LinkedIn