有效地计算边界适应的邻域平均值

时间:2012-05-21 10:31:11

标签: 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 =方阵(圆圈由1表示)
  • 填充2,而不是零从那以后我无法正确分隔填充区域的零和实际栅格的零
  • countkernel = kernel
  • 中的个数
  • n = image内的单元格数,排除由值2标识的填充区域的单元格
  • 通过从原始邻域总和中减去(填充单元格数* 2.0)来纠正sum

更新

1)使用NaNs填充会使计算增加约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)

- &GT;我必须在这里纠正自己!
我必须在验证过程中弄错,因为经过一些计算运行后,似乎scipy.ndimage.<filters>无法处理masked_arrays,因为在过滤操作期间不会考虑掩码。
其他一些人也提到了这一点,例如herehere


图像的力量......

  • 灰色:要处理的图像范围
  • 白色:填充区域(在我的情况下填充2.0)
  • 红色阴影:内核的范围
    • 深红色:有效的neighbourhoud
    • 浅红色:被忽略的邻居的一部分

enter image description here


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

非常感谢提前!

2 个答案:

答案 0 :(得分:1)

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

如果scipy提供具有内置函数的过滤器的专用版本,那么加速有一些希望。

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

答案 1 :(得分:0)

我不确定这是多么有效,但我正在使用一个更简单的配方nan来处理边框和蒙版。

没有面具案例:

avg = scipy.ndimage.generic_filter(image, np.nanmean, mode='constant', cval=np.nan, footprint=kernel)

面具案例:

masked_image = np.where(mask, image, np.nan)
avg = scipy.ndimage.generic_filter(masked_image, np.nanmean, mode='constant', cval=np.nan, footprint=kernel)

您可以使用所有numpy nan个功能。