Python: 仅在图像蒙版内执行模糊
Python: perform blur only within a mask of image
我有一张灰度图像和该图像中 ROI 的二进制掩码。我想对灰度图像执行模糊操作,但只能在蒙版的范围内进行。现在我正在模糊整个图像,而不是仅仅删除蒙版外的项目,但我不希望蒙版外的像素影响我的投资回报率。有没有办法在不构建自定义模糊函数的情况下做到这一点?
希望得到类似的东西:
import scipy
blurredImage = scipy.ndimage.filters.gaussian_filter(img, sigma = 3, weight = myMask)
@stefan:
blur = 3
invmask = np.logical_not(mask).astype(int)
masked = img * mask
remaining = img * invmask
blurred = scipy.ndimage.filters.gaussian_filter(masked, sigma = blur)
blurred = blurred+remaining
扩张方法:
blur = 3
invmask = np.logical_not(mask).astype(int)
masked = img * mask
masked2 = scipy.ndimage.morphology.grey_dilation(masked,size=(5,5))
masked2 = masked2 *invmask
masked2 = masked + masked2
blurred = scipy.ndimage.filters.gaussian_filter(masked2, sigma = blur)
您想要实现的目标并不像您想象的那么容易和明确。
模糊操作对应于每个像素邻域中像素的某种(各向同性)平均。但是在域的边界附近,邻域是不完整的,你需要修复它
通过局部重新定义滤波器系数来避免"querying"外像素;一种简单的方法是将这些像素的过滤器权重设置为零;或
通过外推 ROI 之外的像素值。这应该以避免沿边界不连续的方式完成,例如通过泊松重建。
对于第一种方法,你可以像下面这样劫持标准过滤器:
将外部像素设置为0并模糊整个图像;当过滤器跨越轮廓时,您将仅获得内部权重和内部像素的组合;
将内部像素设置为1并模糊图像;您只会得到内部权重的总和;
取两个模糊图像的比率,以便正确重新归一化权重。
如果图像是整数类型,请使用 255 而不是 1 以保持足够的准确性。请注意,在 ROI 之外,比率的分母为零。
将线性滤波器应用于有限域的正确方法是使用 Normalized Convolution。该方法计算每个邻域内的(加权)均值,然后通过该邻域中存在的(加权)像素数进行归一化。它仅使用过滤器的两个应用程序和一些微不足道的每像素操作来实现:
# normalized convolution of image with mask
filter = scipy.ndimage.filters.gaussian_filter(img * mask, sigma = blur)
weights = scipy.ndimage.filters.gaussian_filter(mask, sigma = blur)
filter /= weights
# after normalized convolution, you can choose to delete any data outside the mask:
filter *= mask
请注意,mask
不必只是 0 和 1,它可以包含表明 "certain" 您对该像素值正确性的评价的中间值。但通常 "missing data" 为 0,可用数据为 1。
gaussian_filter
必须以浮点格式进行计算,return 必须以浮点值图像进行计算。整数运算不会在这里做正确的事情。
这是一个例子:
第二张图:普通过滤,然后去除遮罩外的东西。这说明mask外的数据影响了过滤的结果。
第三张图片:普通过滤,但首先将遮罩外的东西设置为零。这表明掩码外的零影响了过滤的结果。
第4张图:使用归一化卷积:masked区域外的数据完全不影响过滤
我有一张灰度图像和该图像中 ROI 的二进制掩码。我想对灰度图像执行模糊操作,但只能在蒙版的范围内进行。现在我正在模糊整个图像,而不是仅仅删除蒙版外的项目,但我不希望蒙版外的像素影响我的投资回报率。有没有办法在不构建自定义模糊函数的情况下做到这一点?
希望得到类似的东西:
import scipy
blurredImage = scipy.ndimage.filters.gaussian_filter(img, sigma = 3, weight = myMask)
@stefan:
blur = 3
invmask = np.logical_not(mask).astype(int)
masked = img * mask
remaining = img * invmask
blurred = scipy.ndimage.filters.gaussian_filter(masked, sigma = blur)
blurred = blurred+remaining
扩张方法:
blur = 3
invmask = np.logical_not(mask).astype(int)
masked = img * mask
masked2 = scipy.ndimage.morphology.grey_dilation(masked,size=(5,5))
masked2 = masked2 *invmask
masked2 = masked + masked2
blurred = scipy.ndimage.filters.gaussian_filter(masked2, sigma = blur)
您想要实现的目标并不像您想象的那么容易和明确。
模糊操作对应于每个像素邻域中像素的某种(各向同性)平均。但是在域的边界附近,邻域是不完整的,你需要修复它
通过局部重新定义滤波器系数来避免"querying"外像素;一种简单的方法是将这些像素的过滤器权重设置为零;或
通过外推 ROI 之外的像素值。这应该以避免沿边界不连续的方式完成,例如通过泊松重建。
对于第一种方法,你可以像下面这样劫持标准过滤器:
将外部像素设置为0并模糊整个图像;当过滤器跨越轮廓时,您将仅获得内部权重和内部像素的组合;
将内部像素设置为1并模糊图像;您只会得到内部权重的总和;
取两个模糊图像的比率,以便正确重新归一化权重。
如果图像是整数类型,请使用 255 而不是 1 以保持足够的准确性。请注意,在 ROI 之外,比率的分母为零。
将线性滤波器应用于有限域的正确方法是使用 Normalized Convolution。该方法计算每个邻域内的(加权)均值,然后通过该邻域中存在的(加权)像素数进行归一化。它仅使用过滤器的两个应用程序和一些微不足道的每像素操作来实现:
# normalized convolution of image with mask
filter = scipy.ndimage.filters.gaussian_filter(img * mask, sigma = blur)
weights = scipy.ndimage.filters.gaussian_filter(mask, sigma = blur)
filter /= weights
# after normalized convolution, you can choose to delete any data outside the mask:
filter *= mask
请注意,mask
不必只是 0 和 1,它可以包含表明 "certain" 您对该像素值正确性的评价的中间值。但通常 "missing data" 为 0,可用数据为 1。
gaussian_filter
必须以浮点格式进行计算,return 必须以浮点值图像进行计算。整数运算不会在这里做正确的事情。
这是一个例子:
第二张图:普通过滤,然后去除遮罩外的东西。这说明mask外的数据影响了过滤的结果。
第三张图片:普通过滤,但首先将遮罩外的东西设置为零。这表明掩码外的零影响了过滤的结果。
第4张图:使用归一化卷积:masked区域外的数据完全不影响过滤