如何在 Android 中将 OpenCV 旋转和平移矢量与 OpenGL ES 一起使用?

Posted

技术标签:

【中文标题】如何在 Android 中将 OpenCV 旋转和平移矢量与 OpenGL ES 一起使用?【英文标题】:How to use an OpenCV rotation and translation vector with OpenGL ES in Android? 【发布时间】:2011-04-12 08:10:58 【问题描述】:

我正在开发 android 上的基本增强现实应用程序。到目前为止,我所做的是用 opencv 检测一个正方形,然后使用 cvFindExtrinsicCameraParams2() 我计算了一个旋转和平移向量。为此,我使用了 4 个对象点,它们只是 (0,0,0) 周围正方形的角和图像中正方形的 4 个角。

这为我提供了一个非常好的旋转和平移矩阵。我还用 cvRodrigues2() 计算了旋转矩阵,因为使用它比旋转向量更容易。只要我使用这些在图像中绘制一些点,一切正常。然而,我的下一步是将这些向量和矩阵传递回 java,然后将它们与 OpenGL 一起使用,在 OpenGLView 中绘制一个正方形。正方形应该正好在 OpenGLView 后面显示的图像中的正方形周围。

我的问题是我找不到在 OpenGL 中使用旋转矩阵和平移向量的正确方法。我开始使用与 openCV 函数完全相同的对象点。然后我以我能想到的几乎所有可能的方式应用旋转矩阵和平移向量。遗憾的是,这些方法都没有产生接近我希望的结果。谁能告诉我如何正确使用它们?

到目前为止,我得到的“最接近”的结果是将整个矩阵随机乘以 -1。但大多数情况下,正方形仍然像镜子一样倒转或旋转 180 度。所以我猜这只是一个幸运的命中,但不是正确的方法。

【问题讨论】:

也许你需要transpose 一些东西。 【参考方案1】:

好的,经过更多的测试,我终于设法让它工作了。虽然我不明白......它确实“工作”。对于将来需要这样做的任何人,这是我的解决方案。

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 以来,所有内容都需要转置,因为 OpenGL 需要以列为主的顺序。 (感谢您的评论,我之前已经看过该页面。)此外,y 和 z 旋转角度以及 y 和 z 平移需要乘以 -1。这是我觉得有点奇怪的地方。为什么只有那些而不是 x 值?

这正如我所猜测的那样有效。但是角落并不完全匹配。我猜这是由一些错误的 openGLView 配置引起的。因此,即使我对我的解决方案仍然不是 100% 满意,但我想这就是我问题的答案。

【讨论】:

这是ModelView矩阵还是投影矩阵? 您需要翻转 y 和 z,因为 open GL 沿 -z 轴向下查看并将其原点定义在左下角,openCV 的原点在左上角,z 很可能是正数。跨度> 【参考方案2】:

潘多罗的方法真的很管用!如果有人想知道“如何将旋转向量转换为旋转矩阵”,我就是这样做的。顺便说一句,我在 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;

祝你好运!

【讨论】:

以上是关于如何在 Android 中将 OpenCV 旋转和平移矢量与 OpenGL ES 一起使用?的主要内容,如果未能解决你的问题,请参考以下文章

在 Android 上的 OpenCV 中旋转 VideoCapture

裁剪和旋转图片 OpenCV

将相机预览旋转到人像 Android OpenCV 相机和 Xamarin

OpenCV Python围绕特定点将图像旋转X度

UnsatisfiedLinkError - 在 Android 中旋转相机图像数据(在 OpenCV 中使用,而不仅仅是在屏幕上显示)

OpenCV,dlib 地标旋转