获取高于某个值的二维数组中的局部最大值坐标

Posted

技术标签:

【中文标题】获取高于某个值的二维数组中的局部最大值坐标【英文标题】:Get coordinates of local maxima in 2D array above certain value 【发布时间】:2012-02-25 01:42:14 【问题描述】:
from PIL import Image
import numpy as np
from scipy.ndimage.filters import maximum_filter
import pylab

# the picture (256 * 256 pixels) contains bright spots of which I wanna get positions
# problem: data has high background around value 900 - 1000

im = Image.open('slice0000.png')
data = np.array(im)

# as far as I understand, data == maximum_filter gives True-value for pixels
# being the brightest in their neighborhood (here 10 * 10 pixels)

maxima = (data == maximum_filter(data,10))
# How can I get only maxima, outstanding the background a certain value, let's say 500 ?

恐怕我不太了解scipy.ndimage.filters.maximum_filter() 函数。有没有办法只在斑点内而不在背景内获得像素坐标?

http://i.stack.imgur.com/RImHW.png(16位灰度图片,256*256像素)

【问题讨论】:

【参考方案1】:
import numpy as np
import scipy
import scipy.ndimage as ndimage
import scipy.ndimage.filters as filters
import matplotlib.pyplot as plt

fname = '/tmp/slice0000.png'
neighborhood_size = 5
threshold = 1500

data = scipy.misc.imread(fname)

data_max = filters.maximum_filter(data, neighborhood_size)
maxima = (data == data_max)
data_min = filters.minimum_filter(data, neighborhood_size)
diff = ((data_max - data_min) > threshold)
maxima[diff == 0] = 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)

plt.imshow(data)
plt.savefig('/tmp/data.png', bbox_inches = 'tight')

plt.autoscale(False)
plt.plot(x,y, 'ro')
plt.savefig('/tmp/result.png', bbox_inches = 'tight')

给定 data.png

上述程序生成带有threshold = 1500result.png。降低threshold 以获取更多局部最大值:

参考文献

J.F. Sebastian counts nuclei Joe Kington finds paw prints Ivan finds local maximums

【讨论】:

你好 unutbu,恐怕我并没有真正得到你的解决方案,即输出。目前,我设法排除了所有绝对值小于 1500 的最大值。我只是在尝试结果是否令人满意。 很可能是我不明白你的问题。您是否正在寻找一种方法来找到最大值的(x,y) 坐标?如果是这样,您可以使用np.where(maxima) 找到它们。 你是对的。但我想摆脱背景中的局部最大值。就像说:一个局部最大值只是一个局部最大值,如果它从它的邻域中脱颖而出超过某个值。目前,我通过将值低于 1500 的所有像素设置为零来取消背景,但我对此并不满意。你知道ImageJ吗? “查找最大值”功能做得很好,我想重现这个输出。明确一点:我想要图片上亮点内最亮像素的坐标。【参考方案2】:
import numpy as np
import scipy
import scipy.ndimage as ndimage
import scipy.ndimage.filters as filters
import matplotlib.pyplot as plt

fname = '/tmp/slice0000.png'
neighborhood_size = 5
threshold = 1500

data = scipy.misc.imread(fname)

data_max = filters.maximum_filter(data, neighborhood_size)
maxima = (data == data_max)
data_min = filters.minimum_filter(data, neighborhood_size)
diff = ((data_max - data_min) > threshold)
maxima[diff == 0] = 0

labeled, num_objects = ndimage.label(maxima)
xy = np.array(ndimage.center_of_mass(data, labeled, range(1, num_objects+1)))

plt.imshow(data)
plt.savefig('/tmp/data.png', bbox_inches = 'tight')

plt.autoscale(False)
plt.plot(xy[:, 1], xy[:, 0], 'ro')
plt.savefig('/tmp/result.png', bbox_inches = 'tight')

上一个条目对我非常有用,但是 for 循环减慢了我的应用程序的速度。我发现 ndimage.center_of_mass() 在获取坐标方面做得很好而且很快……因此提出了这个建议。

【讨论】:

感谢您的改进!【参考方案3】:

现在可以使用 skimage 完成。

from skimage.feature import peak_local_max
xy = peak_local_max(data, min_distance=2,threshold_abs=1500)

在我的计算机上,对于 VGA 图像大小,它的运行速度比上述解决方案快约 4 倍,并且在某些情况下还返回了更准确的位置。

【讨论】:

这是skimage 中的一个很好的示例/教程,用于在图像中查找“blob”:scikit-image.org/docs/stable/auto_examples/features_detection/…

以上是关于获取高于某个值的二维数组中的局部最大值坐标的主要内容,如果未能解决你的问题,请参考以下文章

Labview中 怎么获取 波形数据中 其Y最小值对应的X轴坐标,谢谢,

C ++在二维数组中查找局部最大值

C++中如何在一个二维数组中查找某个值

HDU4456-Crowd (坐标旋转处理+hash处理+二维树状数组)

如何(稳健地)在python中的二维数组上找到局部最小值?

PHP获取二维数组中相同的元素