2012-10-22 12 views
8

मुझे 2560x2160 2 डी numpy सरणी (छवि) के प्रत्येक पिक्सेल के माध्यम से लूप की आवश्यकता है। मेरी समस्या का एक सरलीकृत संस्करण इस प्रकार है:पायथन में किसी छवि के प्रत्येक पिक्सेल के माध्यम से लूप करने का तेज़ तरीका?

import time 
import numpy as np 

t = time.clock() 
limit = 9000 
for (x,y), pixel in np.ndenumerate(image): 
    if(pixel > limit) 
     pass 
tt = time.clock() 
print tt-t 

यह मेरे कंप्यूटर पर पूरा करने के लिए एक अप्रिय ~ 30 सेकंड ले रहा है। (कोर i7, 8GB RAM) क्या इस लूप को आंतरिक 'if' कथन के साथ करने का कोई तेज़ तरीका है? मुझे केवल एक निश्चित सीमा से ऊपर पिक्सल में दिलचस्पी है, लेकिन मुझे उनके (एक्स, वाई) सूचकांक और मूल्य की आवश्यकता है।

उत्तर

13

एक बूलियन मैट्रिक्स का उपयोग करें:

x, y = (image > limit).nonzero() 
vals = image[x, y] 
+1

वाह! मेरी आंखें खोली गई हैं। <0.1 सेकंड ले लिया। – dinkelk

+0

एक्स और वाई में क्या है? –

+1

@AndrewHundt: 'x' और' y' क्रमशः nonzero अंक के लिए x- और y-indices के सरणी हैं। – nneonneo

6

पहले, इस्तेमाल करने की कोशिश vectorize गणना:

i, j = np.where(image > limit) 

आपकी समस्या vectorize गणना से हल नहीं किया जा सकता है, तो आप के रूप में पाश के लिए speedup कर सकते हैं :

for i in xrange(image.shape[0]): 
    for j in xrange(image.shape[1]): 
     pixel = image.item(i, j) 
     if pixel > limit: 
      pass 

या:

from itertools import product 
h, w = image.shape 
for pos in product(range(h), range(w)): 
    pixel = image.item(pos) 
    if pixel > limit: 
     pass 

numpy.ndenumerate लूप के लिए सामान्य उपयोग करके धीमा है और item विधि से सरणी से मान प्राप्त करें, जिससे आप लूप को 4x तक तेज कर सकते हैं।

यदि आपको अधिक गति की आवश्यकता है, तो साइथन का उपयोग करने का प्रयास करें, यह आपके कोड को सी कोड जितना तेज़ कर देगा।