私はグリッドで校正中に何かすることができると思った。私は再投影誤差を計算することができます。ですからまず、変換行列を得るために解いてください。次に、変換行列を使用して3次元で点を変換し、その後、projectPointsを使用して2次元で投影します。次に、オリジナルの2D点と投影された2D点の間の距離をチェックします。これは、品質のために使用することができます。可能でないオブジェクトは、画像に再投影エラーが100ピクセル以上あることがよくありますが、オブジェクトのサイズが20ピクセル未満です。だから私はちょうど25ピクセルのカットオフを行い、それは正常に動作するようです。
私はより多くの変換が可能であることに注意してください。私の元の画像では、私の現在のカメラでは2つが可能ではないかもしれませんが、それでも多くの偽物を拒否しました。
他に誰も考えられない人がいる場合は、これを回答として受け入れます。ここで
は、私が使用する方法についていくつかのコードです:
//This is the object in 3D
double width = 50.0; //Object is 50mm wide
double height = 30.0; //Object is 30mm tall
cv::Mat object_points(4,3,CV_64FC1);
object_points.at<double>(0,0)=0;
object_points.at<double>(0,1)=0;
object_points.at<double>(0,2)=0;
object_points.at<double>(1,0)=width;
object_points.at<double>(1,1)=0;
object_points.at<double>(1,2)=0;
object_points.at<double>(2,0)=width;
object_points.at<double>(2,1)=height;
object_points.at<double>(2,2)=0;
object_points.at<double>(3,0)=0;
object_points.at<double>(3,1)=height;
object_points.at<double>(3,2)=0;
//Check all rectangles for error
cv::Mat image_points(4,2,CV_64FC1);
for (size_t i = 0; i < rectangles_to_test.size(); i++) {
// Get rectangle points
for (size_t c = 0; c < 4; ++c) {
image_points.at<double>(c,0) = (rectangles_to_test[i].points[c].x);
image_points.at<double>(c,1) = (rectangles_to_test[i].points[c].y);
}
// Calculate transformation matrix
cv::Mat rvec, tvec;
cv::solvePnP(object_points, image_points, M1, D1, rvec, tvec);
cv::Mat rotation;
Matrix4<double> transform;
transform.init_identity();
cv::Rodrigues(rvec, rotation);
for(size_t row = 0; row < 3; ++row) {
for(size_t col = 0; col < 3; ++col) {
transform.set(row, col, rotation.at<double>(row, col));
}
transform.set(row, 3, tvec.at<double>(row, 0));
}
// Calculate projection
std::vector<cv::Point3f> p3(4);
std::vector<cv::Point2f> p2;
Vector4<double> p = transform * Vector4<double>(0, 0, 0, 1);
p3[0] = cv::Point3f((float)p.x, (float)p.y, (float)p.z);
p = transform * Vector4<double>(width, 0, 0, 1);
p3[1] = cv::Point3f((float)p.x, (float)p.y, (float)p.z);
p = transform * Vector4<double>(width, height, 0, 1);
p3[2] = cv::Point3f((float)p.x, (float)p.y, (float)p.z);
p = transform * Vector4<double>(0, height, 0, 1);
p3[3] = cv::Point3f((float)p.x, (float)p.y, (float)p.z);
cv::projectPoints(p3, cv::Mat::zeros(1, 3, CV_64FC1), cv::Mat::zeros(1, 3, CV_64FC1), M1, D1, p2);
// Calculate reprojection error
rectangles_to_test[i].reprojection_error = 0.0;
for (size_t c = 0; c < 4; ++c) {
double dx = p2[c].x - rectangles_to_test[i].points[c].x;
double dy = p2[c].y - rectangles_to_test[i].points[c].y;
rectangles_to_test[i].reprojection_error += std::sqrt(dx*dx + dy*dy);
}
if (rectangles_to_test[i].reprojection_error > reprojection_error_threshold) {
//rectangle is no good
}
}
これは本当にクールな質問ですが、私はそれが少しあまりにも理論だとちょっと議論を必要とするので、それがスタック交換フォーマットに適合疑います。あなたは本当に他の人との問題について話すためにいくつかのCVフォーラムを試してください。 –
投影された矩形の縦横比を計算することができます(http://stackoverflow.com/questions/38285229/counting-aspect-ratio-of-perspective-transform-destination-image/38402378#38402378を参照)。アスペクト比をすでに知っている場合は、次のことができます。コーナーに基づいてアスペクト比を推定し、それが知っている比率に一致するかどうかを確認します。 – y300
TomášZato - 私はanswers.opencv.orgに投稿したいと思っていましたが、以前はあまり投稿していないので、写真を投稿(またはリンク)できませんでした。私は自分のカルマを上げなければならない。 – user1214513