NumPy

2012-02-23 21 views
9

में कई पिक्सेल स्थानों के रैखिक इंटरपोलेशन को तेज करना मैंने अपने कार्यक्रमों में से एक में मुख्य बाधा को दोहराने की कोशिश की है।NumPy

मैं कई गैर-पूर्णांक पिक्सेल मानों के साथ-साथ linearly (or rather bilinearly) interpolated मान प्राप्त करना चाहता हूं। यह है कि प्रत्येक पिक्सेल समन्वय उसी तरह से परेशान है। नीचे टिप्पणियों के साथ एक पूर्ण/न्यूनतम लिपि है जो समस्या का प्रदर्शन करती है। मैं result की गणना कैसे बढ़ा सकता हूं?

import numpy as np 
import time 

im = np.random.rand(640,480,3) # my "image" 
xx, yy = np.meshgrid(np.arange(im.shape[1]), np.arange(im.shape[0])) 
print "Check these are the right indices:",np.sum(im - im[yy,xx,:]) 

# perturb the indices slightly 
# I want to calculate the interpolated 
# values of "im" at these locations 
xx = xx + np.random.normal(size=im.shape[:2]) 
yy = yy + np.random.normal(size=im.shape[:2]) 

# integer value/pixel locations 
x_0 = np.int_(np.modf(xx)[1]) 
y_0 = np.int_(np.modf(yy)[1]) 
x_1, y_1 = x_0 + 1, y_0 + 1 

# the real-valued offsets/coefficients pixels 
a = np.modf(xx)[0][:,:,np.newaxis] 
b = np.modf(yy)[0][:,:,np.newaxis] 

# make sure we don't go out of bounds at edge pixels 
np.clip(x_0,0,im.shape[1]-1,out=x_0) 
np.clip(x_1,0,im.shape[1]-1,out=x_1) 
np.clip(y_0,0,im.shape[0]-1,out=y_0) 
np.clip(y_1,0,im.shape[0]-1,out=y_1) 

# now perform linear interpolation: THIS IS THE BOTTLENECK! 
tic = time.time() 
result = ((1-a) * (1-b) * im[y_0, x_0, :] + 
      a * (1-b) * im[y_1, x_0, :] + 
      (1-a) * b * im[y_0, x_1, :] + 
      a * b * im[y_1, x_1, :]) 
toc = time.time() 

print "interpolation time:",toc-tic 
+2

किसी भी कारण तुम क्यों 'अनदेखा कर रहे हैं scipy.ndimage.map_coordinates' यह सबसे तेजी से संस्करण है? (उदा। Scipy.ndimage पर निर्भरता से बचने के लिए चाहते हैं?) यदि नहीं, तो यह वह कार्य है जिसे आप चाहते हैं। –

+0

@ जोकिंगटन मुझे इस बारे में पता नहीं था - मुझे देखने दो कि क्या मैं इस फ़ंक्शन का उपयोग कर सकता हूं और यदि यह तेज़ है। धन्यवाद। – YXD

उत्तर

4

सुझाव के लिए @ जोकिंगटन के लिए धन्यवाद। यहाँ सबसे अच्छा मैं का उपयोग कर scipy.ndimage.map_coordinates

# rest as before 
from scipy import ndimage 
tic = time.time() 
new_result = np.zeros(im.shape) 
coords = np.array([yy,xx,np.zeros(im.shape[:2])]) 
for d in range(im.shape[2]): 
    new_result[:,:,d] = ndimage.map_coordinates(im,coords,order=1) 
    coords[2] += 1 
toc = time.time() 
print "interpolation time:",toc-tic 

अद्यतन के साथ आ सकता है: जोड़ा तोड़ मरोड़ टिप्पणी में सुझाव दिया और एक या दो अन्य बातों की कोशिश की।

tic = time.time() 
new_result = np.zeros(im.shape) 
coords = np.array([yy,xx]) 
for d in range(im.shape[2]): 
    ndimage.map_coordinates(im[:,:,d], 
          coords,order=1, 
          prefilter=False, 
          output=new_result[:,:,d]) 
toc = time.time() 

print "interpolation time:",toc-tic 

उदाहरण चलने का समय:

original version: 0.463063955307 
    better version: 0.204537153244 
    best version: 0.121845006943 
+0

क्षमा करें मैंने पहले एक उदाहरण पोस्ट नहीं किया था। मैं समय पर कम चल रहा था। ख़ुशी है कि यह आपको समझ में आ गया! आप इसे 'map_coordinates' पर एक कॉल के साथ कर सकते हैं, लेकिन आपकी छवि के आकार के आधार पर, प्रत्येक बैंड के माध्यम से पुनरावृत्ति संभवतः एक बेहतर विकल्प है। निर्देशांक की एक अस्थायी 3 डी सरणी संग्रह करना बहुत सारे रैम खाती है। यदि आप एक समय में केवल एक बैंड में 'map_coordinates' में पास करते हैं तो आप चीजों को थोड़ा सा गति दे सकते हैं। यह आपको 'coords' में शून्य शून्य सरणी छोड़ने की अनुमति भी देगा। –

+1

इसके अलावा, बिलीनेर इंटरपोलेशन के मामले में, यदि आप 'prefilter = False' निर्दिष्ट करते हैं तो आप थोड़ी मेमोरी और गति को थोड़ा ऊपर बचा सकते हैं। एक छोटी छवि के साथ आप एक अंतर नहीं देखेंगे, लेकिन बड़ी छवियों के साथ, यह स्मृति में एक अतिरिक्त प्रतिलिपि बनाने से बचाता है। –