我有一个值从 0 到 1 的图像。我喜欢做的是简单的平均。
但是,更具体地说,对于图像边界处的单元格,我想计算位于图像范围内的邻域/内核部分的像素平均值。事实上,这归结为适应“平均公式”的分母,即总和除以的像素数。
我设法做到这一点,如下所示scipy.ndimage.generic_filter
,但这远非省时。
def fnc(buffer, count):
n = float(sum(buffer < 2.0))
sum = sum(buffer) - ((count - b) * 2.0)
return (sum / n)
avg = scipy.ndimage.generic_filter(image, fnc, footprint = kernel, \
mode = 'constant', cval = 2.0, \
extra_keywords = {'count': countkernel})
细节
kernel
= 方阵(圆圈由一表示)- 用 2 填充而不是用零填充,从那时起我无法正确分离填充区域的零和实际栅格的零
countkernel
= 中的个数kernel
n
image
=通过排除由值 2 标识的填充区域的单元格,位于其中的单元格数sum
通过从原始邻域总和中减去(填充单元数 * 2.0)来纠正
更新)
1) 使用 NaN 填充使计算量增加约 30%:
def fnc(buffer):
return (numpy.nansum(buffer) / numpy.sum([~numpy.isnan(buffer)]))
avg = scipy.ndimage.generic_filter(image, fnc, footprint = kernel, \
mode = 'constant', cval = float(numpy.nan)
2)应用Yves Daoust提出的解决方案(已接受的答案),无疑将处理时间减少到最低限度:
def fnc(buffer):
return numpy.sum(buffer)
sumbigimage = scipy.ndimage.generic_filter(image, fnc, \
footprint = kernel, \
mode = 'constant', \
cval = 0.0)
summask = scipy.ndimage.generic_filter(mask, fnc, \
footprint = kernel, \
mode = 'constant', \
cval = 0.0)
avg = sumbigimage / summask
3) 基于Yves 的提示使用附加的二值图像,实际上是在应用掩码,我偶然发现了掩码数组的原理。因此,只需处理一个数组,因为掩码数组将图像和掩码数组“混合”在一起。
关于掩码数组的一个小细节:不要像之前的更新那样用 1 填充内部(原始图像的范围)并用 0 填充外部(边框),反之亦然。掩码数组中的 1 表示“无效”,0 表示“有效”。
此代码甚至比更新 2 中提供的代码快 50%):
maskedimg = numpy.ma.masked_array(imgarray, mask = maskarray)
def fnc(buffer):
return numpy.mean(buffer)
avg = scipy.ndimage.generic_filter(maskedimg, fnc, footprint = kernel, \
mode = 'constant', cval = 0.0)
--> 我必须在这里纠正自己!
在验证过程中我一定是误会了,因为在运行了一些计算之后,似乎scipy.ndimage.<filters>
无法处理 masked_arrays,因为在过滤操作期间没有考虑掩码。
其他一些人也提到了这一点,比如这里和这里。
图像的力量...
- 灰色:要处理的图像范围
- 白色:填充区域(在我的情况下填充 2.0)
- 红色阴影:内核范围
- 深红色:有效邻居
- 浅红色:邻里的一部分被忽略
如何更改这段相当实用的代码以提高计算性能?
提前谢谢了!