2011-12-27 25 views
29

Tôi có một mảng như thế này:Làm cách nào để áp dụng mặt nạ có hình dạng đĩa vào một mảng có nhiều mảng?

>>> 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.]]) 

tôi là tạo ra một mặt nạ đĩa hình với bán kính 3 như sau:

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

Điều này cho phép:

>> 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) 

Bây giờ, tôi muốn để có thể áp dụng mặt nạ này cho mảng của tôi, sử dụng bất kỳ phần tử nào làm điểm trung tâm. Vì vậy, ví dụ, với điểm trung tâm tại (1,1), tôi muốn để có được một mảng như:

>>> 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.]]) 

Có một cách dễ dàng để áp dụng mặt nạ này?

Chỉnh sửa: Tôi không nên có booleans hỗn hợp và phao nổi - đó là gây hiểu lầm.

>>> 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.]]) 

Đây là kết quả tôi cần.

mảng [mặt nạ] = 255

sẽ che mảng bằng cách sử dụng điểm giữa (0 + bán kính, 0 + bán kính).

Tuy nhiên, tôi muốn có thể đặt bất kỳ mặt nạ có kích thước nào tại bất kỳ điểm nào (y, x) và tự động cắt nó để vừa.

Trả lời

44

tôi sẽ làm điều đó như thế này, trong đó (a, b) là trung tâm của mặt nạ của bạn:

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

Để có được kết quả tương tự như trong ví dụ của bạn, bạn có thể làm một cái gì đó như thế này:

>>> 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

Nó hoạt động ... nhưng đó là một hack, với sao chép mảng và thay đổi dtype của nó ... Nhân bằng 0/1 là cách kinh điển như đề xuất bởi @ 9000. – mac

+0

@mac Vâng, tôi đồng ý. Tôi dự kiến ​​sẽ nhận được một số phản hồi từ OP để tìm ra những gì anh ấy thực sự đang tìm kiếm. – jcollado

+0

Tôi xin lỗi vì đã gây hiểu lầm. Tôi đã làm rõ câu hỏi của mình trong bài đăng của mình. Những gì tôi muốn là một cách để có được các yếu tố trong mảng ban đầu được bao phủ bởi mặt nạ, được đưa ra một điểm trung tâm (y, x) cho mặt nạ. Sau đó, tôi có thể thao tác chúng theo yêu cầu. – user816555

2

Bạn có thử làm một mặt nạ hoặc zero và những người thân và sau đó sử dụng mảng nhân mỗi nguyên tố? Đây là cách kinh điển, nhiều hay ít.

Ngoài ra, bạn có nhất định bạn muốn kết hợp các số và boolean trong một mảng numpy? NumPy, như tên của nó, hoạt động tốt nhất với các con số.

+0

Tôi xin lỗi về sự nhầm lẫn về kết hợp số/booleans. Hy vọng rằng câu hỏi không còn gây hiểu lầm nữa. Bạn có thể giải thích câu đầu tiên của mình nhiều hơn không? – user816555

7

Tôi chỉ muốn chia sẻ với tất cả mọi người một ứng dụng nhẹ tiên tiến hơn của kỹ thuật này mà tôi chỉ có đối mặt.

Vấn đề của tôi là áp dụng hạt nhân tròn này để tính trung bình của tất cả các giá trị xung quanh mỗi điểm trong ma trận 2D. Hạt nhân được tạo có thể được chuyển tới bộ lọc chung của scipy theo cách sau:

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) 

Hy vọng điều này sẽ hữu ích!

3

Để đưa nó trở thành một chức năng thuận tiện:

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])) 

Trả về tổng điểm ảnh trong vòng bán kính, hoặc trả lại (array [mask] = 2) cho bất cứ điều gì cần thiết.

3

Bạn có thể sử dụng chức năng dây leo scipy của, trong đó có lợi ích của việc cho phép bạn đặt bất kỳ mặt nạ đặc biệt, hay còn gọi là hạt nhân, trên bất kỳ số tọa độ được đưa ra trong mảng của bạn, tất cả cùng một lúc:

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

Đầu tiên tạo một phối hợp mảng với tọa độ của nơi bạn muốn mặt nạ (kernel) để được tập trung đánh dấu là 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.]] 

Tạo mặt nạ của bạn:

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.]] 

Convolve hai hình ảnh:

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.]] 

Lưu ý rằng các mục chức năng dây leo không đi lại, tức là dây leo (a, b) = dây leo (b, a)

Cũng lưu ý rằng nếu bạn điểm gần cạnh, bản ngã không tái tạo hạt nhân tại tọa độ. Để giải quyết vấn đề này, bạn có thể tạo nền bằng trục lớn nhất của hạt nhân, áp dụng chập, sau đó loại bỏ phần đệm.

Bây giờ, bạn có thể ánh xạ bất kỳ hạt nhân nào tới bất kỳ số điểm nào trong một mảng, nhưng lưu ý rằng nếu hai hạt nhân chồng lên nhau, chúng sẽ thêm chồng lên nhau. Bạn có thể ngưỡng này nếu bạn cần.

Các vấn đề liên quan