我正在使用OpenCV和OpenGL构建Mac OSX AR应用程序。它是基于标记的AR,我正在使用名为ARma的库。这个lib只是使用OpenCV函数将可视输出直接写入图像缓冲区。但是我想使用OpenGL进行可视化输出,所以我创建了一个OpenGL视图,我正在使用内部参数(我使用OpenCV凸轮校准程序获得)初始化GL_PROJECTION矩阵,如下所示:
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);
这就是我在类似项目中看到的情况,我想直到这里一切正确。当检测到标记时,使用cvFindExtrinsicCameraParams2()
(与cv::solvePnP
相同)在ARma库中计算外部参数。所以我得到了旋转向量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;
}
这是将这两个向量转换为我发现here的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视图中显示?