如何在OpenCV中使用矩阵R和T(外参矩阵)来转换图像?

6

我有一个旋转平移矩阵 [R T](3x4)。

在OpenCV中,是否有执行由[R T]描述的旋转平移的功能?


是的,但您还需要自己的内在参数,您有这些吗?您还需要对图像的初始位置进行一些假设,但通常这不是问题。 - Hammer
是的,我有内参。 - Carlo Pane
1
下一个问题是,你的R和T矩阵与什么相关?相机的初始位置?世界空间中的某个位置?等等。 - Hammer
1
世界空间中的一个位置,具体来说是地面。 - Carlo Pane
1
好的,这应该是最后一个问题了。您知道相机现在的位置,即R和T。如果您想将地板图像从一个透视图转换为另一个透视图,则需要知道拍摄第一张图像时相机的R和T。然后,您可以计算它们之间的R和T等。您知道拍摄图像时的R和T吗? - Hammer
是的,我在每个角度都了解 R 和 T。 - Carlo Pane
1个回答

11
很多人对这个问题的解决方案都存在隐含假设。我将试图快速概述一下我如何思考这个问题(过去我不得不经常思考它)。在两个图像之间进行变形是一个二维过程,需要使用一个称为单应性矩阵的3x3矩阵来完成。你手头有的是一个定义了三维变换的3x4矩阵。你可以将图像视为三维空间中的平面,并在两者之间进行转换。关键是要确定图像平面在世界空间中的初始位置。然后,你可以通过相机内参矩阵将其位置进行变换,并投影到新的图像平面上。
第一步是确定你的初始图像在世界空间中的位置。请注意,这不必与你的初始R和T矩阵指定的位置相同。那些是在世界坐标系下的,我们讨论的是由该世界创建的图像,所有图像中的对象都被压缩成一个平面。最简单的决策是将图像设置在z轴上的固定位移处,没有旋转。从此以后,我将假设没有旋转。如果你想看到一般情况,我可以提供,但稍微复杂一些。
接下来,在三维空间中定义两个图像之间的变换。由于你已经有了相对于同一原点的两个变换,从[A]到[B]的变换与从[A]到你的原点的变换相同,然后是从原点到[B]的变换。你可以通过以下方式获得它:
transform = [B]*inverse([A])

概念上,您需要做的是将第一张图像的像素投影到三维空间中的几何解释中,然后通过上述变换在三维空间中转换这些像素,最后使用相机矩阵将它们投影回一个新的二维图像。这些步骤需要组合成一个单独的3x3矩阵。

cv::Matx33f convert_3x4_to_3x3(cv::Matx34f pose, cv::Matx33f camera_mat, float zpos)
{   
//converted condenses the 3x4 matrix which transforms a point in world space 
//to a 3x3 matrix which transforms a point in world space.  Instead of 
//multiplying pose by a 4x1 3d homogeneous vector, by specifying that the
//incoming 3d vectors will ALWAYS have a z coordinate of zpos, one can instead 
//multiply converted by a homogeneous 2d vector and get the same output for x and y.

cv::Matx33f converted(pose(0,0),pose(0,1),pose(0,2)*zpos+pose(0,3),
                      pose(1,0),pose(1,1),pose(1,2)*zpos+pose(1,3),
                      pose(2,0),pose(2,1),pose(2,2)*zpos+pose(2,3));

//This matrix will take a homogeneous 2d coordinate and "projects" it onto a 
//flat plane at zpos.  The x and y components of the incoming homogeneous 2d 
//coordinate will be correct, the z component is dropped.  
cv::Matx33f projected(1,0,0,
                      0,1,0,
                      0,0,zpos);
projected = projected*camera_mat.inv();

//now we have the pieces.  A matrix which can take an incoming 2d point, and 
//convert it into a pseudo 3d point (x and y correspond to 3d, z is unused) 
//and a matrix which can take our pseudo 3d point and transform it correctly.  
//Now we just need to turn our transformed pseudo 3d point back into a 2d point 
//in our new image, to do that simply multiply by the camera matrix.

return camera_mat*converted*projected;
}

这可能比你想要的答案更复杂,但我希望它能让你了解你所问的问题。这可能非常令人困惑,我快速地浏览了一些部分,如有需要,请随时要求澄清。如果您需要不假定初始图像出现旋转的解决方案,请告诉我,我只是不想使它比必要的更加复杂。


我一直在尝试按照您的答案去做类似的事情,也许您可以帮忙。您函数的输入是pose和camera_mat?这些具体是什么?Carlo提到他有两个相机的内部和外部矩阵(我也有)。您如何将View 1中的(x,y)点映射到View 2中对应的(x,y)点?您只需将从函数返回的3x3矩阵乘以View 1中的(x,y)点即可吗? - Luke Zammit
1
@LukeZammit 要将点转换,您需要将您的点(x,y)转换为3向量[x,y,1],然后乘以3x3矩阵。Camera_mat是相机内部参数矩阵。您可以在网上找到有关内部参数矩阵工作原理的解释,但从概念上讲,它代表相机的焦距。姿态是您想要在“三维空间”中应用于图像的变换。如果您仍有问题,请告诉我。 - Hammer

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