如何在安卓系统中使用OpenCV旋转和平移向量与OpenGL ES相结合?

15
我正在开发一个基本的Android增强现实应用程序。到目前为止,我使用opencv检测到一个正方形,然后使用cvFindExtrinsicCameraParams2()计算了旋转和平移向量。为此,我使用了4个对象点,它们只是围绕(0,0,0)的正方形角和图像中正方形的4个角。这为我提供了一个相当不错的旋转和平移矩阵。我还使用cvRodrigues2()计算了旋转矩阵,因为使用它比旋转向量更容易。只要我使用这些在图像中画一些点,一切都很好。但接下来我的步骤是将这些向量和矩阵传回Java,然后在OpenGL中使用它们绘制OpenGLView中的一个正方形。该正方形应该精确地环绕在OpenGLView背后显示的图像中的正方形周围。 我的问题是我找不到正确的方法在OpenGL中使用旋转矩阵和平移向量。我从与openCV函数使用的完全相同的对象点开始。然后我以几乎任何可能的方式应用旋转矩阵和平移向量。可悲的是,这些方法都没有产生我所希望的结果。有谁能告诉我如何正确使用它们? 到目前为止,“最接近的”结果是当我随机将整个矩阵乘以-1时。但大多数时候,正方形看起来仍然镜像反转或旋转了180度。所以我想这只是幸运的命中,而不是正确的方法。

也许你需要对某些东西进行转置 - genpfault
2个回答

12

经过更多的测试,我终于成功让它工作了。虽然我不理解它...但它确实“工作”。对于将来需要做这件事的任何人,这是我的解决方案。

float rv[3]; // the rotation vector
float rotMat[9]; // rotation matrix
float tv[3]; // translation vector.


rv[1]=-1.0f * rv[1]; rv[2]=-1.0f * rv[2];
//Convert the rotation vector into a matrix here.

//Complete matrix ready to use for OpenGL
float RTMat[] = {rotMat[0], rotMat[3], rotMat[6], 0.0f,
                 rotMat[1], rotMat[4], rotMat[7], 0.0f,
                 rotMat[2], rotMat[5], rotMat[8], 0.0f,
                 tv[0], -tv[1], -tv[2], 1.0f};

正如genpfault在他的评论中所说,由于OpenGL需要列主序,因此需要转置所有内容。(感谢评论,我之前已经看过那个页面了。)此外,y和z旋转角度以及y和z平移需要乘以-1。这是我觉得有点奇怪的地方。为什么只有这些而不是x值呢?

我想这应该可以正常工作。但是角落并不完全匹配。我猜这是由于一些错误的openGLView配置引起的。所以尽管我对我的解决方案还不是100%满意,但我想这就是我的问题的答案。


1
这是模型视图矩阵还是投影矩阵? - Mitch Lindgren
5
由于OpenGL视图沿着负Z轴向下,并将其原点定义在左下角,而OpenCV则将其原点定义在左上角,且Z轴很可能为正,因此您需要交换Y和Z的值。 - Hammer

2

Pandoro的方法真的很有效!如果有人想知道“如何将旋转向量转换为旋转矩阵”,这就是我做的方式。顺便说一句,我在OpenGL 2中使用了这些方法,而不是ES。

// use the rotation vector generated from OpenCV's cvFindExtrinsicCameraParams2() 
float rv[] = {rotation->data.fl[0], rotation->data.fl[1], rotation->data.fl[2] }; 

// use the translation vector generated from OpenCV's cvFindExtrinsicCameraParams2() 
float tv[] = {translation->data.fl[0], translation->data.fl[1], translation->data.fl[2]} ; 

float rm[9];
// rotation matrix
CvMat* rotMat = cvCreateMat (3, 3, CV_32FC1); 

// rotation vectors can be converted to a 3-by-3 rotation matrix
// by calling cvRodrigues2() - Source: O'Reilly Learning OpenCV
cvRodrigues2(rotation, rotMat, NULL);

for(int i=0; i<9; i++){
    rm[i] = rotMat->data.fl[i];
}

rv[1]=-1.0f * rv[1]; rv[2]=-1.0f * rv[2];
//Convert the rotation vector into a matrix here.

//Complete matrix ready to use for OpenGL
float RTMat[] = {rm[0], rm[3], rm[6], 0.0f,
             rm[1], rm[4], rm[7], 0.0f,
             rm[2], rm[5], rm[8], 0.0f,
             tv[0], -tv[1], -tv[2], 1.0f};

祝你好运!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接