该项目
我正在为移动设备开发纹理跟踪项目。它专门跟踪平面,所以我一直在使用 openCV 的 cv::FindHomography() 来计算两帧之间的单应性。然而,该功能运行非常缓慢,是我管道中的主要瓶颈。我决定可以对单应性进行初始估计的算法运行得更快,因为我在帧之间的单应性变化非常小。此外,我的异常值百分比非常小,因此稳健的方法是可选的。不幸的是,据我所知,open CV 不包括进行初步估计的单应性查找器。然而,它确实包含solvePnP(),它获取场景的原始3d 世界坐标、当前2d 图像坐标、相机矩阵、失真参数,最重要的是初始估计。我正在尝试用solvePnP替换FindHomography。由于我在整个管道中仅使用 2d 坐标,并且 solvePnP 要求提供 3d 坐标,因此我试图从 2d->3d->3d_transform->2d_transform 移动。现在,如果给定一个好的初始猜测,但它有问题,该过程的运行速度比 FindHomography() 快 6 倍。
问题
我的转换方式有问题。我的理论是,由于不需要相机矩阵来找到单应性,因此此过程不需要它,因为我只想要最终包含在单应性中的信息。我还假设,由于我最终丢弃了所有 z 信息,因此我如何初始化 z 应该无关紧要。我的流程如下
首先,我将所有初始 2d 坐标转换为 3d,方法是给它们 1 的 az pos。我可以假设我的原始坐标平放在 xy 平面上。然后
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 旋转矩阵,最后一列是平移向量。一个技巧是单应性(2,2) 对应于比例,而 pnp_tran(2) 对应于 z 轴上的移动。鉴于我将 z 坐标初始化为 1,比例为 z_translation + 1。此过程适用于 6 个自由度中的 4 个。Translation_x、translation_x、缩放和围绕 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 > 58 的点 x,y,1 为例。结果将是 x,y,some_negative_number。当我从齐次坐标转换回笛卡尔坐标时,我的 x 和 y 值都会翻转符号。
也就是说,我现在有一个更简单的问题,我认为它可以让我解决所有问题。如何构建一个单应性,将点围绕 x 和 y 轴旋转某个角度?