如何使ndimage.filters.maximum_filter像MATLAB的imregionalmax函数那样工作?

3 人关注

阅读后 this post 我发现Python与MATLAB的函数 imregionalmax 相比,有很大的不同,我还玩了SciKit-image。

我有这几行代码。

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)

我期望一个二维数组,对于变量giannisgiorgos只有一个True值([2,4]),就像我在MATLAB中得到的那样。相反,我采取了一个以上的最大值。

是否知道为什么会这样,以及如何使其像在MATLAB中那样工作?

python
matlab
image-processing
scikit-image
ndimage
Hipparkhos
Hipparkhos
发布于 2019-05-14
1 个回答
Cris Luengo
Cris Luengo
发布于 2019-05-15
已采纳
0 人赞同

替换代码0】和 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-fil类型的算法效率较低。主要的想法是找到一个不低于任何邻居的像素,然后从它开始向它的等值邻居扩展,直到整个高原被探索完,或者直到你找到高原上的一个有更高价值的邻居的像素。

一个可从Python中获得的实现是在DIPlib(注:我是一名作家)。

import diplib as dip
nikos = dip.Maxima(manos)
pp.plot(manos);
pp.plot(nikos);
pp.show()