计算2D阵列中跨区域的平均值

时间:2016-02-02 10:41:37

标签: python opencv numpy scipy

简而言之:我需要一个快速(预编译)功能,例如来自OpenCV的 filter2d ,带有 double type 输出。不是整数

详情: 我有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张图片。 enter image description here

4 个答案:

答案 0 :(得分:4)

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

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

mode='valid'参数只需要获取您感兴趣的结果部分。

答案 1 :(得分:3)

看看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]])

答案 2 :(得分:3)

如果您对OpenCV解决方案感兴趣:您需要的功能是cv2.blur。 对于大多数情况,它必须比卷积更快,因为它对标准化内核进行了单独的优化(系数之和等于1)。

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

请参阅有关平滑here的精彩教程。

答案 3 :(得分:1)

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

使用这些积分图像,您可以在恒定时间内计算图像特定右上角或旋转矩形区域的和,平均值和标准偏差

如果"内核" size是常数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]