2011-12-27 81 views
29

我有一個這樣的數組:如何將一個圓形的遮罩應用到一個numpy數組?

>>> np.ones((8,8)) 
array([[ 1., 1., 1., 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1., 1., 1., 1.], 
     [ 1., 1., 1., 1., 1., 1., 1., 1.]]) 

我創建一個半徑3這樣一個圓盤狀面膜:

y,x = np.ogrid[-3: 3+1, -3: 3+1] 
mask = x**2+y**2 <= 3**2 

這給:

>> mask 
array([[False, False, False, True, False, False, False], 
     [False, True, True, True, True, True, False], 
     [False, True, True, True, True, True, False], 
     [ True, True, True, True, True, True, True], 
     [False, True, True, True, True, True, False], 
     [False, True, True, True, True, True, False], 
     [False, False, False, True, False, False, False]], dtype=bool) 

現在,我想能夠將這個掩碼應用到我的數組中,使用任何元素作爲中心點。 因此,例如,與(1,1)的中心點,我想得到這樣一個數組:

>>> new_arr 
array([[ True, True, True, True, 1., 1., 1., 1.], 
     [ True, True, True, True, True, 1., 1., 1.], 
     [ True, True, True, True, 1., 1., 1., 1.], 
     [ True, True, True, True, 1., 1., 1., 1.], 
     [ 1., True, 1., 1., 1., 1., 1., 1.], 
     [ 1.,  1., 1., 1., 1., 1., 1., 1.], 
     [ 1.,  1., 1., 1., 1., 1., 1., 1.], 
     [ 1.,  1., 1., 1., 1., 1., 1., 1.]]) 

有沒有申請這個面膜的簡單方法?

編輯:我不應該有混合布爾和浮動 - 這是誤導。

>>> new_arr 
array([[ 255., 255., 255., 255., 1., 1., 1., 1.], 
     [ 255., 255., 255., 255., 255., 1., 1., 1.], 
     [ 255., 255., 255., 255., 1., 1., 1., 1.], 
     [ 255., 255., 255., 255., 1., 1., 1., 1.], 
     [ 1., 255., 1., 1., 1., 1., 1., 1.], 
     [ 1.,  1., 1., 1., 1., 1., 1., 1.], 
     [ 1.,  1., 1., 1., 1., 1., 1., 1.], 
     [ 1.,  1., 1., 1., 1., 1., 1., 1.]]) 

這更多是我需要的結果。

陣列[掩模] = 255

會掩蓋使用陣列中心點(0 +半徑,0 +半徑)。

但是,我希望能夠在任何點(y,x)放置任意大小的面具,並自動修剪以適合它。

回答

44

我會做這樣的,其中(A,B)爲您的面罩的中心:

import numpy as np 

a, b = 1, 1 
n = 7 
r = 3 

y,x = np.ogrid[-a:n-a, -b:n-b] 
mask = x*x + y*y <= r*r 

array = np.ones((n, n)) 
array[mask] = 255 
0

要得到相同的結果,在你的榜樣,你可以做這樣的事情:

>>> new_arr = np.array(ones, dtype=object) 
>>> new_arr[mask[2:, 2:]] = True 
>>> print new_arr 
array([[True, True, True, True, 1.0, 1.0, 1.0, 1.0], 
     [True, True, True, True, True, 1.0, 1.0, 1.0], 
     [True, True, True, True, 1.0, 1.0, 1.0, 1.0], 
     [True, True, True, True, 1.0, 1.0, 1.0, 1.0], 
     [1.0, True, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], 
     [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], 
     [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0], 
     [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], dtype=object) 
+0

它的工作原理...那是相當的黑客,與陣列的複製和0/1改變它的D型...乘法是由@ 9000建議的正規途徑。 – mac 2011-12-27 17:19:59

+0

@mac是的,我同意。我希望從OP得到一些反饋,以找出他真正想要的東西。 – jcollado 2011-12-27 17:52:17

+0

我很抱歉誤導。我在帖子中澄清了我的問題。我想要的是一種方式來獲得由掩模覆蓋原來的數組中的元素,給定一箇中心點(Y,X)的面具。然後我可以根據需要操縱它們。 – user816555 2011-12-27 18:39:45

2

你有沒有嘗試使口罩或零和一,然後使用每個元素的數組乘法?這是規範的方式,或多或少。

而且,你一定希望數字和布爾值在numpy的陣列的混合?顧名思義,NumPy最適合數字。

+0

我對有關數字/布爾組合的混亂很抱歉。希望這個問題不再具有誤導性。 你能解釋一下你的第一句話嗎? – user816555 2011-12-27 17:51:26

7

我只是想和大家一起分享這種技術的一個更高級的應用程序,我只是面對。

我的問題是應用這個循環內核來計算2D矩陣中每個點周圍所有值的平均值。生成的內核可以通過以下方式傳遞給scipy的通用過濾器:

import numpy as np 
from scipy.ndimage.filters import generic_filter as gf 

kernel = np.zeros((2*radius+1, 2*radius+1)) 
y,x = np.ogrid[-radius:radius+1, -radius:radius+1] 
mask = x**2 + y**2 <= radius**2 
kernel[mask] = 1 
circular_mean = gf(data, np.mean, footprint=kernel) 

希望這有助於!

3

說得一個方便的功能:

def cmask(index,radius,array): 
    a,b = index 
    nx,ny = array.shape 
    y,x = np.ogrid[-a:nx-a,-b:ny-b] 
    mask = x*x + y*y <= radius*radius 

    return(sum(array[mask])) 

返回半徑內的像素總和,或返回(陣列[掩模] = 2),用於任何需要。

3

你可以使用SciPy的的卷積函數,它允許你把任何特定的面具,又名內核的利益,任何數量的陣列中給出的座標,一下子:

import numpy as np 
from scipy.ndimage.filters import convolve 

首先創建座標與你想要的面具(內核)的座標數組爲中心標記爲2

background = np.ones((10,10)) 
background[5,5] = 2 
print(background) 

[[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 2. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]] 

創建你的面具:

y,x = np.ogrid[-3: 3+1, -3: 3+1] 
mask = x**2+y**2 <= 3**2 
mask = 254*mask.astype(float) 
print(mask) 

[[ 0. 0. 0. 254. 0. 0. 0.] 
[ 0. 254. 254. 254. 254. 254. 0.] 
[ 0. 254. 254. 254. 254. 254. 0.] 
[ 254. 254. 254. 254. 254. 254. 254.] 
[ 0. 254. 254. 254. 254. 254. 0.] 
[ 0. 254. 254. 254. 254. 254. 0.] 
[ 0. 0. 0. 254. 0. 0. 0.]] 

卷積兩個圖像:

b = convolve(background, mask)-sum(sum(mask))+1 
print(b) 

[[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 255. 1. 1. 1. 1.] 
[ 1. 1. 1. 255. 255. 255. 255. 255. 1. 1.] 
[ 1. 1. 1. 255. 255. 255. 255. 255. 1. 1.] 
[ 1. 1. 255. 255. 255. 255. 255. 255. 255. 1.] 
[ 1. 1. 1. 255. 255. 255. 255. 255. 1. 1.] 
[ 1. 1. 1. 255. 255. 255. 255. 255. 1. 1.] 
[ 1. 1. 1. 1. 1. 255. 1. 1. 1. 1.] 
[ 1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]] 

注意,卷積功能條目不上班, 即卷積(A,B)=卷積(B,A)

還要注意的是,如果你的點在邊緣附近時,算法不會在座標處再現內核。爲了解決這個問題,你可以通過墊內核的最大軸爲背景,應用卷積,然後取出填充。現在

,你可以映射任何內核數組中的任意數量的點,但要注意,如果兩個內核重疊,它們增加在重疊。如果您需要,您可以將其限定爲此值

相關問題