如何提高单应性矩阵的准确度?

18
我使用了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迭代生成的,所有关键点的整体误差是最小的。但如何获得稳定的单应矩阵,至少使轮廓映射正确?该理论证明如果找到一个平面上的四个对应点,则应计算单应矩阵,但在工程工作中是否有什么技巧?

你找到任何解决方案或解释了吗?我也遇到了同样的问题。 - MMH
@binzhang 这些图片已经不在线上了。你能否重新上传到imgur.com并提供链接?这将有助于原问题的可读性。提前感谢您的帮助。 - Basj
3个回答

11

我认为你是正确的,而且四个点的邻近性并不利于结果的准确性。你所观察到的可能是由于数值问题导致的:这些4个点的结果可能在局部上是正确的,但随着进一步进行,结果变得更差。

然而,RANSAC在这里没有帮助。原因很简单:RANSAC是一种鲁棒估计过程,旨在从许多对应关系(包括一些错误的对应)中找到最佳的点对。然后,在RANSAC的内部循环中执行标准的单应性估计。

你可以将RANSAC看作是一种排除错误点对应关系的方法,这将导致不良结果。

回到你的问题:

你实际上需要更多的点。在你的示例中,你只使用了4个点对应关系,这恰好足以估计一个单应性。通过提供目标图像中遍布的更多匹配项,你将改善你的结果。然后问题就变成了超定的,但是OpenCV仍然可以找到最小二乘解。此外,如果点对应或某些点定位存在错误,则RANSAC将能够选择最佳点并仍然给出可靠的结果。

如果RANSAC在某些4个点上过拟合(就像在你的示例中似乎是这样的),请尝试通过增加ransacReprojThreshold参数来放宽约束。 或者,你可以选择以下任一选项:

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

感谢您的反馈。也许我没有描述得足够清楚。实际上,我已经提供了大约数百个匹配点给cvFindHomography。我已经深入研究了OpenCV中的RANSAC源代码,我所绘制的四个点是RANSAC过程中“认为”最佳结果的点。(这是一种迭代过程,每次选择四对点)不幸的是,尽管这些点对看起来是匹配的,但并不总是能产生良好的单应矩阵。 - binzhang
2
我的实验表明:如果提供的匹配关键点分布在矩形中心,那么如果我使用计算出的单应性矩阵来转换矩形的角点,当关键点位置稍有偏移时误差会很大。如果挑选的匹配关键点位置分布在矩形的四个角落中,那么如果我使用单应性矩阵来转换矩形内部的点,结果是正确的。所以我的问题是,如果我只能获取到靠近矩形中心的匹配关键点,如何提高性能? - binzhang
1
这很明显。中心匹配会导致更大的误差。尝试获取一些角落匹配。改进你的关键点候选者。 - SolessChong
关于你的第二个方法——首先使用CV_RANSAC,然后再使用CV_LMEDS的问题。该技术是使用findHomographymask输出来修剪匹配列表,然后再次运行findHomography,这次使用CV_LMEDS吗? - Victor Odouard
@VictorOdouard 我认为这就是想法。 - JohannB

7

为了延续@sansuiso的答案,我同意他的观点:

如果您向RANSAC提供大约100个对应关系,则可能从cvFindHomography获得4个以上的内点。请检查status输出参数。 要获得良好的单应性矩阵,您应该拥有比4个更多的对应关系(请注意,4个对应关系始终会给您一个单应性矩阵),这些对应关系在图像周围分布良好且不是线性的。实际上,您可以使用最少数量的内点来确定所获得的单应性矩阵是否足够好。

请注意,RANSAC找到一组一致的点,但它必须表明该集合是最佳集合的方式(重投影误差)有些受限制。有一种类似于RANSAC的方法,称为MSAC,它使用略有不同的误差测量,请查看它。

不幸的消息是,在我的经验中,大多数情况下很难获得100%精确的单应性矩阵。如果您有几个相似的帧,则可能会看到单应性矩阵在它们之间略微变化。

有一些技巧可以改善这种情况。例如,在使用RANSAC获得单应性矩阵后,您可以使用它将模型投影到图像中,并查找新的对应关系,以便找到另一个更精确的单应性矩阵。


1
你的目标具有许多对称和相似元素。正如其他人提到的(并且你后来澄清了),点间距和点数可能会成为问题。另一个问题是,SIFT并不适用于处理在你的情况下存在的重要透视失真。尝试通过较小的旋转跟踪你的对象,并像之前提到的那样重新投影它,以使其尽可能接近原始状态。这也将使你能够跳过处理繁重的SIFT,并使用像FAST这样轻量级的东西来进行图像补丁的交叉相关匹配。
你还可能最终明白,仅使用点是不够的。你必须使用所有你拥有的东西,这意味着线或圆锥曲线。如果一个单应性变换将点Pb = H * Pa 转换,很容易验证在齐次坐标中线Lb = Henv.transposed * La。这直接来自方程La'.Pa = 0 = La' * Hinv * H * Pa = La' * Hinv * Pb = Lb'.Pb 可能的最小配置是1条线和三个点或三条线和一个点。两条线和两个点不起作用。你也可以使用四条线或四个点。当然,这意味着你不能再使用OpenCV函数,而必须编写自己的DLT,然后进行非线性优化。

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