我正在尝试创建抗锯齿(加权而非 bool 值)圆形掩码以制作用于卷积的圆形内核。
radius = 3 # no. of pixels to be 1 on either side of the center pixel
# shall be decimal as well; not the real radius
kernel_size = 9
kernel_radius = (kernel_size - 1) // 2
x, y = np.ogrid[-kernel_radius:kernel_radius+1, -kernel_radius:kernel_radius+1]
dist = ((x**2+y**2)**0.5)
mask = (dist-radius).clip(0,1)
print(mask)
输出是
array([[1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. ],
[1. , 1. , 0.61, 0.16, 0. , 0.16, 0.61, 1. , 1. ],
[1. , 0.61, 0. , 0. , 0. , 0. , 0. , 0.61, 1. ],
[1. , 0.16, 0. , 0. , 0. , 0. , 0. , 0.16, 1. ],
[1. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 1. ],
[1. , 0.16, 0. , 0. , 0. , 0. , 0. , 0.16, 1. ],
[1. , 0.61, 0. , 0. , 0. , 0. , 0. , 0.61, 1. ],
[1. , 1. , 0.61, 0.16, 0. , 0.16, 0.61, 1. , 1. ],
[1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 1. ]])
然后我们可以做
mask = 1 - mask
print(mask)
得到
array([[0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ],
[0. , 0. , 0.39, 0.84, 1. , 0.84, 0.39, 0. , 0. ],
[0. , 0.39, 1. , 1. , 1. , 1. , 1. , 0.39, 0. ],
[0. , 0.84, 1. , 1. , 1. , 1. , 1. , 0.84, 0. ],
[0. , 1. , 1. , 1. , 1. , 1. , 1. , 1. , 0. ],
[0. , 0.84, 1. , 1. , 1. , 1. , 1. , 0.84, 0. ],
[0. , 0.39, 1. , 1. , 1. , 1. , 1. , 0.39, 0. ],
[0. , 0. , 0.39, 0.84, 1. , 0.84, 0.39, 0. , 0. ],
[0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ]])
我现在可以对其进行归一化并将其用作卷积运算中的圆形过滤器(内核)。
注意:半径可以是小数。例如:get_circular_kernel(0.5,(5,5))
应该给出
array([[0. , 0. , 0. , 0. , 0. ],
[0. , 0.08578644, 0.5 , 0.08578644, 0. ],
[0. , 0.5 , 1. , 0.5 , 0. ],
[0. , 0.08578644, 0.5 , 0.08578644, 0. ],
[0. , 0. , 0. , 0. , 0. ]])
我想至少生成一百万个,固定kernel_size
,改变radius
,有没有更好的或更有效的方法来做到这一点? (也许没有像 sqrt 这样的昂贵操作,并且仍然保持足够精确以进行弧积分,即特定像素中曲线覆盖的区域?)
最佳答案
由于您想要生成大量具有相同大小的内核,您可以通过一步构建每个内核而不是在循环中一个接一个地构建内核来大大提高性能。给定每个内核的 num_radii
值,您可以创建一个形状为 (num_radii, kernel_size, kernel_size)
的数组。这种矢量化的代价是内存:您必须将所有这些值放入 RAM 中,否则您应该将数百万个半径分成几个较小的批处理,然后分别再次生成每个批处理。
您唯一需要更改的是获取一个半径数组(而不是标量半径),并注入(inject)两个尾随的单一维度,以便您的掩码创建触发 broadcasting :
import numpy as np
kernel_size = 9
kernel_radius = (kernel_size - 1) // 2
x, y = np.ogrid[-kernel_radius:kernel_radius+1, -kernel_radius:kernel_radius+1]
dist = (x**2 + y**2)**0.5 # shape (kernel_size, kernel_size)
# let's create three kernels for the sake of example
radii = np.array([3, 3.5, 4])[...,None,None] # shape (num_radii, 1, 1)
# using ... allows compatibility with arbitrarily-shaped radius arrays
masks = 1 - (dist - radii).clip(0,1) # shape (num_radii, kernel_size, kernel_size)
现在 masks[0,...]
(或简称 masks[0]
,但我更喜欢显式版本)包含您问题中的示例掩码,和 masks[1,...]
和 masks[2,...]
包含半径 3.5
和 4 的内核
,分别。
关于python - 高效创建抗锯齿圆形蒙版,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51002815/