2017-04-09 21 views
2

をシフトさIは、ドキュメントからthis OpenCV exampleに基づいており、ここでは便宜上、コピースペクトル画像フィルタリングを実現しようとした:OpenCVのDFTベースの畳み込みは

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); 
} 

Iは、(512×512)としてレナ画像を使用し、同一のフィルタ(すべてのエントリーはB(41x41)として中央のものを除いて0に設定されます)。


Originalfiltered

下の画像の右部分がトリミングされているようです。また、SOの書式設定のためにここには表示されませんが、フィルタされた画像はオリジナルのものよりも小さくなります(関数の最初の行のためです)。

filter2D関数のように画像をフィルタするようにコードを変更するにはどうすればよいですか?この場合、結果は元の画像になります。

答えて

1

畳み込み結果のサイズは、コールの引数と同様に、A.cols + B.cols - 1A.rows + B.rows - 1である必要があります。これは、すべての周りに境界線を含め、あなたのオリジナルのものよりわずかに大きい結果のイメージを与える必要があります

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

:だから、完全な畳み込み結果を得るために、例の最初の行に変更する必要があります畳み込みの末尾に対応します(ここで、フィルタリングは上下に傾斜します)。一方、畳み込みテールを除去して、出力が元のサイズと同じサイズの画像に限定されるため、完全な畳み込みは戻らない。これを行うために、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); 
関連する問題