如何将圆盘形状的掩模应用到numpy阵列上?

时间:2022-08-07 19:37:40

I have an array like this:

我有一个这样的数组:

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

I'm creating a disc shaped mask with radius 3 thus:

我创建了一个半径为3的圆盘形面具

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

This gives:

这给:

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

Now, I want to be able to apply this mask to my array, using any element as a center point. So, for example, with center point at (1,1), I want to get an array like:

现在,我希望能够将这个掩码应用到我的数组中,使用任何元素作为中心点。例如,如果中心点在(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.]])

Is there an easy way to apply this mask?

有什么简单的方法来应用这个面具吗?

Edit: I shouldn't have mixed booleans and floats - it was misleading.

编辑:我不应该混合布尔值和浮点值-这是误导。

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

This is more the result I require.

这是我需要的结果。

array[mask] = 255

数组(面具)= 255

will mask the array using centre point (0+radius,0+radius).

将使用中心点(0+半径,0+半径)对数组进行掩码。

However, I'd like to be able to place any size mask at any point (y,x) and have it automatically trimmed to fit.

然而,我希望能够在任何一点(y,x)上放置任何尺寸的面具,并自动调整以适合。

6 个解决方案

#1


50  

I would do it like this, where (a, b) is the center of your mask:

我会这样做,(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

#2


7  

I just wanted to share with everyone a slightly more advanced application of this technique that I just had to face.

我只是想和大家分享一个稍微高级一点的技术应用,这是我必须面对的。

My problem was to apply this circular kernel to compute the mean of all the values surrounding each point in a 2D matrix. The kernel generated can be passed to scipy's generic filter in the following way:

我的问题是用这个圆核来计算二维矩阵中每个点的均值。生成的内核可以通过以下方式传递给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)

Hope this helps!

希望这可以帮助!

#3


3  

To put it one convenient function:

使它具有一个方便的功能:

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

Returns the pixel sum within radius, or return(array[mask] = 2) for whatever need.

返回半径内的像素和,或者返回(array[mask] = 2)以满足任何需要。

#4


3  

You could use scipy's convolve function, which has the benefit of allowing you to place any particular mask, aka kernel, on any number of given coordinates in your array, all at once:

你可以使用scipy的convolve函数,它的好处是允许你在数组中任意给定的坐标上同时放置任何特定的掩码,也就是内核:

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

First create a coordinate array with the coordinate of where you want the mask (kernel) to be centered marked as 2

首先创建一个坐标数组,其坐标为您希望将掩码(内核)居中标记为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.]]

Create your mask:

创建你的面具:

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 the two images:

盘旋的两个图片:

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

Note that the convolve function entries do not commute, i.e. convolve(a,b) != convolve(b,a)

注意,convolve函数项不交换,即convolve(a,b) != convolve(b,a)

Note also that if your point is near an edge, the algo does not reproduce the kernel at the coordinate. To get around this you can pad the background by the largest axis of your kernel, apply the convolution, then remove the padding.

还要注意,如果你的点靠近一条边,那么algo不会在坐标上复制内核。要解决这个问题,你可以用内核的最大轴填充背景,应用卷积,然后删除填充。

Now, you can map any kernel to any number of points in an array, but note that if two kernels overlap, they add at the overlap. You can threshold this if you need.

现在,您可以将任何内核映射到数组中的任意数量的点,但是请注意,如果两个内核重叠,它们会在重叠处添加。如果需要,可以设置这个阈值。

#5


2  

Did you try making a mask or zeroes and ones and then using per-element array multiplication? This is the canonical way, more or less.

你试过做一个蒙版或者0和1然后使用每个元素的数组乘法吗?这是典型的方式,或多或少。

Also, are you certain you want a mix of numbers and booleans in a numpy array? NumPy, as the name implies, works best with numbers.

另外,您确定要在numpy数组中混合数字和布尔值吗?NumPy,顾名思义,最适合于数字。

#6


0  

To get the same result as in your example, you can do something like this:

要得到与示例相同的结果,您可以这样做:

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

#1


50  

I would do it like this, where (a, b) is the center of your mask:

我会这样做,(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

#2


7  

I just wanted to share with everyone a slightly more advanced application of this technique that I just had to face.

我只是想和大家分享一个稍微高级一点的技术应用,这是我必须面对的。

My problem was to apply this circular kernel to compute the mean of all the values surrounding each point in a 2D matrix. The kernel generated can be passed to scipy's generic filter in the following way:

我的问题是用这个圆核来计算二维矩阵中每个点的均值。生成的内核可以通过以下方式传递给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)

Hope this helps!

希望这可以帮助!

#3


3  

To put it one convenient function:

使它具有一个方便的功能:

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

Returns the pixel sum within radius, or return(array[mask] = 2) for whatever need.

返回半径内的像素和,或者返回(array[mask] = 2)以满足任何需要。

#4


3  

You could use scipy's convolve function, which has the benefit of allowing you to place any particular mask, aka kernel, on any number of given coordinates in your array, all at once:

你可以使用scipy的convolve函数,它的好处是允许你在数组中任意给定的坐标上同时放置任何特定的掩码,也就是内核:

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

First create a coordinate array with the coordinate of where you want the mask (kernel) to be centered marked as 2

首先创建一个坐标数组,其坐标为您希望将掩码(内核)居中标记为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.]]

Create your mask:

创建你的面具:

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 the two images:

盘旋的两个图片:

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

Note that the convolve function entries do not commute, i.e. convolve(a,b) != convolve(b,a)

注意,convolve函数项不交换,即convolve(a,b) != convolve(b,a)

Note also that if your point is near an edge, the algo does not reproduce the kernel at the coordinate. To get around this you can pad the background by the largest axis of your kernel, apply the convolution, then remove the padding.

还要注意,如果你的点靠近一条边,那么algo不会在坐标上复制内核。要解决这个问题,你可以用内核的最大轴填充背景,应用卷积,然后删除填充。

Now, you can map any kernel to any number of points in an array, but note that if two kernels overlap, they add at the overlap. You can threshold this if you need.

现在,您可以将任何内核映射到数组中的任意数量的点,但是请注意,如果两个内核重叠,它们会在重叠处添加。如果需要,可以设置这个阈值。

#5


2  

Did you try making a mask or zeroes and ones and then using per-element array multiplication? This is the canonical way, more or less.

你试过做一个蒙版或者0和1然后使用每个元素的数组乘法吗?这是典型的方式,或多或少。

Also, are you certain you want a mix of numbers and booleans in a numpy array? NumPy, as the name implies, works best with numbers.

另外,您确定要在numpy数组中混合数字和布尔值吗?NumPy,顾名思义,最适合于数字。

#6


0  

To get the same result as in your example, you can do something like this:

要得到与示例相同的结果,您可以这样做:

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