2017-04-09 69 views
2

我試圖實現在基於this OpenCV example從文檔光譜圖像濾波和複製爲方便起見,這裏:基於DFT的OpenCV的卷積偏移

void convolveDFT(InputArray A, InputArray B, OutputArray C) 
{ 
    C.create(abs(A.rows - B.rows)+1, abs(A.cols - B.cols)+1, A.type()); 
    Size dftSize; 
    // calculate the size of DFT transform 
    dftSize.width = getOptimalDFTSize(A.cols + B.cols - 1); 
    dftSize.height = getOptimalDFTSize(A.rows + B.rows - 1); 

    // allocate temporary buffers and initialize them with 0's 
    Mat tempA(dftSize, A.type(), Scalar::all(0)); 
    Mat tempB(dftSize, B.type(), Scalar::all(0)); 

    // copy A and B to the top-left corners of tempA and tempB, respectively 
    Mat roiA(tempA, Rect(0,0,A.cols,A.rows)); 
    A.copyTo(roiA); 
    Mat roiB(tempB, Rect(0,0,B.cols,B.rows)); 
    B.copyTo(roiB); 

    // now transform the padded A & B in-place; 
    // use "nonzeroRows" hint for faster processing 
    dft(tempA, tempA, 0, A.rows); 
    dft(tempB, tempB, 0, B.rows); 

    // multiply the spectrums; 
    // the function handles packed spectrum representations well 
    mulSpectrums(tempA, tempB, tempA); 

    // transform the product back from the frequency domain. 
    // Even though all the result rows will be non-zero, 
    // you need only the first C.rows of them, and thus you 
    // pass nonzeroRows == C.rows 
    dft(tempA, tempA, DFT_INVERSE + DFT_SCALE, C.rows); 

    // now copy the result back to C. 
    tempA(Rect(0, 0, C.cols, C.rows)).copyTo(C); 
} 

我用海倫圖像爲A(512×512)和身份濾波器(所有條目設置爲0,除了中心條目)爲B(41x41)。


Originalfiltered

看來,底部和圖像的右側部分已經被裁剪。此外,雖然由於SO格式化而不可見,但濾波圖像比原始圖像小(因爲函數的第一行)。

我該如何修改代碼,以便像filter2D函數那樣過濾圖像?所以在這種情況下,結果將是原始圖像。

回答

1

卷積結果的大小應爲A.cols + B.cols - 1A.rows + B.rows - 1(就像調用getOptimalDFTSize的參數一樣)。因此,要獲得全卷積結果,例如第一行應改爲:

C.create(A.rows + B.rows - 1, A.cols + B.cols - 1, A.type()); 

這應該然後給你所得到的圖像比原來的稍大,包括邊境的一切圍繞着對應於卷積的尾部(其中過濾斜向上和向下)。

filter2D另一方面不會返回完整的卷積,因爲輸出被限制爲與原始圖像大小相同的圖像,從而消除卷積尾部。爲此,filter2D假設線性內核,沿着列移動(B.cols - 1)/2,沿行移動(B.rows - 1)/2。過濾後的圖像因此可以用以下方式提取:

C.create(A.rows, A.cols, A.type()); 
... 
tempA(Rect((B.cols-1)/2, (B.rows-1)/2, A.cols, A.rows).copyTo(C);