我有一個100x200的二維數組,表示爲由黑色(0)和白色(255)單元組成的numpy數組。這是一個位圖文件。然後我有二維形狀(最簡單的把它們想象成字母),它們也是2D黑白單元格。查找矩陣內的匹配子矩陣
我知道我可以天真地遍歷矩陣,但這將是我的代碼的'熱'部分,所以速度是一個問題。在numpy/scipy中有快速的方法嗎?
我簡單看了一下Scipy的相關函數。我對'模糊匹配'不感興趣,只有完全匹配。我也看了一些學術論文,但他們高於我的頭腦。
我有一個100x200的二維數組,表示爲由黑色(0)和白色(255)單元組成的numpy數組。這是一個位圖文件。然後我有二維形狀(最簡單的把它們想象成字母),它們也是2D黑白單元格。查找矩陣內的匹配子矩陣
我知道我可以天真地遍歷矩陣,但這將是我的代碼的'熱'部分,所以速度是一個問題。在numpy/scipy中有快速的方法嗎?
我簡單看了一下Scipy的相關函數。我對'模糊匹配'不感興趣,只有完全匹配。我也看了一些學術論文,但他們高於我的頭腦。
您可以使用相關。您需要將黑色值設置爲-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
)(考慮到如果您使用卷積而非相關性 - flipud
和fliplr
)需要翻轉其中一個數據集的每個軸來加快速度。唯一的修改是將分配C:
c = signal.fftconvolve(a, numpy.fliplr(numpy.flipud(b)), 'valid')
上面的時序上的尺寸比較:
In [5]: timeit c = signal.fftconvolve(a, numpy.fliplr(numpy.flipud(b)), 'valid')
100 loops, best of 3: 6.78 ms per loop
In [6]: timeit c = signal.correlate(a, b, 'valid')
10 loops, best of 3: 151 ms per loop
這裏是您可以使用,或適應,這取決於細節的方法你的要求。它採用ndimage.label
and ndimage.find_objects
:
ndimage.label
此找到所有斑點的陣列中,並將其標籤爲整數的圖像。 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])
例如輸入:
ndimage.find_objects
found blobs
符合您的wanted blobs
代碼1.
和2.
獲取這些斑點的片
標記:
孤立的斑點再次進行測試:(甚至計時)
令人驚歎!這幾乎是我想要做的。我將不得不嘗試兩個答案,並看看什麼效果最好。感謝您花時間發佈此信息! – DaveO
哇,偉大的答案!我有一些測試運行。 – DaveO
剛剛發生的事情,您可以通過將值設置爲0來「不關心」您的子矩陣的區域。這意味着這些值將不會影響交叉關聯。然後'max_peak'值可以被找到爲'max_peak = b [b!= 0] .size'(無論你有沒有0值,這都會起作用)。 –
所以我花了下午編輯我的代碼,並使它工作!假設在array([0,6]),array([1,7]))處發現了2個2x3形狀,意味着左上角是[0,1]和[6,7]。我想要做的是能夠索引形狀中的所有2x3單元格,並將它們賦值爲0,因此在下一個要查找的形狀中,我們將不檢查圖像的部分(根據上面的註釋)。我如何使用correlate/fftconvolve的返回值在不使用循環的情況下索引2d形狀?對位置列表片段進行排序。 – DaveO