Utilisez la fonction OpenCV solvepnp() pour résoudre le problème PnP

Manav Narula 30 janvier 2023
  1. Comprendre le problème PnP
  2. Utilisez la fonction opencv.solvepnp() pour résoudre le problème PnP
  3. Conclusion
Utilisez la fonction OpenCV solvepnp() pour résoudre le problème PnP

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 :

  1. 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.
  2. 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.

  1. Le paramètre objectPoints prend les points 3D de toutes les entités mentionnées précédemment.
  2. Le paramètre imagePoints permet de spécifier les points 2D des caractéristiques de l’objet.
  3. 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.
  4. 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.
  5. 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ètre flags.

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.

exemple d’image pour déterminer la pose

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:

pose déterminée à l’aide de solvepnp

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.

Auteur: Manav Narula
Manav Narula avatar Manav Narula avatar

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

Article connexe - Python OpenCV