我有一张图像,其值范围为 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})
Details
-
kernel
= 方阵(用 1 表示圆)
- 用 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)应用提出的解决方案伊夫·达乌斯特(接受的答案),绝对可以将处理时间减少到最低限度:
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'提示使用额外的二值图像,这实际上是应用掩模,我偶然发现了这个原理屏蔽数组 http://docs.scipy.org/doc/numpy/reference/maskedarray.html。因此,只需处理一个数组,因为屏蔽数组将图像和屏蔽数组“混合”在一起。
关于掩码数组的一个小细节:您必须反之亦然,而不是像之前的更新那样用 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,因为在过滤操作期间不考虑掩码。
其他一些人也提到了这一点,比如here http://projects.scipy.org/scipy/ticket/1155 and here http://old.nabble.com/ndimage-aware-of-masked-arrays--td25803414.html.
图像的力量...
- 灰色:要处理的图像范围
- 白色:填充区域(在我的例子中填充了 2.0)
- red shades: extent of kernel
如何更改这段相当实用的代码以提高计算性能?
提前谢谢了!