2016-02-02 57 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 –