numpy:基于距离中心的2d像素欧氏距离的1d直方图

时间:2013-06-21 15:09:28

标签: numpy histogram multidimensional-array

我正在使用python,scipy,numpy等。

我想基于像素到图像质心的距离来计算灰度图像的强度值的直方图。以下解决方案有效,但速度很慢:

import matplotlib.pyplot as plt
from scipy import ndimage
import numpy as np
import math

# img is a 2-dimensionsl numpy array
img = np.random.rand(300, 300)
# center of mass of the pixels is easy to get
centerOfMass = np.array(list(ndimage.measurements.center_of_mass(img)))

# declare histogram buckets
histogram = np.zeros(100)

# declare histogram range, which is half the diagonal length of the image, enough in this case.
maxDist = len(img)/math.sqrt(2.0)

# size of the bucket might be less than the width of a pixel, which is fine.
bucketSize = maxDist/len(histogram)

# fill the histogram buckets
for i in range(len(img)):
    for j in range(len(img[i])):
        dist = np.linalg.norm(centerOfMass - np.array([i,j]))
        if(dist/bucketSize < len(histogram)):
            histogram[int(dist/bucketSize)] += img[i, j]

# plot the img array
plt.subplot(121)
imgplot = plt.imshow(img)
imgplot.set_cmap('hot')
plt.colorbar()
plt.draw()

# plot the histogram
plt.subplot(122)
plt.plot(histogram)
plt.draw()

plt.show()

正如我之前所说,这是有效的,但是非常慢,因为你不应该在numpy中以这种方式双循环数组。是否有更有效的方法来做同样的事情?我假设我需要在所有数组元素上应用一些函数,但我也需要索引坐标。我怎样才能做到这一点?目前1kx1k图像需要几秒钟,这是非常慢的。

1 个答案:

答案 0 :(得分:2)

所有numpy binning函数(bincounthistogramhistogram2d ...都有一个weights关键字参数,您可以使用它来执行非常奇怪的事情,例如您的。我就是这样做的:

rows, cols = 300, 300
img = np.random.rand(rows, cols)

# calculate center of mass position
row_com = np.sum(np.arange(rows)[:, None] * img) / np.sum(img)
col_com = np.sum(np.arange(cols) * img) / np.sum(img)

# create array of distances to center of mass
dist = np.sqrt(((np.arange(rows) - row_com)**2)[:, None] +
               (np.arange(cols) - col_com)**2)

# build histogram, with intensities as weights
bins = 100
hist, edges = np.histogram(dist, bins=bins, weights=img)

# to reproduce your exact results, you must specify the bin edges
bins = np.linspace(0, len(img)/math.sqrt(2.0), 101)
hist2, edges2 = np.histogram(dist, bins=bins, weights=img)

没有给两种方法计时,但从终端运行时的延迟来判断,这明显加快了。