获取2D数组中局部最大值的坐标超过特定值

时间:2012-02-02 11:41:05

标签: python image numpy scipy

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像素)

3 个答案:

答案 0 :(得分:50)

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

enter image description here

上述程序会产生 result.png threshold = 1500。降低threshold以获取更多本地最大值:

enter image description here

<强>参考

答案 1 :(得分:12)

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()可以很快地获得坐标...因此这个建议。

答案 2 :(得分:3)

现在可以用skimage完成。

<iframe id="fullwidthvideo" width="560" height="315" src="https://www.youtube-nocookie.com/embed/uV33h4f1E1s?rel=0&controls=0&showinfo=0&autohide=1&autoplay=1&loop=1&playlist=uV33h4f1E1s" frameborder="0" allowfullscreen></iframe>
<script type="text/javascript">
 document.getElementById('fullwidthvideo').onload = function() {
 vidElement = document.getElementById('fullwidthvideo');
 vidTop = vidElement.clientWidth * -0.25;
 vidElement.style.top = vidTop + 'px';
 }
</script>

在我的电脑上,对于VGA图像尺寸,它的运行速度比上述解决方案快4倍,并且在某些情况下也会返回更准确的位置。