Camera pose estimation (OpenCV PnP)

后端 未结 3 1303
小鲜肉
小鲜肉 2020-12-05 01:30

I am trying to get a global pose estimate from an image of four fiducials with known global positions using my webcam.

I have checked many stackexchange questions an

相关标签:
3条回答
  • 2020-12-05 01:48

    I solved this a while ago, apologies for the year delay.

    In the python OpenCV 2.1 I was using, and the newer version 3.0.0-dev, I have verified that to get the pose of the camera in the global frame you must:

    _, rVec, tVec = cv2.solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs)
    Rt = cv2.Rodrigues(rvec)
    R = Rt.transpose()
    pos = -R * tVec
    

    Now pos is the position of the camera expressed in the global frame (the same frame the objectPoints are expressed in). R is an attitude matrix DCM which is a good form to store the attitude in. If you require Euler angles then you can convert the DCM to Euler angles given an XYZ rotation sequence using:

    roll = atan2(-R[2][1], R[2][2])
    pitch = asin(R[2][0])
    yaw = atan2(-R[1][0], R[0][0])
    
    0 讨论(0)
  • 2020-12-05 01:49

    position of camera would be {- transpose( r ) * t } . That's it.

    And you have done everything correctly except , cv::solvePnp gives (4 x 1) vector for translation if I remember right , you would have to divide x , y , z with the w co-ordinate.

    0 讨论(0)
  • 2020-12-05 02:05

    If you mean with global pose a 4x4 camera pose matrix, which can be used in OpenGL, I do it this way

    CvMat* ToOpenGLCos( const CvMat* tVec, const CvMat* rVec )
    {
        //** flip COS 180 degree around x-axis **//
    
        // Rodrigues to rotation matrix
        CvMat* extRotAsMatrix = cvCreateMat(3,3,CV_32FC1);
        cvRodrigues2(rVec,extRotAsMatrix);
    
        // Simply merge rotation matrix and translation vector to 4x4 matrix 
        CvMat* world2CameraTransformation = CreateTransformationMatrixH(tVec,
        extRotAsMatrix );
    
        // Create correction rotation matrix (180 deg x-axis)
        CvMat* correctionMatrix = cvCreateMat(4,4,CV_32FC1);
        /* 1.00000   0.00000   0.00000   0.00000
           0.00000  -1.00000  -0.00000   0.00000
           0.00000   0.00000  -1.00000   0.00000
           0.00000   0.00000   0.00000   1.00000 */
        cvmSet(correctionMatrix,0,0,1.0); cvmSet(correctionMatrix,0,1,0.0);
        ... 
    
        // Flip it
        CvMat* world2CameraTransformationOpenGL = cvCreateMat(4,4,CV_32FC1);
        cvMatMul(correctionMatrix,world2CameraTransformation,   world2CameraTransformationOpenGL);
    
        CvMat* camera2WorldTransformationOpenGL = cvCreateMat(4,4,CV_32FC1);
        cvInv(world2CameraTransformationOpenGL,camera2WorldTransformationOpenGL,
        CV_LU );
    
        cvReleaseMat( &world2CameraTransformationOpenGL );
        ...
    
        return camera2WorldTransformationOpenGL;
    }
    

    I think flipping the coordinate system is necessary, because OpenCV and OpenGL/VTK/etc. use different coordinate systems, as illustrated in this picture OpenGL and OpenCV Coordinate Systems

    Well, it works this way but somebody might have a better explanation.

    0 讨论(0)
提交回复
热议问题