Ich habe eine Fischaugenkamera in der Decke und ich möchte einige Punkte auf dem Boden finden. Ich habe den Ursprung meines Referenzsystems (reale Welt) direkt unter der Kamera angegeben und möchte die Position jedes Objekts in Zentimetern wissen. Dieses Bild zeigt dies:Bildpunkte (Pixel) zu realen Welt Koordinaten (Meter)
Zum einen habe ich die Kamerakalibrierung getan, und ich habe das nächste Ergebnis mit einem RMS von 1,11 erhalten:
Undistorted image after calibration
Als Ergebnis der Kalibrierung Ich habe intrinsische Parameter (Kameramatrix) erhalten, also habe ich cv :: solvePnP verwendet, um Rotations- und Translationsvektoren zu erhalten. Für die Anwendung habe ich einige Punkte im unverzerrten Bild (in Pixeln) markiert und sie in der realen Welt gemäß meinem Referenzsystem gemessen.
Zum Beispiel ist der Ursprung in der Mitte eines 1024x768 Bildes, so:
- Punkt 0: Imagepoint (512, 384) [Pixel] -> ObjectPoint (0,0) [cm]
Der nächste Code zeigt dies:
std::vector<cv::Point2f> imagePointsPix;
std::vector<cv::Point3f> objectPointsCm;
imagePointsPix.push_back(cv::Point2f(512.,384.));
imagePointsPix.push_back(cv::Point2f(404.,512.));
imagePointsPix.push_back(cv::Point2f(666.,211.));
imagePointsPix.push_back(cv::Point2f(519.,66.));
objectPointsCm.push_back(cv::Point3f(0., 0., 0.));
objectPointsCm.push_back(cv::Point3f(-80.,-132.,0.));
objectPointsCm.push_back(cv::Point3f(120.,188.,0.));
objectPointsCm.push_back(cv::Point3f(-40.,268.,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(objectPointsCm, imagePointsPix, cameraMatrix, distCoeffs, rvec, tvec, 0, SOLVEPNP_ITERATIVE);
cv::Rodrigues(rvec,rotationMatrix);
Jetzt habe ich die Kamera Matrix, die Rotationsmatrix und den traslation Vektor, so von this als Referenz ich bin kann jeden Punkt berechnen, wenn ich seine Position in Pixeln habe. Dies ist der Code:
cv::Mat uvPoint = cv::Mat::ones(3,1,cv::DataType<double>::type); //u,v,1
uvPoint.at<double>(0,0) = 512.; //img point for which we want its real coordinates
uvPoint.at<double>(1,0) = 384.;
cv::Mat tempMat, tempMat2;
double s;
tempMat = rotationMatrix.inv() * cameraMatrix.inv() * uvPoint;
tempMat2 = rotationMatrix.inv() * tvec;
s = 0 + tempMat2.at<double>(2,0); //before 0 it was 285, which represents the height Zconst
s /= tempMat.at<double>(2,0);
std::cout << "P = " << rotationMatrix.inv() * (s * cameraMatrix.inv() * uvPoint - tvec) << std::endl;
ich diese Ergebnisse für die gleichen Punkte ich für den Erhalt meiner Parameter verwendet:
- Punkt 0 -> (0,213, 3,391) (es sollte sein (0,0)) ERROR: 3,69 cm
- Punkt 1 -> (-68,28, -112,82) (es soll (-80, -132)) seine ERROR: 17,49 cm
- Punkt 2 - -> (84.48, 1 37.61) (es sein soll (120, 188)) ERROR: 49,62 cm
Die restlichen Punkte auch einen Fehler zeigen, zu groß ... Ich habe mehr Punkte verwendet, aber die Ergebnisse nicht verbessern. Ich weiß nicht, wo ich falsch gelaufen bin, könnte mir jemand helfen?
Vielen Dank im Voraus.
Es besteht die Möglichkeit, dass die Kalibrierung in Ordnung war und dass Sie das Bild effektiv zweimal entschachtelt haben (siehe meine Antwort für die Erklärung). – rob3c