2016-06-08 4 views
2

나는 천장에 어안 카메라를 가지고 있는데 바닥에 몇 점을 배치하려고합니다. 카메라 바로 아래에 레퍼런스 시스템 (실세계)의 원점을두고 모든 물체의 위치를 ​​센티미터 단위로 알고 싶습니다. 이 그림이 보여줍니다 첫째이미지 포인트 (픽셀)에서 실제 좌표 (미터)

Reference system - Real world

, 나는 카메라 보정을 수행하고 난 1.11의 RMS와 함께 다음의 결과를 얻었다 : 교정의 결과로

Undistorted image after calibration

본질적인 매개 변수 (카메라 행렬)를 얻었으므로 cv :: solvePnP를 ​​사용하여 회전 벡터와 변환 벡터를 얻습니다. 이것을 적용하기 위해 왜곡되지 않은 이미지 (픽셀 단위)의 일부 포인트를 표시하고 레퍼런스 시스템에 따라 실제 세계에서 측정했습니다.

예를 들면, 원점은 그렇게하는 1024 이미지의 중심이다

  • 0 점 : ImagePoint (512, 384) [화소] -> ObjectPoint (0,0) [cm] 참고로 this을 사용하여 내가

    지금
    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); 
    

    I에서, 카메라 행렬, 회전 행렬 및 traslation 벡터를 가지고 있도록 :

다음 코드는 도시 픽셀 단위로 위치를 잡으면 어떤 점을 계산할 수 있습니다. > (0.213는 3.391)이 (가 있어야한다 (-

  • 포인트 0 :이 내 매개 변수를 얻기 위해 사용되는 같은 점에 대한 결과를 얻을

    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; 
    

    :이 코드입니다 0,0)) ERROR : 3.69 cm

  • 포인트 1 -> (-68.28, -112.82)을 (그것이 있어야 (-80, -132)) ERROR : 17.49 cm
  • 점 2 - -> (84.48, 1 37.61))ERROR (이 (120, 188이어야 함) : 포인트의 나머지 부분도 오류가 너무 커 보여 49.62 cm

... 나는 더 많은 포인트를 사용했지만 결과는 개선되지 않는다. 내가 어디 잘못 됐는지 모르겠다. 누가 도와 줄 수 있니?

미리 감사드립니다.

답변

0

마침내 나는 왜곡 계수, 즉 나의 교정에 기인한다고 알았다. solvePNP가 완전한 카메라를 가지고 있다고 가정하기 위해 identityMatrix (eye (3))에 cameraMatrix를 설정하고 distCoefficients를 NULL로 설정했습니다. 이 방법을 사용하면 훨씬 낮은 오류를 얻을 수 있습니다. 나는 더 나은 교정을해야 할 것이다.

+0

보정이 잘되고, 이미지를 두 번 효과적으로 왜곡하지 않았을 가능성이 있습니다 (설명에 대한 내 대답 참조). – rob3c

1

solvePNP의 관점에서 이미지를 두 번 효과적으로 왜곡하지 않은 것 같습니다. 이것은 왜곡되지 않은 이미지에서 이미 파생 된 지점 대응과 함께 왜곡 계수를 전달하기 때문입니다.

보정의 실제 카메라 매트릭스를 항복 매트릭스 대신 solvePNP으로 전달해보십시오.하지만 이중 왜곡을 피하기 위해 왜곡 계수에는 여전히 NULL을 전달하십시오.

관련 문제