Eti*_*rot 18 python numpy image python-imaging-library
我有两个从PIL图像转换的Numpy数组(3维uint8).
我想查找第一个图像是否包含第二个图像,如果是,请找出匹配所在的第一个图像内左上角像素的坐标.
有没有办法在Numpy中以足够快的方式完成这个,而不是使用(4!非常慢)纯Python循环?
2D示例:
a = numpy.array([
[0, 1, 2, 3],
[4, 5, 6, 7],
[8, 9, 10, 11]
])
b = numpy.array([
[2, 3],
[6, 7]
])
Run Code Online (Sandbox Code Playgroud)
怎么做这样的事情?
position = a.find(b)
Run Code Online (Sandbox Code Playgroud)
position那会是(0, 2).
PiQ*_*uer 32
我正在使用OpenCV的matchTemplate 功能.有一个很好的python绑定到OpenCV内部使用numpy,所以图像只是numpy数组.例如,假设您有一个100x100像素的BGR文件testimage.bmp.我们在位置(30,30)处拍摄10x10子图像并在原始图像中找到它.
import cv2
import numpy as np
image = cv2.imread("testimage.bmp")
template = image[30:40,30:40,:]
result = cv2.matchTemplate(image,template,cv2.TM_CCOEFF_NORMED)
print np.unravel_index(result.argmax(),result.shape)
Run Code Online (Sandbox Code Playgroud)
输出:
(30, 30)
Run Code Online (Sandbox Code Playgroud)
您可以选择几种算法来将模板与原始模板匹配,cv2.TM_CCOEFF_NORMED只是其中之一.有关详细信息,请参阅文档,有些算法表示匹配为最小值,其他算法表示结果数组中的最大值.警告:OpenCV默认使用BGR通道顺序,所以要小心,例如,当您将加载cv2.imread的图像与从PIL转换为numpy的图像进行比较时.您始终可以使用cv2.cvtColor格式之间的转换.
要查找超过给定阈值的所有匹配项confidence,我会使用沿着此行的某些内容从我的结果数组中提取匹配的坐标:
match_indices = np.arange(result.size)[(result>confidence).flatten()]
np.unravel_index(match_indices,result.shape)
Run Code Online (Sandbox Code Playgroud)
这给出了长度为2的数组元组,每个数组都是匹配的坐标.
这可以使用scipy的correlate2d完成,然后使用argmax在互相关中找到峰值.
这里有一个关于数学和思想的更完整的解释,以及一些例子.
如果你想保持纯粹的Numpy甚至不使用scipy,或者如果图像很大,你可能最好使用基于FFT的方法来进行交叉相关.
编辑:问题特别要求一个纯粹的Numpy解决方案.但是如果你可以使用OpenCV或其他图像处理工具,使用其中一种显然更容易.下面的PiQuer给出了一个这样的例子,如果你可以使用它,我建议你这样做.