2016-02-02 30 views
3

我需要像filter2d从OpenCV的快速(预编译)函数双型输出。不是整数计算跨越区域意味着在简而言之2D阵列

细节: 我有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

+1

您可以使用卷积矩阵等于只系数1/9然后求和结果得到平均值 – Pierre

回答

3

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

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

查看关于平滑here不错的教程。

+0

谢谢。但cv2.blur只返回int值。 –

+0

@gelezko如果将图像转换为float或double类型,则输出也将为float或double。 – Miki

+0

我决定这是最强大的方法。谢谢!我知道模糊,但我不知道它与浮动。 –

4

计算块的平均值是简单地将图像与 一个常数内核卷积。 可以使用scipy.signal.convolve2d此:

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

mode='valid'参数要求只得到你感兴趣的结果的一部分

+0

谢谢!目前这是最好的答案。在第二天,我决定它是否是解决方案。 –

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

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

使用这些积分图像,可以计算总和,平均值和标准偏差在特定右上方或一定时间内

旋转的图像的矩形区域。如果“仁”的大小是常数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] 
+0

有趣的解决方案。如果可以 - 请提供更多详细信息(我会谈论代码) –

+0

我不太了解Python - 请参阅简单的伪代码 – MBo

+0

python实现http://pastebin.com/y5dEVbzX –