【问题标题】:Calculate mean across area in a 2D array计算二维数组中跨区域的平均值
【发布时间】:2016-05-11 02:57:16
【问题描述】:

简而言之:我需要一个快速(预编译)函数,例如来自 OpenCV 的 filter2ddouble 类型 输出。不是整数

详情: 我有 numpy 数组,它存储来自 OpenCV 的单色图像。

我需要像这样计算一些正方形(例如)内核的矩阵平均值:

kernel size = (3,3)

输入数组:

[[13 10 10 10]
 [12 10 10  8]
 [ 9  9  9  9]
 [ 9 10 10  9]]

输出数组:

[[ 10.22222222   9.44444444]
 [  9.77777778   9.33333333]]

例如:10.22222 = (13+10+10+12+10+10+9+9+9)/9

我写了这个函数:

def smooth_filt(src,area_x,area_y):
    y,x = src.shape
    x_lim = int(area_x/2)
    y_lim = int(area_y/2)
    result = np.zeros((y-2*y_lim,x-2*x_lim), dtype=np.float64)

    for x_i in range(x_lim,x-x_lim):
        for y_i in range(y_lim,y-y_lim):
            result[y_i-y_lim, x_i-x_lim] = np.mean(src[y_i-y_lim:y_i+area_y-y_lim,x_i-x_lim:x_i+area_x-x_lim])
    return result

但这还不够快。

请告诉我是否有更快的计算方法。

答案: 我检查所有方法。可以看代码:http://pastebin.com/y5dEVbzX

并确定模糊是最强大的方法,它几乎与内核大小无关。

用不同方法处理一个图像的图表。测试集是 298 张图片。

【问题讨论】:

  • 您可以使用一个仅系数等于 1/9 的卷积矩阵,然后将结果相加得到均值

标签: python opencv numpy scipy


【解决方案1】:

以块为单位计算平均值只是将图像与 一个恒定的内核。 您可以为此使用scipy.signal.convolve2d

from scipy.signal import convolve2d
kernel = np.ones((3,3)) / 9.
out = convolve2d(img, kernel, mode='valid')

mode='valid' 参数仅用于获取您感兴趣的部分结果。

【讨论】:

  • 谢谢!目前是最好的答案。第二天我决定它是否是解决方案。
【解决方案2】:

看看scipy.signal.convolve2d。这很简单:

import numpy as np
import scipy.signal as ss

data = np.array([[13, 10, 10, 10],
                 [12, 10, 10,  8],
                 [ 9,  9,  9,  9],
                 [ 9, 10, 10,  9]])
kernel = np.ones((3,3))
kernel /= kernel.size

ss.convolve2d(data, kernel, mode='valid')

这给了

array([[ 10.22222222,   9.44444444],
       [  9.77777778,   9.33333333]])

【讨论】:

    【解决方案3】:

    如果您对 OpenCV 解决方案感兴趣:您需要的函数是 cv2.blur。 在大多数情况下,它必须比卷积更快,因为它对归一化内核有单独的优化(系数之和等于 1)。

    blurred = cv2.blur(img,(3,3))
    

    查看关于平滑的精彩教程here

    【讨论】:

    • 谢谢。但 cv2.blur 只返回 int 值。
    • @gelezko 如果将图像转换为浮点型或双精度型,输出也将是浮点型或双精度型。
    • 我认为这是最强大的方法。谢谢!我知道模糊,但我不知道它适用于浮动。
    【解决方案4】:

    您可以利用integral function,以计算(0,0)到(i,j)元素的值之和。

    使用这些积分图像,可以在恒定的时间 em>

    中计算图像的特定上右或旋转矩形区域上的总和,平均值和标准偏差

    如果“内核”大小是恒定的m,则乘以1/M^2以简化平均计算的乘法矩阵。

    要在某些窗口中获取总和(x1,y1) - (x2,y2),只查找
    S((x1,y1)-(x2,y2)) = I(x1,y1) + I(x2,y2) - I(x1,y2) - I(x2,y1)
    

    伪代码:

    integral(src, sum)
    multvalue = 1/(kernelsize*kernelsize)
    sum = sum * multvalue
    for every (x = 0..n-kernelsize-1, y = 0..n-kernelsize-1)
       mean[x,y] =  sum[x,              y] 
                  + sum[x + kernelsize, y + kernelsize] 
                  - sum[x,              y + kernelsize] 
                  - sum[x + kernelsize, y]
    

    【讨论】:

    • 有趣的解决方案。如果可以 - 请提供更多详细信息(我谈论代码) span>
    • 我不知道python足够 - 请参阅简单的伪码 span>
    • 怀疑那个时间如此大(100倍)由于慢矩阵访问方法在这里:means[x,y] = src_integral[x,y] ...。 (内置函数,如blur在C代码中直接访问) span>
    猜你喜欢
    • 2013-03-27
    • 1970-01-01
    • 2019-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多