2011-04-06 95 views
0

我是一個python初學者,我試圖平均兩個NumPy 2D數組與形狀(1024,1024)。做這樣是相當快的:這個numpy數組爲什麼這麼慢?

newImage = (image1 + image2)/2 

但現在的圖像有一個「面具」,如果設置爲0時無效的某些元素。這意味着如果其中一個元素爲零,則生成的元素也應該爲零。我的瑣碎解決方案是:

newImage = numpy.zeros((1024,1024) , dtype=numpy.int16) 

for y in xrange(newImage.shape[0]): 
    for x in xrange(newImage.shape[1]): 
     val1 = image1[y][x] 
     val2 = image2[y][x]        
     if val1!=0 and val2!=0:    
     newImage[y][x] = (val1 + val2)/2 

但是,這真的很慢。我沒有時間它,但它似乎要慢100倍。

我也嘗試使用lambda運算符和「映射」,但這不會返回一個NumPy數組。

回答

8

嘗試此:

newImage = numpy.where(np.logical_and(image1, image2), (image1 + image2)/2, 0) 

如果沒有image1image2等於零,取平均值,否則爲零。

+0

謝謝,這個作品是快。 – Stiefel 2011-04-08 13:26:50

2

使用本地Python代碼進行循環通常要比使用使用快速C循環的內置工具慢得多。我不熟悉NumPy;可以用 你用map()做一個從你的兩個輸入數組到 的輸出嗎?如果是這樣,那應該會更快。

1

顯式for循環在Python中通常非常低效,不僅僅是numpy操作。幸運的是,有更快的方法來解決我們的問題。如果內存是不是一個問題,這個解決方案是相當不錯的:

import numpy as np 
new_image = np.zeros((1024, 1024), dtype=np.int16) 
valid = (image1!=0) & (image2!=0) 
new_image[valid] = (image1+image2)[valid] 

使用屏蔽陣列,它不創建數組的副本(它們所代表的觀點原來image1/2的另一種解決方案:

m1 = np.ma.masked_equal(image1, 0) 
m2 = np.ma.masked_equal(image2, 0) 
new_image = (m1+m2).filled(0) 

更新:第一溶液似乎是比所述第二數組具有約1000的非零項快3倍

0

numpy數組訪問操作看起來好像很慢。我看不到任何理由。您可以通過構建一個簡單的例子清楚地看到它:

import numpy 
    # numpy version 
    def at(s,n): 
     t1=time.time() 
     a=numpy.zeros(s,dtype=numpy.int32) 
     for i in range(n): 
     a[i%s]=n 
     t2=time.time() 
     return t2-t1 
    # native version 
    def an(s,n): 
     t1=time.time() 
     a=[(i) for i in range(s)] 
     for i in range(n): 
     a[i%s]=n 
     t2=time.time() 
     return t2-t1 

    # test 
    [at(100000,1000000),an(100000,1000000)] 

結果:[0.21972250938415527,0.15950298309326172]