根据放置在像素

时间:2017-01-11 05:00:35

标签: numpy

问题

我有一个任意半径的圆形布尔蒙版(总是完全对称):

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

然后我有一个uint8的大矩阵,image和这个矩阵中的一对可以是它的任何有效指标,point

我想要做的是在图像中的这一点上应用此蒙版,这样我就可以在image中的那个点上放置一个圆圈。

这在图像中间非常简单。你可以这样做:

image[point[0] - radius:point[0] + radius + 1, point[1] - radius:point[1] + radius + 1] = circle_mask

但自然这不会处理边界检查,在这种情况下看起来相当复杂,因为我必须确保我们分配的image范围与分配的掩码大小相同

实施例

如果point(1, 1)且圆形遮罩的半径为2,则假设image最初全为零,则最终为:

array([[ 1.,  1.,  1.,  0.,  0.,  ... ,  0.],
       [ 1.,  1.,  1.,  1.,  0.,  ... ,  0.],
       [ 1.,  1.,  1.,  0.,  0.,  ... ,  0.],
       [ 0.,  1.,  0.,  0.,  0.,  ... ,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  ... ,  0.],
       ...,
       [ 0.,  0.,  0.,  0.,  0.,  ... ,  0.]])

我的解决方案

我已经提出了以下代码来实现我想要做的事情:

# Initialization of stuff so this is runnable
point = (1, 1)
radius = 2
image = np.zeros((10, 10))
x, y = np.ogrid[-radius : radius + 1, -radius : radius + 1]
circle_mask = x**2 + y**2 <= radius**2

# My solution to the problem
image_min_row = max(point[0] - radius, 0)
image_min_col = max(point[1] - radius, 0)
image_max_row = min(point[0] + radius + 1, image.shape[0])
image_max_col = min(point[1] + radius + 1, image.shape[1])

mask_min_row = max(radius - point[0], 0)
mask_min_col = max(radius - point[1], 0)
mask_max_row = min(image.shape[0] - point[0] + radius, circle_mask.shape[0])
mask_max_col = min(image.shape[1] - point[1] + radius, circle_mask.shape[1])

temp_mask = circle_mask[mask_min_row:mask_max_row, mask_min_col:mask_max_col]
image[image_min_row:image_max_row, image_min_col:image_max_col][temp_mask] = 1

我的问题

我的解决方案感觉非常冗长。当我想出它时,它花了很多头脑伤害的算术争吵并且有一些一个一个一个的错误。我怀疑是否有更简单的方法来做到这一点。我可以采取掩码的一些方法,定位它以使其中心超过point并根据该掩码分配值,忽略超出界限的元素。

NumPy有办法做到这一点吗?

2 个答案:

答案 0 :(得分:3)

可以根据图像的索引直接创建遮罩,从而消除了绑定检查:

x = np.arange(image.shape[0]) 
y = np.arange(image.shape[1])
image[np.add.outer((x-point[0])**2, (y-point[1])**2) <= radius**2] = 1

这里x,y是image数组的索引,并且在第三行中说明了应该进行赋值的条件。

答案 1 :(得分:2)

以下是使用Scipy's binary-dilation处理多个点的方法 -

from scipy.ndimage.morphology import binary_dilation as dilate

mask_mapped = np.zeros(image.shape,dtype=bool)
mask_mapped[points[...,0],points[...,1]] = 1
image[dilate(mask_mapped,circle_mask)] = 1 

示例运行

案例#1:有一点 -

In [88]: points = np.array([1,1])

In [89]: image = np.zeros((10, 10))

In [90]: mask_mapped = np.zeros(image.shape,dtype=bool)
    ...: mask_mapped[points[...,0],points[...,1]] = 1
    ...: image[dilate(mask_mapped,circle_mask)] = 1
    ...: 

In [91]: print image
[[ 1.  1.  1.  0.  0.  0.  0.  0.  0.  0.]
 [ 1.  1.  1.  1.  0.  0.  0.  0.  0.  0.]
 [ 1.  1.  1.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  1.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]]

案例#2:多点 -

In [96]: points = np.array([[1,1],[7,3],[8,9]])

In [97]: image = np.zeros((10, 10))

In [98]: mask_mapped = np.zeros(image.shape,dtype=bool)
    ...: mask_mapped[points[...,0],points[...,1]] = 1
    ...: image[dilate(mask_mapped,circle_mask)] = 1
    ...: 

In [99]: print image
[[ 1.  1.  1.  0.  0.  0.  0.  0.  0.  0.]
 [ 1.  1.  1.  1.  0.  0.  0.  0.  0.  0.]
 [ 1.  1.  1.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  1.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  1.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  1.  1.  1.  0.  0.  0.  0.  1.]
 [ 0.  1.  1.  1.  1.  1.  0.  0.  1.  1.]
 [ 0.  0.  1.  1.  1.  0.  0.  1.  1.  1.]
 [ 0.  0.  0.  1.  0.  0.  0.  0.  1.  1.]]

如果你从一个zeros初始化数组开始作为图像,你可以简单地使用扩大的二进制数组作为图像,就像这样 -

In [102]: print dilate(mask_mapped,circle_mask).astype(float)
[[ 1.  1.  1.  0.  0.  0.  0.  0.  0.  0.]
 [ 1.  1.  1.  1.  0.  0.  0.  0.  0.  0.]
 [ 1.  1.  1.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  1.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  0.  1.  0.  0.  0.  0.  0.  0.]
 [ 0.  0.  1.  1.  1.  0.  0.  0.  0.  1.]
 [ 0.  1.  1.  1.  1.  1.  0.  0.  1.  1.]
 [ 0.  0.  1.  1.  1.  0.  0.  1.  1.  1.]
 [ 0.  0.  0.  1.  0.  0.  0.  0.  1.  1.]]