在阅读this post之后,并且还使用了SciKit图像,我发现与MATLAB函数imregionalmax
相比,Python有所不同。
我有以下几行代码:
from skimage.feature import peak_local_max
manos = np.ones([5,5])
manos[2,2] = 0.
manos[2,4] = 2.
giannis = peak_local_max(manos,min_distance=1, indices=False, exclude_border=False)
giorgos = ndimage.filters.maximum_filter(manos, footprint=np.ones([3,3]))
giorgos = (giorgos == manos)
我希望2D数组的变量True
或giannis
只有一个giorgos
值([2,4]),就像我在MATLAB中得到的那样。相反,我最多只能考虑一个。
有人知道为什么这样工作,以及如何使其像在MATLAB中那样工作吗?
答案 0 :(得分:2)
giannis
和giorgos
的相似之处在于,它们找到的像素等于或大于3x3邻域中的其他像素。我相信giannis
还会有一些其他阈值。
这两种方法均不能保证找到的像素实际上是局部最大值。注意上面我所说的“更大或相等”。无论图像是局部最大值,局部最小值还是介于两者之间的某个地方,算法都会标记出图像中的任何平稳区域(所有像素均具有相同值的区域)。
例如:
import numpy as np
import matplotlib.pyplot as pp
import scipy.ndimage as ndimage
manos = np.sin(np.arange(100)/10)
manos = np.round(30*manos)/30 # Rounding to create plateaus
giorgos = ndimage.filters.maximum_filter(manos, footprint=np.ones([3]))
giorgos = (giorgos == manos)
pp.plot(manos);
pp.plot(giorgos);
pp.show()
请注意,滤波器是如何识别正弦曲线局部最小值附近的三个点的。其中的中间一个是实际的局部最小值,另外两个是既不是局部最大值也不是局部最小值的高原。
相比之下,MATLAB函数imregionalmax
可以识别被较低像素所包围的所有平稳段。执行此操作所需的算法与上述算法完全不同。可以使用Union-Find算法有效地完成此操作,也可以使用Flood-fill-type算法效率较低地完成操作。主要思想是找到一个不低于任何邻域的像素,然后从其扩展到其等值邻域,直到对整个高原进行了探索,或者直到找到高原中具有更高邻域值的像素之一
我知道的该算法的唯一实现 Python中的一种实现是在PyDIP中(注意:我是作者;还请注意:您还不能通过{ {1}},您需要从源代码进行编译):
pip
另一种实现是in SciKit-Image(感谢Juan的pointing this out):
import PyDIP as dip
nikos = dip.Maxima(manos)
pp.plot(manos);
pp.plot(nikos);
pp.show()