Vous pouvez résoudre cela en 3 étapes simples:
Étape 1:
Calculez le vecteur de direction 3D, exprimé dans le repère de la caméra, du rayon correspondant au point d'image 2D donné en inversant le modèle de projection de la caméra:
std::vector imgPt = {{u,v}}; // Point d'image d'entrée
std::vector normPt;
cv::undistortPoints (imgPt, normPt, cameraMatrix, distCoeffs);
cv::Matx31f ray_dir_cam(normPt[0].x, normPt[0].y, 1);
// 'ray_dir_cam' est la direction 3D du rayon dans le repère de la caméra
// Dans le repère de la caméra, ce rayon prend son origine au centre de la caméra à (0,0,0)
Étape 2:
Calculez la direction 3D du vecteur de ce rayon dans le repère attaché à l'échiquier, en utilisant la pose relative entre la caméra et l'échiquier:
// solvePnP vous donne généralement 'rvec_cam_chessboard' et 'tvec_cam_chessboard'
// Inversez cette pose pour obtenir la pose qui mappe les coordonnées de la caméra aux coordonnées de l'échiquier
cv::Matx33f R_cam_chessboard;
cv::Rodrigues(rvec_cam_chessboard, R_cam_chessboard);
cv::Matx33f R_chessboard_cam = R_cam_chessboard.t();
cv::Matx31f t_cam_chessboard = tvec_cam_chessboard;
cv::Matx31f pos_cam_wrt_chessboard = -R_chessboard_cam*t_cam_chessboard;
// Mappez le vecteur de direction du rayon des coordonnées de la caméra aux coordonnées de l'échiquier
cv::Matx31f ray_dir_chessboard = R_chessboard_cam * ray_dir_cam;
Étape 3:
Trouvez le point 3D désiré en calculant l'intersection entre le rayon 3D et le plan de l'échiquier avec Z=0:
// Exprimé dans le repère de l'échiquier, le rayon prend son origine
// de la position 3D du centre de la caméra, c'est-à-dire 'pos_cam_wrt_chessboard', et son 3D
// le vecteur de direction est 'ray_dir_chessboard'
// Tout point sur ce rayon peut être exprimé de manière paramétrique en utilisant sa profondeur 'd':
// P(d) = pos_cam_wrt_chessboard + d * ray_dir_chessboard
// Pour trouver l'intersection entre le rayon et le plan de l'échiquier, nous
// calculons la profondeur 'd' pour laquelle la coordonnée Z de P(d) est égale à zéro
float d_intersection = -pos_cam_wrt_chessboard.val[2]/ray_dir_chessboard.val[2];
cv::Matx31f intersection_point = pos_cam_wrt_chessboard + d_intersection * ray_dir_chessboard;
0 votes
Avec vos vecteurs de transformation et de rotation, êtes-vous capable d'expliquer tous les coins de l'échiquier en 3D?
0 votes
Si vous dites que Z sera 0, est-il acceptable pour vous d'obtenir simplement les coordonnées de l'avion de ce point? Comme "aller 10 cm dans la direction rouge et moins 15 cm dans la direction verte?
0 votes
@Micka cela ne fonctionnera pas, car les pixels plus proches de l'appareil photo représentent une zone plus grande
0 votes
Il est facile d'obtenir les coordonnées de l'avion avec une homographie de perspective. Mais si vous avez besoin des points 3D dans votre espace 3D centré sur la caméra, vous devez ensuite transformer l'avion selon vos vecteurs de rotation et de translation.
0 votes
Pouvez-vous fournir votre résultat attendu de ces coordonnées de point?
0 votes
Aussi les dimensions de l'échiquier?