2016-06-12 15 views
3

と仮定、我々は、2D整数配列として表されたビットマップイメージを有する int [,] image2D;そのFFT Complex[,] fftImage2D;周波数領域でコンボリューションをどのように実装できますか?

と仮定、我々は int [,] kernel2D; FFT Complex[,] fftKernel2D;

ある2D整数のアレイとして表さカーネルを持っている私たちimage2Dkernel2Dの(空間領域で)の畳み込みは次のようになり、ことを知って、

int Rows = image2D.GetLength(0); 
int Cols = image2D.GetLength(1); 

for(int i=0 ; i<Rows ; i++) 
{ 
    for(int j=0 ; j<Cols ; j++) 
    { 
     //sweep the kernel2D across image2D 
     //........................... 
    } 
} 

以下のリンクであります空間領域での畳み込みについてLL:

http://www.codeproject.com/Articles/2008/Image-Processing-for-Dummies-with-C-and-GDI-Part http://www.gutgames.com/post/Matrix-Convolution-Filters-in-C.aspx https://softwarebydefault.com/2013/05/01/image-convolution-filters/

コンボリューション周波数領域では、fftImage2DfftKernel2D間の乗算になります。

は、どのように私はこの乗算を行うことができますか?

どのように異なる寸法の2つのComplex [,]型2Dアレイを掛けることができますか?

答えて

5

あなたが最初の2つの複素2D配列が同じ次元を持っていることを確認する必要があり、周波数領域での乗算を使用することにより、線形畳み込みを実行します。これは、同じ大きさに2つの空間領域配列(image2Dkernel2D)をパディングすることによって達成することができます。円形の畳み込みではなく線形の畳み込みを実行するためには、すでに2つの配列次元の合計(各次元に沿って)の最小値より1小さい空間ドメイン配列を埋めなければならないことに注意してください。

だからプロセスは次のようになります。

  • 計算行のパディング数:image2D.GetLength(0)+kernel2D.GetLength(0)-1
  • 計算列のパディング数:この新しいサイズにimage2D.GetLength(1)+kernel2D.GetLength(1)-1
  • パッドimage2D、繰り返し境界要素
  • パッドゼロを埋めるこの新しいサイズにkernel2D、パディングimage2D
  • 計算FFTとkernel2D
  • もしによってフィルタリングされた画像を得ることに興味を持っている場合にのみ必要とされる(
  • 計算逆FFTが
  • は、必要に応じて元のimage2Dサイズに結果を切り捨てる同じサイズで今のパディングfftImage2DfftKernel2Dの乗算を行いますkernel2Dには完全な畳み込みに伴うエッジ効果はありません)。

今後の読者はthis other question from @anonymousと、my answerで示した変更を見ているかもしれません。

+0

何場合2つのうち大きい方(image2D vs kernel2D)をパッドサイズとして取るか?私は、パディングされた画像の中心に、または四隅のいずれかにカーネルを保持する必要がありますか?そして、image2Dをどのように切り捨てることができますか? – anonymous

+1

2つのうち大きい方のみをパッドサイズとして使用すると、循環コンボルーションのアーティファクトが巻き込まれます。サイズが上記の値以上になると、アーティファクトはゼロになります。周波数領域でのカーネルの位置は、イメージをfftshift/ifftshift(つまり、同じゼロ周波数位置で両方のイメージを維持する必要がある)しない限り、4つのコーナーにある必要があります(ゼロ周波数が中心にあると仮定し、一般的です)。 – SleuthEye

+1

空間ドメインのカーネルの位置は、結果の画像を切り捨てるときに対応するシフトを考慮して、どこからでも指定できます。空間領域の4隅に配置すると、0シフトが得られるので、結果として得られる画像を切り捨てるだけで、最初の 'GetLength(0)'と 'GetLength(1)'ピクセルを取ることになります。 – SleuthEye

-1

あなたはmultiplication of two complex numbersを使用する必要があります。ここ

は、符号化して、2つの1Dアレイの作業を行うほとんどのJavaコードである:[R1、C1、R2、C2、...、Rnを、CN]:

public void Multiply(double[] object1, double[] object2, double[] result) 
{ 
double img_r, img_i, mask_r, mask_i ; 

for (int pos=0 ; pos < result.length ; pos+=2) 
    { 
    img_r = object1[pos] ; 
    img_i = object1[pos+1] ; 

    mask_r = object2[pos] ; 
    mask_i = object2[pos+1] ; 

    result[pos] = img_r*mask_r - img_i*mask_i; 
    result[pos+1] = img_r*mask_i + img_i*mask_r ; 
    } 
} 
関連する問題