2012-12-26 93 views
2

由於我是新來numpy的,我對着實現,我寫在C++NumPy的:循環替代,優化

for(i=0;i<h;i++) 
{ 
    for(j=0;j<w;j++) 
    { 
     val=0; 
     for(i1=-size;i1<=size;i1++) 
     { 
      for(j1=-size;j1<=size;j1++) 
      { 
       h1=i+i1,w1=j+j1; 
       if (w1<=0) w1=w1+w; 
       if (h1<=0) h1=h1+h; 
       if (w1>=w) w1=w1-w; 
       if (h1>=h) h1=h1-h; 
       val=val+sqrt(pow(data[i][j][0]-data[h1][w1][0],2) 
          +pow(data[i][j][1]-data[h1][w1][1],2) 
          +pow(data[i][j][2]-data[h1][w1][2],2)); 
      } 
     } 
    } 
} 

正如你看到的我基本上將歐幾里得距離[我一個特定代碼的問題, j]元素與作爲子矩陣的一部分的每個元素[i-size到i +大小] [j大小到j +大小]

如何在python中編寫代碼而無需使用循環執行某些操作對numpy數組中每個依賴於其行和列位置的元素進行操作。或者必須有某種方法來優化它。

這是我當前的實現是很喜歡很慢

for i in range(0,h): 
    for j in range(0,w): 
     for i1 in range(-window_size, window_size+1): 
      for j1 in range(-window_size, window_size+1): 
       h1=i+i1 
       w1=j+j1 
       if w1 <= 0: 
        w1+=w 
       if h1 <= 0: 
        h1+=h 
       if w1 >= w: 
        w1-=w 
       if h1 >= h: 
        h1-=h 
       val[i][j] += np.sqrt(((source_pyr_down_3_Luv[i][j][0] - source_pyr_down_3_Luv[h1][w1][0])**2) 
            +((source_pyr_down_3_Luv[i][j][1] - source_pyr_down_3_Luv[h1][w1][1])**2) 
            +((source_pyr_down_3_Luv[i][j][2] - source_pyr_down_3_Luv[h1][w1][2])**2)) 

它幾乎用了6分鐘,運行這段代碼。

+1

您是否嘗試過自己什麼?你有什麼問題?代碼是什麼樣的,你得到了什麼錯誤信息?爲什麼你想避免循環? – Ben

+0

增加了我在執行代碼,也加入解釋UR問題,使原來的問題是更詳細。 –

+2

如果你有C++代碼,你可以用用Cython。無論如何,'pow(x,2)'在C或Python中效率都很低。只要使用'X * x' – tiago

回答

3

訪問子陣列IM numpy的嘗試:

data[i-size:i+size,j-size:j+size] 

編輯該子陣列(在這種情況下簡單+1到每個元件):

data[i-size:i+size,j-size:j+size] += 1 

或獲得含有距離的其它陣列2陣列(形狀(n,2))的元素之間:

data3 = np.sqrt(np.power(data1[:,0]-data2[:,0],2)+ np.power(data1[:,1]-data2[:,1],2)) 

我知道這不是一個完整的答案,但我希望它能幫助你開始。

+0

'data [i-size:i + size,j-size:j + size]'仍然需要循環,我猜Python循環會讓代碼非常慢相比於C++實現,如果這可以用numpy的可以做到,那麼代碼會變得非常快。這就是爲什麼我熱衷於消除環 –

2

可以避開明確的內部循環,並通過預擴展原始矩陣,這樣需要對元素索引沒有檢查直接計算歐幾里得距離的矩陣:

# Extend the matrix to avoid modular access 
h, w, _ = data.shape 
exdata = numpy.zeros((h+2*size, w+2*size, 2), data.dtype) 
exdata[size:-size, size:-size, :] = data[:,:,:] # Fill central part 
exdata[:size,:,:] = exdata[-size*2:-size,:,:] # Copy last rows to begin 
exdata[-size:,:,:] = exdata[size:size*2,:,:]  # Copy first rows to end 
exdata[:,:size,:] = exdata[:,-size*2:-size,:] # Copy last cols to begin 
exdata[:,-size:,:] = exdata[:,size:size*2,:]  # Copy first cols to end 

# Do the actual computation 
val = 0 
for i in xrange(h): 
    for j in xrange(w): 
     dx = numpy.copy(exdata[i:i+size*2+1, j:j+size*2+1, 0]) # all x values 
     dy = numpy.copy(exdata[i:i+size*2+1, j:j+size*2+1, 1]) # all y values 
     dx -= dx[size, size] # subtract central x 
     dy -= dy[size, size] # subtract central y 
     dx *= dx # square dx 
     dy *= dy # square dy 
     dx += dy # sum of squares 
     val += numpy.sum(dx ** 0.5)