2013-01-18 92 views
1

我正在做一些視頻處理,我需要獲得每個幀的雙變量函數的梯度。 該函數被表示爲雙精度的二維數組。其中域是行和列索引,範圍是相應索引值的雙倍值。或者更簡單地說,功能fdouble[][] matrix這樣定義:獲取雙變量函數的梯度

f(x,y)=matrix[x][y]

我試圖使用它在Apache共享數學庫:

SmoothingPolynomialBicubicSplineInterpolator iterpolator = new SmoothingPolynomialBicubicSplineInterpolator(); 
BicubicSplineInterpolatingFunction f = iterpolator.interpolate(xs, ys, matrix.getData()); 
    for (int i = 0; i < ans.length; i++) { 
     for (int j = 0; j < ans[0].length; j++) { 
      ans[i][j] = f.partialDerivativeY(i, j); 
     } 
    } 
  • 與XS,作爲x索引的排序陣列(0,1,...,matrix.getRowDimension() - 1)
  • ys在列維上相同(0,1,...,matrix.getColumnDimension() - 1)

問題是,對於大小爲150X80的典型矩陣,運行需要多達1.4秒,這使得它與我的需求完全無關。所以,作爲這個庫的新手用戶,以及一般的編程數值分析,我想知道:

  1. 我做錯了什麼?
  2. 是否有另一種更快的方式可以完成此任務?
  3. 是否有另一個提供解決方案的開源庫(最好是maven友好的)?
+1

1)你確定你需要每個點的漸變嗎?無論你做什麼,都是歐米茄(NM)。 2)爲什麼插值?你有沒有試過更直接的方法來計算偏導數(組成梯度)? 3)你有沒有介紹1.4秒鐘內大部分時間? – davin

+0

1.我確實需要所有這些要點。 2.我正在插入以獲取公共數學API的函數表示形式,而不是因爲真的需要我。 3.時間進入插值命令,但正如我所看到的,我必須使用它來使用公共數學函數。我想聽聽更直接的方法。 – sagioto

回答

0

數值微分本身就是一個完整的主題,一個簡單的谷歌應該提供足夠的材料供您使用(只需維基可能就足夠了)。有些問題的參數是我無法知道的,所以我只能在這裏進行廣泛的說明,但是在給定點處有確定梯度的直接方法,即不需要插值的方法。請參閱維基百科的公式(範圍從簡單的f(x+1)-f(x),其中h=1到更高階的公式)。然後計算偏導數是一個簡單的O(NM)循環,裏面有一個超級簡單公式(不需要內插)。

的細節可以得到砂礫:

  1. 高階公式需要爲邊緣被減少,或完全 丟棄。
  2. 您的精確速度要求可能會導致更復雜的公式無用(取決於平臺,有時高階公式的查找時間會使它們太慢;同樣,這取決於緩存等)。這很容易測試,公式很簡單;編碼他們和基準。
  3. 具體實現還取決於您的錯誤要求。該理論提供了誤差界限,以便在您需要的公式中扮演角色;但是再次,速度要求是一個折衷。反過來,如果你知道關於你將要處理的矩陣類型的具體細節,可以實際降低,如果這樣的事情是已知的。

如果你有現有的卷積工具,實現可以變得更容易(也許更快),因爲這種方法實際上只是矩陣的卷積(注意;技術上它被稱爲互相關)。