2014-01-28 59 views
1

我正在嘗試爲一個任務寫一個非本地平均值過濾器。我用兩種方法編寫了代碼,但我期望更快的方法比其他方法慢得多。在MATLAB中的非本地平均值過濾器優化

方法1:(此方法比較慢)

for i = 1:size(I,1) 
    tic 
    sprintf('%d/%d',i,size(I,1)) 
    for j = 1:size(I,2) 
     w = exp((-abs(I-I(i,j))^2)/(h^2)); 

     Z = sum(sum(w)); 
     w = w/Z; 

     sumV = w .* I; 

     NL(i,j) = sum(sum(sumV)); 
    end 
    toc 
end 

方法2:(此方法速度更快)

for i = 1:size(I,1) 
    tic 
    sprintf('%d/%d',i,size(I,1)) 
    for j = 1:size(I,2) 
     Z = 0; 
     for k = 1:size(I,1) 
      for l = 1:size(I,2) 
       w = exp((-abs(I(i,j)-I(k,l))^2)/(h^2)); 

       Z = Z + w; 
      end 
     end 

     sumV = 0; 
     for k = 1:size(I,1) 
      for l = 1:size(I,2) 
       w = exp((-abs(I(i,j)-I(k,l))^2)/(h^2)); 
       w = w/Z; 

       sumV = sumV + w * I(k,l); 
      end 
     end 

     NL(i,j) = sumV; 
    end 
    toc 
end 

我真的以爲MATLAB會爲矩陣運算進行優化。它有沒有理由不在這個代碼中?差別非常大。對於512x512形象,h = 0.05,外循環的一次迭代需要24-28秒的方法1和10-12秒的方法2

+0

第二種方法中的「h」是什麼? –

+0

'h'是非局部均值濾波參數。對於這兩種方法,'h = 0.05'。 – shashwat

回答

3

這兩種方法沒有做同樣的事情。在方法2中,w=表達式中的術語abs(I(i,j)-I(k,l))正在平方,這很好,因爲該術語只是單個數值。

然而,在方法1中,術語abs(I-I(i,j))實際上是(數字值I(i,j)正在從每個元素中減去在基質I,再次返回一個矩陣)的矩陣。所以,當這個術語與^算子平方時,就會發生矩陣乘法。根據方法2,我的猜測是,這不是你想要的。相反,如果要將矩陣中的每個元素平方,則使用.^運算符,如abs(I-I(i,j)).^2

矩陣乘法是一個計算量更大的操作,這可能就是爲什麼方法1需要更長的時間。

+0

哦!謝謝!我確實打算進行按期乘法。 '。^'將運行時間縮短到2-3秒! – shashwat

0

我的猜測是,你有沒有預先分配NL,這兩種方法都在同一個函數(或者是腳本,並且在功能運行之間沒有清除NL)。這會使第一種方法減慢很多。

請嘗試以下操作:爲兩種方法創建一個函數。運行每個方法一次。然後使用profiler來查看每個函數花費大部分時間的位置。

+0

它們是獨立的功能,而不是腳本。在兩種情況下,我都將NL初始化爲「零」。我會嘗試'探查器'並回復你。 – shashwat

0

更快的實現(矢量化)可以用im2col實現:

  1. 出每個街區的創建矢量。
  2. 使用預定義的索引計算每個補丁之間的距離。
  3. 使用sum函數求和的值和權重。

這種方法根本沒有迴路。