1

I'm building an Mac OSX AR application using OpenCV and OpenGL. It is marker-based AR and I'm using a library called ARma for that. This lib just writes the visual output directly to the image buffer using OpenCV functions. But I want to use OpenGL for visual output so I created an OpenGL View which I'm initializing by using the intrinsic parameters (which I got from using an OpenCV cam calibration program) for the GL_PROJECTION matrix as follows:

cv::Mat intrMat = tracker.camMatrix; // intrinsic 3x3 matrix
// contains:
// 641.68  0.00    319.50   
// 0.00    641.68  212.50   
// 0.00    0.00    1.00

const float fx = intrMat.at<double>(0,0);
const float fy = intrMat.at<double>(1,1);
const float fovy = 2 * atan(0.5f * screenH / fy) * RAD2DEG;
const float aspect = (screenW*fy) / (screenH*fx);
// GL Perspective values: fx=641.68 / fy=641.68 / fovy=41.01 / aspect=1.33

gluPerspective(fovy, aspect, 0.1, 100.0);

This is how I've seen it in similar projects and I think until here everything's correct. When a marker is detected, the extrinsic parameters are calculated in the ARma library using cvFindExtrinsicCameraParams2() (which is the same as cv::solvePnP). So I get the rotation vector rotVec and the translation vector tVec and throw them into the following method to calculate the GL_MODELVIEW matrix:

-(void)calcModelviewMat:(GLfloat *)mvMat fromRotVec:(cv::Mat const &)rotVec transVec:(cv::Mat const &)tVec {
    cv::Mat rotMat;
    cv::Mat rotVecGL = rotVec.clone();

    rotVecGL.at<float>(1) = -rotVecGL.at<float>(1);
    rotVecGL.at<float>(2) = -rotVecGL.at<float>(2);

    cv::Rodrigues(rotVecGL, rotMat);

    // init array with zeros
    memset((void *)mvMat, 0, 16 * sizeof(float));

    // set the rotation
    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            mvMat[i * 4 + j] = rotMat.at<float>(i, j);
        }
    }

    // set the translation
    for (int i = 0; i < 3; i++) {
        float s = (i > 0) ? -1 : 1;
        mvMat[12 + i] = s * tVec.at<float>(i);
    }

    mvMat[15] = 1;
}

This is the way of transforming these two vectors into a GL_MODELVIEW matrix that I've found here. I believe that this is correct but the problem is that the components in the translation vector which I get are much too large (between +/-500 and +/-1500) to get displayed. Here is an example output of the matrix:

0.96    0.05    -0.26   0.00    
0.01    0.97    0.23    0.00    
0.27    -0.22   0.94    0.00    
-72.55  8.47    -479.63 1.00

Why is that so? What kind of units does solvePnP() use in the translation vector and how can I transform them into usable values for displaying in my OpenGL View?

Community
  • 1
  • 1
IsaacKleiner
  • 425
  • 2
  • 13

0 Answers0