如何提高单应性准确度?

时间:2013-09-26 04:59:31

标签: opencv computer-vision

我使用OpenCV的cv::findHomography API来计算两个平面图像的单应矩阵。 匹配的关键点由SIFT提取并由BFMatcher匹配。据我所知,cv:findHomography使用RANSAC迭代找出最佳的四个对应点来获得单应矩阵。 因此,我使用对象边缘的同一矩阵绘制所选择的四对点和计算出的轮廓。 结果如链接:

https://postimg.cc/image/5igwvfrx9/

正如我们所看到的,RANSAC选择的匹配点是正确的,但轮廓显示单应性不准确。

但是这些测试表明,所选择的匹配点和单应性都是正确的:

https://postimg.cc/image/dvjnvtm53/

我的猜测是,如果选定的匹配点太近,像素位置的小误差将导致单应矩阵的显着误差。如果四个点位于图像的角落,那么匹配点的移位4-6个像素仍然具有良好的单应矩阵。 (根据同质坐标,我认为这是合理的,因为近平面的小误差会在很远的地方被放大)

我的问题是:

1.我猜对了吗? 2.由于RANSAC迭代生成了四个匹配点,因此所有关键点的总误差最小。但是如何获得稳定的单应性,至少使轮廓的映射是正确的?理论证明,如果找到平面上的四个对应点,应该计算单应矩阵,但是工程师的工作是否有任何技巧?

3 个答案:

答案 0 :(得分:8)

我认为你是对的,4点的接近度无助于结果的准确性。您观察到的可能是由数字问题引起的:对于这4个点,结果可能局部正确,但在进一步发展时会变得更糟。

然而,RANSAC在这里不会帮助你。原因很简单:RANSAC是一个强大的估计程序,旨在找到许多对应关系中的最佳点对(包括一些错误的对应关系)。然后,在RANSAC的内环中,执行标准的单应性估计。

您可以看到 RANSAC 作为拒绝错误点对应的方式,这会导致错误的结果。

回到你的问题:

你真正需要的是获得更多积分。在您的示例中,您仅使用4点对应关系,这足以估计单应性。 您将通过在目标图片上提供更多匹配来改善结果。然后问题变得过于确定,但OpenCV仍然可以找到最小二乘解决方案。此外,在点对应过程或某些点定位中存在一些错误,RANSAC将能够选择最佳的并且仍然给您可靠的结果。

如果RANSAC导致过度拟合4个点(在您的示例中似乎就是这种情况),请尝试通过增加ransacReprojThreshold参数来放宽约束。 或者,你可以:

  • 使用不同的估算器(如果匹配错误很少,则强健中位数CV_LMEDS是一个不错的选择)
  • 或者在第一步中使用RANSAC进行大量重投影错误(以获得粗略估计)以检测虚假匹配,然后在正确的匹配上使用LMEDS。

答案 1 :(得分:5)

只是为了扩展@sansuiso的回答,我同意:

如果您向RANSAC提供大约100个通信,那么您可能会从cvFindHomography获得超过4个内容。检查status输出参数。 为了获得良好的单应性,你应该有超过4个对应关系(注意4个对应关系总是给你一个单应性),它们很好地分布在图像周围并且不是线性的。实际上,您可以使用最少数量的内点来确定获得的单应性是否足够好。

请注意,RANSAC找到一组一致的点,但是它必须说该集合是最好的(重投影错误)有点受限。有一种类似RANSAC的方法,称为MSAC,它使用稍微不同的误差测量,检查出来。

根据我的经验,坏消息是大多数时候几乎不可能获得100%的精确单应性。如果你有几个相似的框架,你可能会发现它们之间的单应性变化很小。

有一些技巧可以改善这一点。例如,在使用RANSAC获得单应性后,您可以使用它将模型投影到图像中,并查找新的对应关系,这样您就可以找到另一个应该更准确的单应性。

答案 2 :(得分:1)

你的目标有很多对称和相似的元素。正如其他人提到的(你后来澄清),点间距和点数可能是个问题。另一个问题是SIFT并非旨在处理您的案例中存在的重大透视扭曲。尝试通过较小的旋转跟踪您的对象,如前所述,使用最新的单应性重新投影它,使其看起来尽可能接近原始。这也将允许您跳过处理繁重的SIFT并使用像FAST一样轻量级的东西,并使用图像补丁的互相关进行匹配。

你也可能最终明白使用积分是不够的。你必须使用你所拥有的一切,这意味着线条或圆锥曲线。如果单应性变换点Pb = H * Pa,则很容易验证在齐次坐标线Lb = Henv.transposed * La。这直接来自等式La'.Pa = 0 = La'* Hinv * H * Pa = La'* Hinv * Pb = Lb'.Pb 可能的分钟。配置是1行和3点或3行和1点。两条线和两条点不起作用。您也可以使用四行或四个点。当然这意味着您不能再使用openCV功能,必须编写自己的DLT然后进行非线性优化。