使用 scikit-image 搜索所有模板
Search for all templates using scikit-image
我正在尝试遵循 scikit-image 中有关模板匹配的教程(检查它 here).
仅使用这个例子,我想在图像中找到所有匹配的硬币(最大值),而不仅仅是给出最高分的这一个。我在考虑使用:
maxima = argrelextrema(result, np.greater)
但问题是它也发现了非常小的局部最大值,这只是一个噪音。有没有办法筛选 numpy 数组并找到最强的最大值?谢谢!
我一直在挖掘并找到了一些解决方案,但不幸的是我不确定我是否知道脚本中到底做了什么。我稍微修改了脚本 here:
neighborhood_size = 20 #how many pixels
threshold = 0.01 #threshold of maxima?
data_max = filters.maximum_filter(result, neighborhood_size)
maxima = (result == data_max)
data_min = filters.minimum_filter(result, neighborhood_size)
diff = ((data_max - data_min) > threshold)
maxima[diff == 0] = 0
x_image,y_image = [], []
temp_size = coin.shape[0]
labeled, num_objects = ndimage.label(maxima)
slices = ndimage.find_objects(labeled)
x, y = [], []
for dy,dx in slices:
x_center = (dx.start + dx.stop - 1)/2
x.append(x_center)
y_center = (dy.start + dy.stop - 1)/2
y.append(y_center)
fig, (raw,found) = plt.subplots(1,2)
raw.imshow(image,cmap=plt.cm.gray)
raw.set_axis_off()
found.imshow(result)
found.autoscale(False)
found.set_axis_off()
plt.plot(x,y, 'ro')
plt.show()
并这样做:
我还意识到,与原始图像相比,找到的峰的坐标发生了偏移。我认为差异来自模板大小。当我发现更多时,我会更新。
编辑:通过稍微修改代码,我还能够在输入图像上找到位置:
x_image_center = (dx.start + dx.stop - 1 + temp_size) / 2
x_image.append(x_image_center)
y_image_center = (dy.start + dy.stop - 1 + temp_size) / 2
y_image.append(y_image_center)
找到 documentation suggests "...you should use a proper peak-finding function." The easiest of these is probably peak_local_max
(as suggested in the comments) which is also from skimage, and has a manual page here 的所有硬币。在 *args 中使用一些合理的数字可以从响应图像中获取峰值。
关于峰被置换的第二条评论也在 documentation
中讨论
"Note that the peaks in the output of match_template correspond to the origin (i.e. top-left corner) of the template."
可以手动纠正这一点(通过将峰平移到模板的边长),或者您可以将 pad_input
bool 设置为 True
(source),作为副产品,这意味着响应函数中的峰值在最大重叠点与模板中心对齐。
将这两个位组合成一个脚本,我们得到如下内容:
import numpy as np
import matplotlib.pyplot as plt
from skimage import data
from skimage.feature import match_template
from skimage.feature import peak_local_max # new import!
image = data.coins()
coin = image[170:220, 75:130]
result = match_template(image, coin,pad_input=True) #added the pad_input bool
peaks = peak_local_max(result,min_distance=10,threshold_rel=0.5) # find our peaks
# produce a plot equivalent to the one in the docs
plt.imshow(result)
# highlight matched regions (plural)
plt.plot(peaks[:,1], peaks[:,0], 'o', markeredgecolor='r', markerfacecolor='none', markersize=10)
我正在尝试遵循 scikit-image 中有关模板匹配的教程(检查它 here).
仅使用这个例子,我想在图像中找到所有匹配的硬币(最大值),而不仅仅是给出最高分的这一个。我在考虑使用:
maxima = argrelextrema(result, np.greater)
但问题是它也发现了非常小的局部最大值,这只是一个噪音。有没有办法筛选 numpy 数组并找到最强的最大值?谢谢!
我一直在挖掘并找到了一些解决方案,但不幸的是我不确定我是否知道脚本中到底做了什么。我稍微修改了脚本 here:
neighborhood_size = 20 #how many pixels
threshold = 0.01 #threshold of maxima?
data_max = filters.maximum_filter(result, neighborhood_size)
maxima = (result == data_max)
data_min = filters.minimum_filter(result, neighborhood_size)
diff = ((data_max - data_min) > threshold)
maxima[diff == 0] = 0
x_image,y_image = [], []
temp_size = coin.shape[0]
labeled, num_objects = ndimage.label(maxima)
slices = ndimage.find_objects(labeled)
x, y = [], []
for dy,dx in slices:
x_center = (dx.start + dx.stop - 1)/2
x.append(x_center)
y_center = (dy.start + dy.stop - 1)/2
y.append(y_center)
fig, (raw,found) = plt.subplots(1,2)
raw.imshow(image,cmap=plt.cm.gray)
raw.set_axis_off()
found.imshow(result)
found.autoscale(False)
found.set_axis_off()
plt.plot(x,y, 'ro')
plt.show()
并这样做:
我还意识到,与原始图像相比,找到的峰的坐标发生了偏移。我认为差异来自模板大小。当我发现更多时,我会更新。
编辑:通过稍微修改代码,我还能够在输入图像上找到位置:
x_image_center = (dx.start + dx.stop - 1 + temp_size) / 2
x_image.append(x_image_center)
y_image_center = (dy.start + dy.stop - 1 + temp_size) / 2
y_image.append(y_image_center)
找到 documentation suggests "...you should use a proper peak-finding function." The easiest of these is probably peak_local_max
(as suggested in the comments) which is also from skimage, and has a manual page here 的所有硬币。在 *args 中使用一些合理的数字可以从响应图像中获取峰值。
关于峰被置换的第二条评论也在 documentation
中讨论"Note that the peaks in the output of match_template correspond to the origin (i.e. top-left corner) of the template."
可以手动纠正这一点(通过将峰平移到模板的边长),或者您可以将 pad_input
bool 设置为 True
(source),作为副产品,这意味着响应函数中的峰值在最大重叠点与模板中心对齐。
将这两个位组合成一个脚本,我们得到如下内容:
import numpy as np
import matplotlib.pyplot as plt
from skimage import data
from skimage.feature import match_template
from skimage.feature import peak_local_max # new import!
image = data.coins()
coin = image[170:220, 75:130]
result = match_template(image, coin,pad_input=True) #added the pad_input bool
peaks = peak_local_max(result,min_distance=10,threshold_rel=0.5) # find our peaks
# produce a plot equivalent to the one in the docs
plt.imshow(result)
# highlight matched regions (plural)
plt.plot(peaks[:,1], peaks[:,0], 'o', markeredgecolor='r', markerfacecolor='none', markersize=10)