격자로 교정하는 동안 수행 할 작업을 할 수 있다고 생각했습니다. 재 투영 오류를 계산할 수 있습니다. 먼저 변환 행렬을 구하십시오. 그런 다음 변환 행렬을 사용하여 점을 3D로 변환 한 다음 나중에 projectPoints를 사용하여 2D로 다시 투영합니다. 그런 다음 원본 2D 점과 투영 된 2D 점 사이의 거리를 확인합니다. 이것은 품질에 사용될 수 있습니다. 가능하지 않은 개체는 이미지에서 100 픽셀 이상의 재 투영 오류가 발생하지만 가능한 개체는 20 픽셀 미만입니다. 그래서 나는 단지 25 픽셀의 컷오프를 했으므로 제대로 작동하는 것 같습니다.
내가 변환하는 것보다 더 많은 변환이 가능하다는 점에 유의하십시오. 내 원래 이미지에서 아마도 현재 카메라로는 두 가지가 가능하지 않지만 여전히 많은 가짜를 거부합니다.
아무도 다른 아이디어가 없다면이 대답으로 대답하겠습니다. 여기
내가 사용하는 방법에 대한 몇 가지 코드 :
이
//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 - answer.opencv.org에 게시하고 싶었지만 이전에 많이 게시하지 않았기 때문에 사진 (또는 링크)을 게시 할 수 없었습니다. 나는 업을 세워야 해. – user1214513