1

我正在使用 OpenCV 和 OpenGL 构建一个 Mac OSX AR 应用程序。它是基于标记的 AR,我为此使用了一个名为ARma的库。这个库只是使用 OpenCV 函数将视觉输出直接写入图像缓冲区。但是我想使用 OpenGL 进行视觉输出,所以我创建了一个 OpenGL 视图,我通过使用 GL_PROJECTION 矩阵的内部参数(我从使用 OpenCV cam 校准程序获得)来初始化它,如下所示:

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

这就是我在类似项目中看到的方式,我认为直到这里一切都是正确的。当检测到标记时,在 ARma 库中使用 cvFindExtrinsicCameraParams2()(与 相同cv::solvePnP)计算外部参数。所以我得到了旋转向量rotVec和平移向量tVec,然后把它们扔到下面的方法中来计算GL_MODELVIEW矩阵:

-(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;
}

这是将这两个向量转换为我在这里找到的 GL_MODELVIEW 矩阵的方法。我相信这是正确的,但问题是我得到的平移向量中的分量太大(在 +/-500 和 +/-1500 之间)无法显示。这是矩阵的示例输出:

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

为什么呢?solvePnP() 在平移向量中使用什么样的单位,如何将它们转换为可用值以在我的 OpenGL 视图中显示?

4

0 回答 0