2017-01-20 13 views
3

카메라에서 이미지를 얻고 (렌즈 왜곡없이) 직사각형 객체를 감지해야합니다. 마커가 좋은 예입니다. 마커의 경우 코너 수, 최소 크기, 보드 대비 및 볼록을 확인합니다. 거짓 사각형의 양이 많은 경우이를 향상시키는 방법에 대한 아이디어가있었습니다. 일반적으로 이러한 모든 때문에 관점 모양의 이러한 종류를 허용하는 경우 우리가 확인할 수없는 카메라에 대해 아무것도 모른 채, 유효원근감있는 직사각형 피사체 품질 찾기

image

: 다음은 예제 이미지입니다. 나는 현실에서 직사각형의 크기 (또는 적어도 비율)를 안다. 그래서 나는 이들을 재 투영하고 오류를 검사함으로써이 모양 중 많은 부분을 무시할 수 있어야한다는 생각을 가지고있었습니다. solvePnPRansac을 사용하는 경우처럼 모양을 사용할 수없는 경우 수렴 할 수 없습니다. 그것이 수렴하지 않으면 나는 그것을 무시한다. 슬프게도, OpenCV 해결 함수 중 어느 것도 오류 또는 수렴을 검사 할 수 없습니다. 일부 직사각형이 겹칠 가능성이 있기 때문에 실제로 비율이나 품질이 필요합니다. 세 가지의

overlap image

하나는 실제로 올바른지, 또는 적어도 "최고"예를 들어 내 객체 찾기에이 사각형을 식별합니다. 그러나 그것이 어떤 것인지 알기 위해서는 어떤 방법이 필요합니다. 나는 카메라의 관점 때문에 선 길이와 같은 것을 사용할 수 없다. 그래서 나는 방금 내가 풀 수 있고 가장 작은 오류가있는 것을 볼 수 있다고 생각했습니다.

이미지에 렌즈 왜곡이 없지만 solvePnP가 있다고해도 일반적으로 D를 전달할 수 있습니다. 이것도 가능합니까 아니면 뭔가 빠졌습니까? solvePnPRansac을 해킹하여 방금 수렴을 시도해 볼 수는 있겠지만 더 간단한 방법이 있을까요?

+0

이 정말 멋진 질문이다,하지만 난 그냥 조금 너무 이론적 그리고 좀 토론을 포함하기 때문에이 스택 교환 형식에 맞는 의심한다. 다른 사람들과 문제에 관해 이야기하기 위해 CV 포럼을 시도해야합니다. –

+0

투영 된 사각형의 종횡비를 계산할 수 있습니다 (http://stackoverflow.com/questions/38285229/counting-aspect-ratio-of-perspective-transform-destination-image/38402378#38402378 참조). 종횡비를 이미 알고 있다면 다음과 같이 할 수 있습니다. 모서리를 기준으로 종횡비를 계산 한 다음 알고있는 비율과 일치하는지 확인합니다. – y300

+0

Tomáš Zato - answer.opencv.org에 게시하고 싶었지만 이전에 많이 게시하지 않았기 때문에 사진 (또는 링크)을 게시 할 수 없었습니다. 나는 업을 세워야 해. – user1214513

답변

0

격자로 교정하는 동안 수행 할 작업을 할 수 있다고 생각했습니다. 재 투영 오류를 계산할 수 있습니다. 먼저 변환 행렬을 구하십시오. 그런 다음 변환 행렬을 사용하여 점을 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 
    } 
    }