c++ - 使用单应性绕x/y轴旋转

标签 c++ opencv computer-vision transform affinetransform

项目

我正在从事移动设备的纹理跟踪项目。它专门跟踪平面,因此我一直在使用openCV的cv::FindHomography()计算两帧之间的单应性。但是,该函数的运行速度非常慢,并且是我管道中的主要瓶颈。我决定可以对单应性进行初始估计的算法将运行得更快,因为我在帧之间的单应性变化很小。另外,我的异常值百分比很小,因此可选的健壮方法。不幸的是,据我所知,开放式CV不包含采用初始估计的单应性查找器。但是,它确实包含有solvePnP(),它获取场景的原始3d世界坐标,当前2d图像坐标,相机矩阵,失真参数,最重要的是初始估计。我正在尝试用solvePnP替换FindHomography。由于我在整个管道中仅使用2d坐标,而solvePnP要求使用3d坐标,因此我试图从2d-> 3d-> 3d_transform-> 2d_transform移出。现在,如果给出一个很好的初始猜测,但该过程的运行速度比FindHomography()快6倍,但它存在问题。

问题

我的转换方式有问题。我的理论是,由于不需要相机矩阵来查找单应性,因此该过程也不需要,因为我只希望最后包含在单应性中的信息。我还认为,由于最终我抛弃了所有z信息,因此初始化z的方式应该无关紧要。我的流程如下

首先,我给它们所有的初始2d坐标,并将它们的z pos值转换为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旋转矩阵,最后一列是平移 vector 。一个技巧是,单应性(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转换并丢弃column(2)。但是我发现事实并非如此。测试用例向我展示了我的方式的错误,当时他试图制作一个单应图,该点将点绕y轴旋转一些小 Angular 。
//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,some_negative_number。当我从齐次坐标转换回笛卡尔坐标时,我的x和y值都会翻转符号。

就是说,我现在有一个简单得多的问题,我认为它可以解决所有问题。我该如何构造一个将点围绕x和y轴旋转一定 Angular 单应性?

最佳答案

同形异义不是简单的平移或旋转矩阵。目的是将直线映射到直线,而不是将单个点映射到其他点。他们考虑到了透视矩阵来实现这一点,并解释为here

因此,单应性矩阵不易分解,但是here有(复杂的)方法可以做到这一点。这可以帮助您提取旋转和平移。

这应该可以帮助您更好地理解单应性,但是我不熟悉其余的内容。

关于c++ - 使用单应性绕x/y轴旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11616219/

相关文章:

image - 检测图像中某种颜色的矩形

python - 导入错误:没有名为 'torchvision.datasets.mnist' 的模块

opencv - 二值图像方向

c++ - 丢弃指针上的标志是否合法?

C++/Thrift:TThreadedServer::stop() 是线程安全的吗?

c++ 和 openCV 与 windows8 : VideoWriter class not opening

image - 内向360度照片

c++ - 如果我想在构建时将 HLSL 编译为头文件,如何编写头文件,

c++ - TinyXML2 从节点和所有子节点获取文本

android - 相机权限无效