【问题标题】:Finding shapes using Modified Hausdorff Distance使用修正的豪斯多夫距离寻找形状
【发布时间】:2017-10-16 17:53:56
【问题描述】:

我有 2 张图片,它们的形状相同,但排列在不同的位置。我想正确匹配这些图像。


执行的步骤...

  1. 从源图像获取轮廓。
  2. 从目标图像中获取轮廓。
  3. 使用修改后的豪斯多夫距离比较从源到目标的轮廓。
  4. 获取最小值作为匹配项。

    def modified_hausdorff(A,B): D = cdist(A,B) #euclidean distance fhd = np.mean(np.min(D,axis=0)) rhd = np.mean(np.min(D,axis=1)) return max(fhd,rhd)

源图像。

目标图片。

【问题讨论】:

  • 究竟是什么问题?
  • 问题是修改后的豪斯多夫距离使用位置来计算两个形状之间的相似度。因为它计算形状 A 与形状 B 的点集之间的距离。因此使其具有平移不变性。我需要一些东西来制作这个 RSTInvariant。
  • 我在豪斯多夫距离方面遇到了类似的问题。为了处理翻译,我翻译了所有要点;模板和框架,回到原点。关于旋转,我旋转了框架点以匹配模板点的角度。 Scale,image pyramids 是你的朋友
  • 嗯,如果您添加了您正在寻找旋转、缩放和平移不变解决方案的事实,那将会更有帮助。
  • 谢谢@eshirima。你能分享你的代码或sn-p吗?那真的很有帮助。下次我会更加小心地提供问题的完整细节。

标签: python opencv image-processing computer-vision pattern-recognition


【解决方案1】:

这是一个双向任务。

前进方向


1.翻译

对于每个轮廓,计算其moment。然后对于该轮廓中的每个点,将其转换为大约时刻,即contour.point[i] = contour.point[i] - contour.moment[i]。这会将所有轮廓点移动到原点。

PS:您需要跟踪每个轮廓的产生时刻,因为它将在下一部分中使用

2。轮换

使用新翻译的点,计算它们的rotated rect。这将为您提供旋转角度。根据这个角度,您需要计算要旋转此轮廓的新角度; this answer 会很有帮助。

获得新角度后,计算rotation matrix。请记住,您的中心将是原点,即(0, 0)。在计算旋转矩阵时,我没有考虑缩放(这就是金字塔发挥作用的地方),因此我通过了 1。

PS:您需要跟踪每个轮廓生成的矩阵,因为它将在下一节中使用

使用此矩阵,您可以继续并通过它旋转轮廓中的每个点,如图所示here*

所有这些都完成后,您可以继续计算 Hausdorff 距离并找到通过您设定的阈值的轮廓。


后向

必须撤消第一部分中完成的所有操作,以便我们将有效轮廓绘制到我们的相机源上。


1.轮换

回想一下,每个检测到的轮廓都会产生一个旋转矩阵。您想要撤消有效轮廓的旋转。只需执行相同的轮换,但使用 inverse matrix

For each valid contour and corresponding matrix
inverse_matrix = matrix[i].inv(cv2.DECOMP_SVD)
Use * to rotate the points but with inverse_matrix as parameter

PS:在计算逆时,如果生成的矩阵不是一个平方,它会失败。 cv2.DECOMP_SVD 将产生一个逆矩阵,即使原始矩阵是非正方形的。

2。翻译

将有效轮廓的点向后旋转,您只需撤消之前执行的平移。无需减去,只需将时刻添加到每个点。

您现在可以继续将这些轮廓绘制到您的相机源中。


缩放


这是图像金字塔发挥作用的时候。

您所要做的就是将模板图​​像的大小调整为固定大小/比例,直至达到您想要的次数(称为图层)。找到的教程here 很好地解释了如何在 OpenCV 中执行此操作。

不用说,您选择调整图像大小的值和层数将并且确实对您的程序的健壮性起着重要作用。


把它们放在一起

模板图像操作

Create a pyramid consisting of n layers
For each layer in n
    Find contours
    Translate the contour points
    Rotate the contour points

这个操作应该只执行一次并且只存储旋转点的结果。

相机供稿操作

假设

让模板图像在每一层的旋转轮廓存储在templ_contours中。所以如果我说templ_contours[0],这将给我金字塔级别 0 的旋转轮廓。

让图像的平移、旋转轮廓和矩分别存储在transControtContmoment中。

image_contours = Find Contours
for each contour detected in image
    moment = calculate moment

for each point in image_contours
    transCont.thisPoint = forward_translate(image_contours.thisPoint)
    rotCont.thisPoint = forward_rotate(transCont.thisPoint)

for each contour_layer in templ_contours
    for each contour in rotCont
        calculate Hausdorff Distance
        valid_contours = contours_passing_distance_threshold

for each point in valid_contours
    valid_point = backward_rotate(valid_point)

for each point in valid_contours
    valid_point = backward_translate(valid_point)

drawContours(valid_contours, image)

一开始可能会有点令人困惑,尤其是在跟踪每个轮廓各自的矩和旋转矩阵时,但一旦你了解了发生了什么,它确实是一个非常容易实现的算法。

【讨论】:

  • 非常感谢。我一定会试一试的。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-15
  • 2019-09-28
  • 2020-03-10
  • 1970-01-01
  • 2017-11-06
相关资源
最近更新 更多