使用单应性矩阵在x/y轴周围旋转

3

项目

我正在为移动设备开发一个纹理跟踪项目。它专门跟踪平面表面,因此我一直在使用openCV的cv::FindHomography()函数来计算两个帧之间的单应性矩阵。然而,该函数运行非常缓慢,是我的流水线中的主要瓶颈。我决定使用一种可以接受单应性矩阵初始估计的算法,因为我的帧之间的单应性变化非常小。此外,我的异常值百分比非常小,因此鲁棒方法是可选的。不幸的是,据我所知,openCV没有包括可以接受初始估计的单应性矩阵查找器。但是,它确实包括solvePnP()函数,该函数需要场景的原始3D世界坐标、当前2D图像坐标、相机矩阵、畸变参数以及最重要的是一个初始估计。我正在尝试用solvePnP替换FindHomography。由于我在整个流水线中仅使用2D坐标,而solvePnP要求3D坐标,因此我正在尝试从2D->3D->3D_transform->2D_transform转换。如果给出良好的初始猜测,目前该过程比FindHomography()快6倍,但它存在问题。

问题

我在转换过程中遇到了问题。我的理论是,由于不需要相机矩阵来查找单应性,因此在这个过程中也不应该需要相机矩阵,因为最终我只需要单应性中包含的信息。我还假设,由于最终我会丢弃所有的z信息,所以如何初始化z并不重要。我的过程如下:

首先,我通过将它们的z位置设置为1来将所有初始2D坐标转换为3D坐标。我可以假设我的原始坐标位于x-y平面上。然后

cv::Mat rot_mat; //3x3 rotation matrix
cv::Mat pnp_rot; //3x1 rotation vector
cv::Mat pnp_tran; //3x1 translation vector
cv::Matx33f camera_matrix(1,0,0,
                          0,1,0,
                          0,0,1);
cv::Matx41f dist(0,0,0,0);
cv::solvePnP(original_cord, current_cord, camera_matrix, dist, pnp_rot, pnp_tran,true);

//Rodrigues converts from a rotation vector to a rotation matrix
cv::Rodrigues(pnp_rot, rot_mat);
cv::Matx33f homography(rot_mat(0,0),rot_mat(0,1),pnp_tran(0),
                       rot_mat(1,0),rot_mat(1,1),pnp_tran(1),
                       rot_mat(2,0),rot_mat(2,1),pnp_tran(2)+1);

这里的同态转换很简单。同态矩阵的前两列来自3x3旋转矩阵,最后一列是平移向量。唯一的技巧是homography(2,2)对应于比例,而pnp_tran(2)对应于z轴上的运动。考虑到我将我的z坐标初始化为1,因此比例是z_translation + 1。这个过程对于6个自由度中的4个完美地工作。Translation_x、translation_x、scale和绕z轴的旋转都可以工作。然而,绕x和y轴的旋转显示出了显著的误差。我认为这是由于将我的点初始化为z = 1,但我不知道如何修复它。

问题

我使用伪造的相机矩阵和初始z坐标来通过solvePnP获得良好结果的假设是否正确?如果是这样,我应该如何设置我的相机矩阵和z坐标以使x和y旋转起作用?此外,如果有人知道在仅使用2d的情况下采用初始猜测并查找同态变换算法的位置,或者有关编写自己算法的技术信息,那将非常有帮助。一旦我解决了这个问题,我很可能会朝着这个方向前进。

更新

我建立了一个测试程序,它接受一个单应性矩阵,从该矩阵生成一组共面点,然后通过solvePnP将这些点运行以恢复指定的单应性矩阵。在这个过程中,我意识到我基本上误解了单应性矩阵的构造方式的某些部分。我一直认为单应性矩阵是按照以下方式构造的。
hom(0,2) = x translation
hom(1,2) = y translation
hom(2,2) = scale, I can divide the entire matrix by this to normalize

我假设前两列是一个3x3旋转矩阵的前两列。这基本上相当于取一个3x4变换并丢弃列(2)。然而,我发现这不是真的。试图制作绕y轴旋转一些小角度的单应性时,测试用例向我展示了我的错误。

//rotate by .0175 rad about y axis
rot_mat = (1,0,.0174,
           0,1,0,
      -.0174,0,1);
//my conversion method to make this a homography gives

homography = (1,0,0,
              0,1,0,
         -.0174,0,1);

上述的单应性根本不起作用。以点 x,y,1 为例,其中 x > 58。结果将是 x,y,某个负数。当我将齐次坐标转换回笛卡尔坐标时,我的 x 和 y 值都会翻转符号。

所有这些都是为了说明,我现在有一个更简单的问题,我认为它可以让我解决所有问题。如何构造一个单应性,围绕 x 轴和 y 轴旋转点的某个角度?


1
我对这个话题不是很了解,但你问题中的某些内容引起了我的注意。你说:“我可以假设我的原始坐标在x-y平面上”,然而你却设置z=1,这不是“x-y平面”。为什么你要使用z=1而不是z=0呢? - yms
@yms:是的,你说得对,为了忽略Z值并将所有转换保持在x-y平面上,Z应该是0,而不是1。 - diverscuba23
@diverscuba23 你是来自古巴的吗? :) - yms
我最初也有同样的想法,将z设为0,但是对于这些起始坐标,solvePnP返回nan。我猜测这是因为solvePnP假定投影的焦点位于z=0处,这意味着任何位于该点的物体看起来都是无限大的,并且由于小位移引起的变化是未定义的。 - Hammer
@yms:不,来自密歇根州。 - diverscuba23
1个回答

3

同态矩阵不是简单的平移或旋转矩阵。其目的是将直线映射到直线,而不是将单个点映射到其他点。为了实现这一点,同态矩阵考虑透视矩阵,具体解释请参见 此处

因此,同态矩阵不能轻松分解,但有(复杂的)方法可以做到,详见 此处。这可能有助于您从中提取出旋转和平移。

这应该能帮助您更好地理解同态矩阵,但我不熟悉其中的其余部分。


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