点模式识别

信息处理 图像处理 计算机视觉 图像配准
2022-01-15 21:26:00

有两个不同大小的点集(为简单起见是二维的)分散在两个不同大小的正方形中,问题是:

1-如何通过大的找到小一个的出现?
2-关于如何对事件进行排名的任何想法,如下图所示?

这是问题的简单演示和所需的解决方案: 在此处输入图像描述


更新 1:
下图显示了正在调查的问题的更现实的视图。 在此处输入图像描述

关于评论,以下属性适用:

  • 点的确切位置可用
  • 点的确切大小可用
    • 大小可以为零(~1)=只有一个点
  • 白色背景上的所有点都是黑色的
  • 没有灰度/抗锯齿效果

这是我对提出的方法进行endolith了一些小改动的实现(我旋转了目标而不是源,因为它更小且旋转更快)。我接受了 'endolith's 的回答,因为我之前也在考虑这个问题。关于 RANSAC 到目前为止我还没有任何经验。此外,RANSAC 的实现需要大量代码。 在此处输入图像描述

4个回答

从计算机视觉的角度来看:基本问题是估计目标点集与大集合中的点子集之间的单应性。在您的情况下,仅旋转,它将是仿射单应性。您应该研究RANSAC方法。它旨在在具有许多异常值的集合中找到匹配项。因此,您拥有两个重要的关键字,单应性RANSAC

OpenCV 提供了计算这些解决方案的工具,但您也可以使用 MATLAB。这是一个使用 OpenCV 的 RANSAC 示例以及另一个完整的实现

一个典型的应用可能是在图片中查找书籍封面。你有一张书封面的照片,还有一张桌子上的书的照片。该方法不是进行模板匹配,而是在每个图像中找到显着角,并比较这些点集。您的问题看起来像这个过程的后半部分 - 在大云中找到点集。RANSAC 旨在稳健地做到这一点。

在此处输入图像描述

我想互相关方法也可以为您工作,因为数据非常干净。问题是,您添加了另一个旋转自由度,并且该方法变得非常慢。

这不是最好的解决方案,但它是一个解决方案。我想学习更好的技术:

如果它们不被旋转或缩放,您可以使用图像的简单互相关。小图像出现在大图像中的任何地方都会有一个明亮的峰值。

您可以使用 FFT 方法加速互相关,但如果您只是将小源图像与大目标图像进行匹配,蛮力乘加法有时(通常不是)更快。

资源:

在此处输入图像描述

目标:

在此处输入图像描述

互相关:

在此处输入图像描述

两个亮点是匹配的位置。

但是您的示例图像中确实有一个旋转参数,因此它本身不会起作用。如果只允许旋转,不允许缩放,那么还是可以使用互相关的,但是需要互相关,旋转源,与整个目标图像互相关,再旋转等等。所有旋转。

请注意,这不一定会找到图像。如果源图像是随机噪声,而目标是随机噪声,则除非您以完全正确的角度进行搜索,否则您将找不到它。在正常情况下,它可能会找到它,但这取决于图像属性和您搜索的角度。

此页面显示了如何完成的示例,但没有给出算法。

总和高于某个阈值的任何偏移量都是匹配的。您可以通过将源图像与其自身相关并将所有总和除以该数字来计算匹配的好坏。完美匹配将是 1.0。

不过,这在计算上会非常繁重,并且可能有更好的方法来匹配点的模式(我想知道)。

使用灰度和 FFT 方法的快速 Python 示例:

from __future__ import division
from pylab import *
import Image
import ImageOps

source_file = 'dots source.png'
target_file = 'dots target.png'

# Load file as grayscale with white dots
target = asarray(ImageOps.invert(Image.open(target_file).convert('L')))

close('all')
figure()
imshow(target)
gray()
show()

source_Image = ImageOps.invert(Image.open(source_file).convert('L'))

for angle in (0, 180):
    source = asarray(source_Image.rotate(angle, expand = True))
    best_match = max(fftconvolve(source[::-1,::-1], source).flat)

    # Cross-correlation using FFT
    d = fftconvolve(source[::-1,::-1], target, mode='same')

    figure()
    imshow(source)


    # This only finds a single peak.  Use something that finds multiple peaks instead:
    peak_x, peak_y = unravel_index(argmax(d),shape(d))

    figure()    
    plot(peak_y, peak_x,'ro')
    imshow(d)

    # Keep track of all these matches:
    print angle, peak_x, peak_y, d[peak_x,peak_y] / best_match

1 色位图

不过,对于 1 色位图,这会快得多。互相关变为:

  • 将源图像放在目标图像上
  • 将源图像移动 1 个像素
    • 按位与所有重叠像素
    • 将所有的 1 相加
  • ...

将灰度图像阈值化为二进制然后这样做可能就足够了。

点云

如果源和目标都是点的模式,更快的方法是找到每个点的中心(与已知点交叉相关一次,然后找到峰值)并将它们存储为一组点,然后匹配源通过旋转、平移和找到两组中最近点之间的最小二乘误差来定位。

如果模式是稀疏二进制,您可以对坐标向量而不是图像进行简单的协方差。取子窗口中左上排序的点坐标,将所有坐标组成一个向量,计算与左上排序的图案点坐标组成的向量的协方差。您也可以使用权重。之后,在大窗口中的某个网格(以及旋转角度的网格)上进行蛮力最近邻搜索最大协方差。通过搜索找到近似坐标后,您可以使用重新加权最小二乘法对其进行细化。

PS Idea 是,您可以使用非零像素的坐标,而不是使用图像。常见的最近邻搜索。您应该使用一些网格对所有搜索空间进行详尽的搜索,包括平移和旋转,即坐标和旋转角度的一些步骤。对于每个坐标/角度,您在窗口中获取像素子集,中心坐标旋转到该角度,获取它们的坐标(相对于中心)并将它们与您寻找的图案的像素坐标进行比较。您应该确保在两个集合中以相同的方式排序点。您找到具有最小差异(最大协方差)的坐标。在粗略匹配之后,您可以通过一些优化方法找到精确匹配。对不起,我不能比这更简单。

我很惊讶为什么没有人提到广义霍夫变换家族的方法。他们直接解决了这个特殊问题。

这是我的建议:

  1. 获取模板并创建R-table,索引模板的边缘。我选择的边缘如下:

在此处输入图像描述

  1. 使用广义霍夫变换的默认OpenCV 实现来获得: 在此处输入图像描述

标记匹配位置的位置。即使边缘减少到一个点,相同的方法仍然有效,因为该方法不需要图像强度。

此外,对于 Hough 方案来说,处理旋转是非常自然的。事实上,对于二维情况,它只是累加器中的一个附加维度。如果您想详细了解如何使其真正高效,M. Ulrich 在他的论文中解释了很多技巧。