在矩阵内查找匹配的子矩阵

时间:2012-06-18 06:52:50

标签: python numpy

我有一个100x200的2D数组,表示为由黑色(0)和白色(255)单元组成的numpy数组。它是一个位图文件。然后,我有2D形状(最容易将它们视为字母),它们也是2D黑白细胞。

我知道我可以天真地遍历矩阵,但这将成为我代码的“热门”部分,因此速度是一个问题。在numpy / scipy中有没有快速的方法来执行此操作?

我简要地看了一下Scipy的相关功能。我对'模糊匹配'不感兴趣,只对完全匹配感兴趣。我也看了一些学术论文,但它们都在我的头上。

2 个答案:

答案 0 :(得分:9)

可以使用相关性。您需要将黑色值设置为-1,将白色值设置为1(反之亦然),以便您知道相关峰值的值,并且只会出现正确的字母。

以下代码执行我认为您想要的内容。

import numpy
from scipy import signal

# Set up the inputs
a = numpy.random.randn(100, 200)
a[a<0] = 0
a[a>0] = 255

b = numpy.random.randn(20, 20)
b[b<0] = 0
b[b>0] = 255

# put b somewhere in a
a[37:37+b.shape[0], 84:84+b.shape[1]] = b

# Now the actual solution...

# Set the black values to -1
a[a==0] = -1
b[b==0] = -1

# and the white values to 1
a[a==255] = 1
b[b==255] = 1

max_peak = numpy.prod(b.shape)

# c will contain max_peak where the overlap is perfect
c = signal.correlate(a, b, 'valid')

overlaps = numpy.where(c == max_peak)

print overlaps

这将输出(array([37]), array([84])),即代码中设置的偏移的位置。

你可能会发现,如果你的字母大小乘以你的大数组大小大于Nlog(N),其中N是你正在搜索的大数组的相应大小(对于每个维度),那么你通过使用基于fft的算法(例如scipy.signal.fftconvolve)可能会加快速度(请记住,如果使用卷积而不是相关性,则需要翻转其中一个数据集的每个轴 - {{ 1}}和flipud)。唯一的修改是分配c:

fliplr

比较上述尺寸的时间:

c = signal.fftconvolve(a, numpy.fliplr(numpy.flipud(b)), 'valid')

答案 1 :(得分:8)

根据您的要求的详细信息,您可以使用或修改这种方法。它使用ndimage.label and ndimage.find_objects:

  1. 使用ndimage.label标记图像,这会找到数组中的所有blob并将它们标记为整数。
  2. 使用ndimage.find_objects
  3. 获取这些blob的切片
  4. 然后使用set intersection查看found blobs是否与您的wanted blobs
  5. 相对应

    1.2.的代码:

    import scipy
    from scipy import ndimage
    import matplotlib.pyplot as plt
    
    #flatten to ensure greyscale.
    im = scipy.misc.imread('letters.png',flatten=1)
    objects, number_of_objects = ndimage.label(im)
    letters = ndimage.find_objects(objects)
    
    #to save the images for illustrative purposes only:
    plt.imsave('ob.png',objects)
    for i,j in enumerate(letters):
        plt.imsave('ob'+str(i)+'.png',objects[j])
    

    示例输入:

    enter image description here

    标记:

    enter image description here

    隔离斑点进行测试:

    enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here