6

我有一个值从 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
  • nimage=通过排除由值 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)
  • 红色阴影:内核范围
    • 深红色:有效邻居
    • 浅红色:邻里的一部分被忽略

在此处输入图像描述


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

提前谢谢了!

4

2 回答 2

1

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

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

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

于 2012-05-24T09:02:51.460 回答
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

于 2015-06-15T19:06:25.470 回答