python - 有效地计算边界自适应邻域平均值

标签 python performance image-processing filter boundary

我有一张图像,其值范围从 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 的 提示使用额外的二值图像,实际上是在应用掩码,我偶然发现了 masked arrays 的原理。 .因此,只需要处理一个数组,因为蒙版数组将图像和蒙版数组“混合”在一起。
关于掩码数组的一个小细节:不是像上次更新那样用 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>无法处理掩码数组,因为在过滤操作期间不考虑掩码。
其他一些人也提到了这一点,比如 herehere .


图像的力量...

  • 灰色:待处理图像的范围
  • 白色:填充区域(在我的例子中填充了 2.0)
  • 红色阴影:内核的范围
    • 深红色:有效邻居
    • 浅红色:要忽略的部分邻域

enter image description here


如何更改这段相当实用的代码以提高计算性能?

非常感谢!

最佳答案

不确定这是否有帮助,因为我不精通 scipy:在灰色区域使用 1,在白色区域使用 0(源图像中也有 0)的辅助图像。然后通过简单的求和将滤镜应用于两张图像。

如果 scipy 提供具有内置求和功能的过滤器的专用版本,则有望实现加速。

完成后,您需要逐个像素地划分两个图像。

关于python - 有效地计算边界自适应邻域平均值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10683596/

相关文章:

python - 如何修复游戏中的此语法错误?

python - 使用带有 df.loc == 语句的append() Pandas Python

python - 是否可以通过在脚本中包含一行来调用 virtualenv 的 python 解释器?

python - Numpy 和 matlab polyfit 结果差异

performance - VS 性能不佳 - IsAssertEtwEnabled 上的高 CPU

c++ - 如何混合 OpenCV 1.0 和 OpenCV 2.0

python - Numpy - 通过测试相邻索引获取索引位置

java - Java JVM 是否执行任何特化或部分评估类型优化?

mysql - 如何提高基于字符串的查询连接的性能?

image - 如何在 MATLAB 中根据固定图像的细节分割运动图像的一部分?