2016-03-03 9 views
9

की फास्ट पूर्ण अंतर मैं dtype=np.uint8 के साथ दो numpy-सरणियों है - इस तरह:दो uint8 सरणियों

img1=np.uint8(np.random.randint(0, 255, (480, 640))) 
img2=np.uint8(np.random.randint(0, 255, (480, 640))) 

और मैं इन सरणियों के सकारात्मक अंतर निर्माण करना चाहते हैं।

def differenceImageV1(img1, img2): 
    diff=np.empty_like(img1) 
    h, w=img1.shape 
    for y in range(h): 
    for x in range(w): 
     if img1[y, x]<img2[y, x]: diff[y, x]=img2[y, x]-img1[y, x] 
     else:      diff[y, x]=img1[y, x]-img2[y, x] 
    return(diff) 

def differenceImageV2(img1, img2): 
    return(np.uint8(np.absolute(np.int16(img1)-np.int16(img2)))) 

def differenceImageV3(img1, img2): # fast - but wrong result 
    return(img1-img2) 

मैं (और रकम की जांच करने के लिए यदि वे बराबर हैं) इन निष्पादन समय मिलता है:

10x: 1893.54 ms np.sum=26122208 
1000x: 411.71 ms np.sum=26122208 
1000x: 26.60 ms np.sum=39123624 

यहाँ मेरी पहले दो approches (और संदर्भ के लिए एक तिहाई एक) कर रहे हैं

क्या वी 2 के साथ सही परिणाम प्राप्त करने का कोई तरीका है?

+0

यह सुनिश्चित नहीं है कि यह वास्तव में बहुत मदद करेगा, लेकिन संभवतया आपको 'अंतर ImageV2' में 'np.int16 (img2)' की आवश्यकता नहीं है, और केवल' img2' का उपयोग कर सकते हैं। साथ ही, क्या आप सटीक समय के परिणामों के लिए ['timeit'] (https://docs.python.org/2/library/timeit.html) लाइब्रेरी का उपयोग कर रहे हैं? – Kupiakos

+0

मुझे ओवरफ्लो के बारे में पता है (अंडरफ्लो तब होता है जब दो फ़्लोटिंग पॉइंट नंबरों के बीच का अंतर अलग-अलग बनने के लिए बहुत छोटा होता है)। मेरा मतलब है कि पूरा बयान 'वापसी (np.uint8 (np.absolute (np.int16 (img1) -img2) होगा)। 'img1' अभी भी' int16' पर डाला गया है, इसलिए परिणाम 'int16' होगा और उसी ऋणात्मक संख्या को अनुमति दे सकता है जो पहले से ही कास्ट कर देगा। 'np.sum' एक ही परिणाम देता है। यह सिर्फ पूरे सरणी की एक प्रति नहीं लेता है। मैं 1000 लूप के लिए लगभग 70 एमएस बंद कर देता हूं। – Kupiakos

+0

आप सही हैं। मुझे एक ही परिणाम मिलता है, अगर मैं 'np.int16 (img1) -img2' करता हूं। 1000 लूप के लिए निष्पादन समय 400.3 9 एमएस तक चला जाता है। और नहीं, मैं 'time.process_time() 'का उपयोग यहां करता हूं, क्योंकि मुझे एक या दस मिलीसेकंड की परवाह नहीं है। – dede

उत्तर

7

यहां एक दृष्टिकोण है जो V2 से काफी तेज़ है: img1-img2 लें, और img1>img2 पर निर्भर करते हुए 1 या -1 से गुणा करें। यह इस प्रकार से कार्यान्वित किया जाता है है:

def differenceImageV6(img1, img2): 
    a = img1-img2 
    b = np.uint8(img1<img2) * 254 + 1 
    return a * b 

परीक्षण प्रदर्शन के लिए एक परीक्षण दोहन:

import numpy as np 

img1=np.uint8(np.random.randint(0, 255, (480, 640))) 
img2=np.uint8(np.random.randint(0, 255, (480, 640))) 

def differenceImageV1(img1, img2): 
    diff=np.empty_like(img1) 
    h, w=img1.shape 
    for y in range(h): 
    for x in range(w): 
     if img1[y, x]<img2[y, x]: diff[y, x]=img2[y, x]-img1[y, x] 
     else:      diff[y, x]=img1[y, x]-img2[y, x] 
    return(diff) 

def differenceImageV2(img1, img2): 
    return(np.uint8(np.abs(np.int16(img1)-img2))) 

def differenceImageV3(img1, img2): # fast - but wrong result 
    return(img1-img2) 

def differenceImageV4(img1, img2): 
    return np.where(img1>img2, img1-img2, img2-img1) 

def differenceImageV5(img1, img2): 
    a = img1-img2 
    b = img2-img1 
    c = img1>img2 
    return a*c + b*(~c) 

def differenceImageV6(img1, img2): 
    a = img1-img2 
    b = np.uint8(img1<img2) * 254 + 1 
    return a * b 

import timeit 
def testit(): 
    for fn in [differenceImageV2, differenceImageV3, differenceImageV4, differenceImageV5, differenceImageV6]: 
    print fn.__name__, np.sum(fn(img1, img2).astype('int64')), 
    print timeit.timeit("%s(img1, img2)" % fn.__name__, "from test import img1, img2, %s" % fn.__name__, number=1000) 

if __name__ == '__main__': 
    testit() 

और जिसके परिणामस्वरूप प्रदर्शन संख्या:

differenceImageV2 26071358 0.982538938522 
differenceImageV3 39207702 0.0261280536652 
differenceImageV4 26071358 1.36270809174 
differenceImageV5 26071358 0.220561981201 
differenceImageV6 26071358 0.154536962509 

differenceImageV6, गलत differenceImageV3 से के बारे में 6x धीमी है लेकिन पिछले सबसे अच्छे differenceImageV2 की तुलना में अभी भी 6x तेज है। differenceImageV1 परीक्षण नहीं किया गया है क्योंकि यह बाकी की तुलना में धीमी गति के कुछ आदेश आसानी से धीमा है।

नोट: मैंने तुलना के लिए np.where दृष्टिकोण शामिल किया है; मैंने सोचा कि इसका अच्छा प्रदर्शन हो सकता है लेकिन यह काफी खराब साबित हुआ है। ऐसा लगता है कि एक बूलियन सरणी द्वारा स्लाइसिंग प्रदर्शन NumPy में काफी धीमी है।

+0

मुझे 'अंतर ImageV2' के लिए लगभग 895 μs मिल रहा है, जबकि 'differenceImageV6' के लिए 645 μs। वास्तविक गति के बावजूद, मैं अभी भी numpy जादूगर की सराहना करता हूं। – Kupiakos

+1

मुझे आपकी वी 6 :-) पसंद है ... लेकिन अभी भी इसे समझने की कोशिश कर रहा है ;-) – dede

+0

मुझे लगता है कि यदि आप इसे 'ए = img1 - img2 के रूप में करते हैं तो V6 तेज होगा; एक [img1 Jaime

संबंधित मुद्दे