我正在使用 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 视图中显示?