2017-08-17 30 views
0

這是我一直在努力幾個星期的事情。該算法如下:沿着二維陣列滑動一個子陣列

  1. 選擇一個子陣列作爲行和列的從一個較大的陣列
  2. 計算子陣列的中值
  3. 在子陣列中位值替換單元的陣列
  4. 移動通過其自身的長度子陣列向右
  5. 重複結束陣列的
  6. 移動子陣列向下通過其自身的高度
  7. 重複

我有步驟1至3如下:

import numpy as np 
w1 = np.arange(100).reshape(10,10) 
side = 3 
patch = w1[0:side, 0:side] 

i, j = patch.shape 
for j in range(side): 
    for i in range(side): 
     patch[i,j] = np.median(patch) 

最後,我將使用從圖像的901x877陣列,但我只是試圖讓這個簡單的舉行任務第一。我怎樣才能一起滑動陣列,然後用循環向下滑動?

+0

儘管修復代碼非常簡單,但在['scipy.ndimage'](https://docs.scipy.org/doc/scipy/reference/ndimage.html)或[scikit-image] (http://scikit-image.org/)來完成這項工作。 – user2357112

+0

我試圖不使用scipy或skimage,而是明確寫出算法。最終我會使用一個蒙面數組。 – Jim421616

回答

0

可以使用scikit圖像的view_as_blocks和NumPy的廣播向量化操作:

import numpy as np 
import skimage 

w1 = np.arange(144).reshape(12,12) 
print(w1) 
# [[ 0 1 2 3 4 5 6 7 8 9 10 11] 
# [ 12 13 14 15 16 17 18 19 20 21 22 23] 
# [ 24 25 26 27 28 29 30 31 32 33 34 35] 
# [ 36 37 38 39 40 41 42 43 44 45 46 47] 
# [ 48 49 50 51 52 53 54 55 56 57 58 59] 
# [ 60 61 62 63 64 65 66 67 68 69 70 71] 
# [ 72 73 74 75 76 77 78 79 80 81 82 83] 
# [ 84 85 86 87 88 89 90 91 92 93 94 95] 
# [ 96 97 98 99 100 101 102 103 104 105 106 107] 
# [108 109 110 111 112 113 114 115 116 117 118 119] 
# [120 121 122 123 124 125 126 127 128 129 130 131] 
# [132 133 134 135 136 137 138 139 140 141 142 143]] 

side = 3 
w2 = skimage.util.view_as_blocks(w1, (side, side)) 
w2[...] = np.median(w2, axis=(-2, -1))[:, :, None, None] 
print(w1) 
# [[ 13 13 13 16 16 16 19 19 19 22 22 22] 
# [ 13 13 13 16 16 16 19 19 19 22 22 22] 
# [ 13 13 13 16 16 16 19 19 19 22 22 22] 
# [ 49 49 49 52 52 52 55 55 55 58 58 58] 
# [ 49 49 49 52 52 52 55 55 55 58 58 58] 
# [ 49 49 49 52 52 52 55 55 55 58 58 58] 
# [ 85 85 85 88 88 88 91 91 91 94 94 94] 
# [ 85 85 85 88 88 88 91 91 91 94 94 94] 
# [ 85 85 85 88 88 88 91 91 91 94 94 94] 
# [121 121 121 124 124 124 127 127 127 130 130 130] 
# [121 121 121 124 124 124 127 127 127 130 130 130] 
# [121 121 121 124 124 124 127 127 127 130 130 130]] 

請注意,我有你的數組的大小,使所有更改爲12x12你的瓷磚的3x3實際上適合在那裏。

+0

您使用view_as_blocks的想法讓我看到了view_as_windows,這幾乎就是我所需要的。謝謝! – Jim421616

0

下面是我看到的一些「代碼氣味」。 從range(side)開始,因爲此數字設置爲3那麼您將得到[0,1,2]的結果。這是你真正想要的嗎?

您設置i,j = patch.size然後立即在您的for循環中寫入這些值。

最後,您將重新計算每個循環的median

好的,這是我會做的。

  1. 找出你需要寬度和高度的補丁數量。並將其乘以邊的大小。
  2. 將你的數組(矩陣)切成片段。
  3. 將補丁分配給中位數。

import numpy as np                                               
w1 = np.arange(100).reshape(10,10)                                           
side = 3                                                 
w, h = w1.shape                                                
width_index = np.array(range(w//side)) * side                                        
height_index = np.array(range(h//side)) * side                                        

def assign_patch(patch, median, side):                                          
    """Break this loop out to prevent 4 nested 'for' loops"""                                    
    for j in range(side):                                             
     for i in range(side):                                            
      patch[i,j] = median                                            
    return patch                                               

for width in width_index:                                             
    for height in height_index:                                            
     patch = w1[width:width+side, height:height+side]                                     
     median = np.median(patch)                                           
     assign_patch(patch, median, side)                   

print w1   
+0

這是一個好主意......這個錯誤在第5行出現: TypeError:'float'對象不能被解釋爲一個整數 – Jim421616

+0

好吧,你是np數組是float,因爲(我認爲)在python3該部門不會默認爲整數除法。因此,檢查了這一點對於這個問題的解釋:https://stackoverflow.com/questions/1282945/python-integer-division-yields-float ,我會更新的代碼在Python 3 – VoNWooDSoN

+0

工作的變化是在'np.array(range(w // side))* side'中有'//'而不是'/',因爲在python 3中默認爲浮點除法。 我很抱歉,我知道這可以迷惑人剛開始學習Python,但我是一個老的黑客,並繼續使用Python解釋這兩個則算的區別2.7 – VoNWooDSoN