2013-06-21 3 views
2

에서 2D 화소 유클리드 거리에 기초한 1D 히스토그램NumPy와 : 등 scipy, NumPy와 함께 I 파이썬 사용하고 중심

I는 그레이 스케일 이미지의 밝기 값의 히스토그램을 계산하려면, 거리에 따라 이미지의 질량 중심에 대한 픽셀의 비율. 다음 솔루션은 작동하지만, 매우 느립니다 :

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 이미지의 경우 수 초가 걸리며 엄청나게 느립니다. .

답변

2

모든 NumPy와 비닝 기능 (bincount, histogram, histogram2d은 ... 당신은 당신 같은 정말 이상한 일을 수행하는 데 사용할 수있는 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) 

두 가지 방법 모두 시간을 정하지 않았지만 터미널에서 둘 다 실행할 때의 지연으로 판단하면 눈에 띄게 빨라졌습니다.

+0

np.histogram이 다차원 배열을 사용할 수 있다는 것은 흥미롭지 만 놀랄만 한 것은 아닙니다. – Daniel

+0

@Ophion 그것은 당신이 무엇이든 걸립니다. 그 행은 항상 처리하기 전에 평평하게됩니다. – Jaime

+0

대단히 고맙습니다. 갈 길이 멀어 보이는 것처럼 거리의 배열을 가지고 놀고 있었지만 작동하지 못했습니다. –