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

时间:2012-10-27 13:23:40

标签: opencv camera-calibration projective-geometry

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

opencv中是否有一个函数执行[R T]所描述的旋转转换?

1 个答案:

答案 0 :(得分:9)

我认为这个问题的很多解决方案都是隐藏的假设。我将尽力向您简要介绍一下我对这个问题的看法(过去我不得不考虑很多)。两个图像之间的翘曲是由称为单应性的3×3矩阵完成的二维过程。你所拥有的是一个3x4矩阵,它定义了3维的变换。您可以通过将图像视为三维空间中的平面来在两者之间进行转换。然后,诀窍是决定图像平面的世界空间中的初始位置。然后,您可以使用相机内在矩阵转换其位置并将其投影到新的图像平面上。

第一步是确定初始图像在世界空间中的位置,请注意,这不必与初始R和T矩阵指定的相同。那些是在世界坐标中,我们谈论的是由该世界创建的图像,图像中的所有对象都被平坦化为一个平面。这里最简单的决定是将图像设置在z轴上的固定位移处,而不是旋转。从这一点开始,我将假设没有轮换。如果你想看到一般情况我可以提供它,但它稍微复杂一些。

接下来,在3d空间中定义两个图像之间的变换。由于您对同一原点进行了两次变换,因此从[A]到[B]的变换与从[A]到原点的变换相同,然后是从原点到[B]的变换。你可以通过

获得
transform = [B]*inverse([A])

现在从概念上讲,您需要做的是拍摄第一张图像,将其像素投影到3d空间中图像的几何解释,然后通过上面的变换将这些像素转换为3d空间中的像素,然后将它们投影回新的带有相机矩阵的2d图像。这些步骤需要组合成一个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;
}

这可能是一个比你想要的更复杂的答案,但我希望它能让你知道你在问什么。这可能非常令人困惑,我很快就对它的某些部分进行了釉面处理,请随时要求澄清。如果你需要解决方案工作而不假设初始图像没有旋转而让我知道,我只是不想让它变得比它需要的更复杂。