Question Calcul des coordonnées x, y (3D) à partir du point image


J'ai pour tâche de localiser un objet dans un système de coordonnées 3D. Comme je dois obtenir des coordonnées X et Y presque exactes, j'ai décidé de suivre un marqueur de couleur avec des coordonnées Z connues qui seront placées sur le dessus de l'objet en mouvement, comme la balle orange sur cette image: undistored

Tout d'abord, j'ai effectué le calibrage de la caméra pour obtenir des paramètres intrinsèques, puis j'ai utilisé cv :: solvePnP pour obtenir le vecteur de rotation et de translation comme dans le code suivant:

std::vector<cv::Point2f> imagePoints;
std::vector<cv::Point3f> objectPoints;
//img points are green dots in the picture
imagePoints.push_back(cv::Point2f(271.,109.));
imagePoints.push_back(cv::Point2f(65.,208.));
imagePoints.push_back(cv::Point2f(334.,459.));
imagePoints.push_back(cv::Point2f(600.,225.));

//object points are measured in millimeters because calibration is done in mm also
objectPoints.push_back(cv::Point3f(0., 0., 0.));
objectPoints.push_back(cv::Point3f(-511.,2181.,0.));
objectPoints.push_back(cv::Point3f(-3574.,2354.,0.));
objectPoints.push_back(cv::Point3f(-3400.,0.,0.));

cv::Mat rvec(1,3,cv::DataType<double>::type);
cv::Mat tvec(1,3,cv::DataType<double>::type);
cv::Mat rotationMatrix(3,3,cv::DataType<double>::type);

cv::solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec);
cv::Rodrigues(rvec,rotationMatrix);

Après avoir toutes les matrices, cette équation qui peut m'aider à transformer le point de l'image en coordonnées wolrd:

transform_equation

où M est cameraMatrix, R-rotationMatrix, t-tvec et s est un inconnu. Zconst représente la hauteur de la balle orange, dans cet exemple, elle est de 285 mm. Donc, d'abord je dois résoudre l'équation précédente, pour obtenir "s", et après je peux trouver les coordonnées X et Y en sélectionnant le point d'image: equation2

En résolvant ce problème, je peux trouver la variable "s", en utilisant la dernière ligne des matrices, car Zconst est connu, voici donc le code suivant:

cv::Mat uvPoint = cv::Mat::ones(3,1,cv::DataType<double>::type); //u,v,1
uvPoint.at<double>(0,0) = 363.; //got this point using mouse callback
uvPoint.at<double>(1,0) = 222.;
cv::Mat tempMat, tempMat2;
double s;
tempMat = rotationMatrix.inv() * cameraMatrix.inv() * uvPoint;
tempMat2 = rotationMatrix.inv() * tvec;
s = 285 + tempMat2.at<double>(2,0); //285 represents the height Zconst
s /= tempMat.at<double>(2,0);
std::cout << "P = " << rotationMatrix.inv() * (s * cameraMatrix.inv() * uvPoint - tvec) << std::endl;

Après cela, j'ai obtenu un résultat: P = [-2629.5, 1272.6, 285.]

et quand je le compare à la mesure, qui est: Preal = [-2629.6, 1269.5, 285.]

l'erreur est très petite ce qui est très bien, mais quand je déplace cette boîte sur les bords de cette pièce, les erreurs sont peut-être de 20-40mm et je voudrais améliorer cela. Quelqu'un peut-il m'aider avec ça, avez-vous des suggestions?


34
2017-09-06 12:12


origine


Réponses:


Compte tenu de votre configuration, les erreurs de 20 à 40 mm sur les bords sont moyennes. On dirait que tu as tout fait bien.

Sans modifier la configuration de la caméra / du système, faire mieux sera difficile. Vous pouvez essayer de refaire le calibrage de la caméra et espérer de meilleurs résultats, mais cela ne les améliorera pas beaucoup (et vous risquez d'obtenir de moins bons résultats, donc ne supprimez pas les paramètres réels)

Comme indiqué par count0, si vous avez besoin de plus de précision, vous devriez opter pour plusieurs mesures.


8
2017-09-06 13:54



Est-ce que vous obtenez les points verts (imagePoints) de l'image déformée ou non déformée? Parce que la fonction solvePnP déforme déjà les imagesPoints (à moins que vous ne passiez pas les coefficients de distorsion, ou ne les transmettiez pas comme null). Si vous les récupérez à partir de l’image non déformée, vous risquez de détourner deux fois ces points d’image, ce qui entraînerait une erreur accrue dans les coins.

https://github.com/Itseez/opencv/blob/master/modules/calib3d/src/solvepnp.cpp


3
2017-10-02 00:39