2016-04-27 4 views
0

私は画像に2次元フーリエ変換を実装しようとしています。私はそれが私のDFTと逆DFT画像上で動作するようにしています。しかし、フィルタを適用するとき、複素数を掛けて、逆の結果を得れば、ただ画像ノイズしか得られません。ディスクリートフーリエ変換を使用して周波数領域の画像にローパスフィルタを実装する方法はありますか?

はここ

そして、ここでは画像が通過して戻ってくる同じDFT

public void inverseDFT(double[][] inRealArray, double[][] inImagArray) { 
int n = realArray.length; 
    outRealArray = new double[n][n]; 
    outImagArray = new double[n][n]; 
    outputarray = new int[n][n]; 

    double[][] tempreal = new double[n][n]; 
    double[][] tempimag = new double[n][n]; 

    for (int col = 0; col < n; col++) { 
     for (int row = 0; row < n; row++) { // For each output element 
      double sumreal = 0; 
      double sumimag = 0; 
      for (int t = 0; t < n; t++) { // For each input element 
       double angle = 2 * Math.PI * t * row/n; 
       sumreal += inRealArray[t][col] * Math.cos(angle) - inImagArray[t][col] * Math.sin(angle); 
       sumimag += inRealArray[t][col] * Math.sin(angle) + inImagArray[t][col] * Math.cos(angle); 

      } 
      //System.out.println("r" + row + " " + "c" + col + " " + sumreal + " " + sumimag); 
      tempreal[row][col] = sumreal; 
      tempimag[row][col] = sumimag; 
     } 
    } 

    //now do it over the columns 
    for(int row = 0; row < n; row++) { 
     for (int col = 0; col < n; col++) { // For each output element 
      double sumreal = 0; 
      double sumimag = 0; 
      for (int t = 0; t < n; t++) { // For each input element 
       double angle = 2 * Math.PI * t * col/n; 
       sumreal += tempreal[row][t] * Math.cos(angle) - tempimag[row][t] * Math.sin(angle); 
       sumimag += tempreal[row][t] * Math.sin(angle) + tempimag[row][t] * Math.cos(angle); 
      } 
      outRealArray[row][col] = sumreal/(n * n); 
      outImagArray[row][col] = sumimag/(n * n); 
      outputarray[row][col] = (int)Math.abs(outRealArray[row][col]); 
      //System.out.println(outRealArray[row][col] + " " + outImagArray[row][col] + "i"); 
     } 
    } 

} 

私の逆である私の2D DFT

public void dft(double[][] inreal, double[][] inimag) { 
int n = inreal.length; 

double[][] tempreal = new double[n][n]; 
double[][] tempimag = new double[n][n]; 
realArray = new double[n][n]; 
imagArray = new double[n][n]; 

    for(int row = 0; row < n; row++) { 
    for (int col = 0; col < n; col++) { 
     double sumreal = 0; 
     double sumimag = 0; 
     for (int t = 0; t < n; t++) { 
      double angle = 2 * Math.PI * t * col/n; 
      sumreal += inreal[row][t] * Math.cos(angle) + inimag[row][t] * Math.sin(angle); 
      sumimag += -inreal[row][t] * Math.sin(angle) + inimag[row][t] * Math.cos(angle); 

     } 
     //System.out.println("r" + row + " " + "c" + col + " " + sumreal + " " + sumimag); 
     tempreal[row][col] = sumreal; 
     tempimag[row][col] = sumimag; 
    } 
} 

    //now do it over the columns 
for (int col = 0; col < n; col++) { 
    for (int row = 0; row < n; row++) { // For each output element 
     double sumreal = 0; 
     double sumimag = 0; 
     for (int t = 0; t < n; t++) { // For each input element 
      double angle = 2 * Math.PI * t * row/n; 
      sumreal += tempreal[t][col] * Math.cos(angle) + tempimag[t][col] * Math.sin(angle); 
      sumimag += -tempreal[t][col] * Math.sin(angle) + tempimag[t][col] * Math.cos(angle); 
     } 
     realArray[row][col] = sumreal; 
     imagArray[row][col] = sumimag; 
     //System.out.println(realArray[row][col] + " " + imagArray[row][col] + "i"); 
    } 
} 

}です。 イメージを中央に移動して、スペクトルイメージを取得してテストします。

This is the magnitude of the complex number and shifted to the center

この

enter image description hereローパスフィルタ複素数の大きさであり、中心

enter image description here

にシフト

enter image description here

フィルタはDFTを通過します。

ここに2つを乗算するコードです。

public void applyLowPassFilter(String filename, double[][] realArray, double[][] imagArray) throws IOException { 
    ReadPGMFile readPGM = new ReadPGMFile(filename); 
    double[][] filterArrayR = readPGM.loadArray(); 
    double[][] filterArrayI = new double[filterArrayR.length][filterArrayR.length]; 

    FourierTransform ft = new FourierTransform(); 
    ft.dft(filterArrayR, filterArrayI); 
    filterReal = ft.getRealArray(); 
    filterImag = ft.getImagArray(); 

    int n = realArray.length; 
    resultRealArray = new double[n][n]; 
    resultImagArray = new double[n][n]; 

    for(int i = 0; i < n; i++){ 
     int colValue = 0; 
     int rowValue = 0; 
     for(int j = 0; j < n; j++) { 
     if(j < n/2){ 
      colValue = (n/2) - j; 
     } else { 
      colValue = (n - 1) - (j - ((n - 1)/2)); 
     } 
     if (i < n/2) { 
      rowValue = (n/2) - i; 
     } else { 
      rowValue = (n - 1) - (i - ((n - 1)/2)); 
     } 


      resultRealArray[i][j] = realArray[rowValue][colValue] * filterReal[i][j] - imagArray[rowValue][colValue] * filterImag[i][j]; 
      resultImagArray[i][j] = realArray[rowValue][colValue] * filterImag[i][j] + imagArray[rowValue][colValue] * filterReal[i][j]; 
     } 
    } 
} 

enter image description here

これは私が取得しています結果です。長い投稿を申し訳ありません。誰かが洞察力を持っているなら、私はそれらを感謝します。私はこれで数週間苦しんできました。

+1

あなたのDFTとInverse DFTが機能することをどのように知っていますか?試したテストデータがありますか?まず、これらの作業が非常にシンプルで簡単な例を使用するか、テスト済みの実装と比較することを確認します。 – Cyb3rFly3r

+0

私は女性の画像をdftに入れます。私はその後、周波数データを取ってそれを逆数に入れ、同じ画像を戻しました。それは動作します。これは一般的な画像処理画像です。スペクトル画像はオンラインで、私の見たものと非常によく似ています。 – MikeT

+0

あなたは乗算を反転していますか?それ以外の場合は、表示方法やPGMフィルタなどの読み方と関連があるかもしれません – gpasch

答えて

1

は、ここで私はそれをテストするために使用するコードです:

 int[] pix=bim.getRGB(0, 0, wc, hc, null, 0, wc); 
     double[][] ri=new double[hc][hc], ii=new double[hc][hc], ro=new double[hc][hc], io=new double[hc][hc]; 
     for(i=0; i<hc; i++) 
     for(j=0; j<hc; j++) { 
     int rr=(pix[i+j*wc]&0x00ff0000)>>16, rg=(pix[i+j*wc]&0x0000ff00)>>8, rb=pix[i+j*wc]&0x000000ff; 
     ri[i][j]=0.2126*rr+0.7152*rg+0.0722*rb; 
     } 
     double[][] ff=new double[hc][hc]; 
     ff[hc/2][hc/2]=ff[hc/2][hc/2+1]=ff[hc/2][hc/2-1]=ff[hc/2+1][hc/2]=ff[hc/2-1][hc/2]=1; 
     // ff[hc/2][hc/2]=ff[hc/2][hc/2+1]=ff[hc/2][hc/2-1]=ff[hc/2+1][hc/2]=ff[hc/2-1][hc/2]=ff[hc/2-1][hc/2-1]=ff[hc/2-1][hc/2+1]=ff[hc/2+1][hc/2-1]=ff[hc/2+1][hc/2+1]=0.125; 
     filterDFT(ff, ri, ro, io); 
     int[] pix2=new int[hc*hc]; 
     for(i=0; i<hc; i++) 
     for(j=0; j<hc; j++) pix2[i+j*hc]=0xff000000|(int)Math.abs(ro[i][j]); 
     BufferedImage b2=new BufferedImage(hc, hc, BufferedImage.TYPE_INT_RGB); 
     b2.setRGB(0, 0, hc, hc, pix2, 0, hc); 

今、B2は、あなたの画像です。それはよく表示されます - あなたは象限を再シャッフルする必要があります。

したがって、私はあなたのフィルタの読み込みのダウンロードをもう一度見てみることをお勧めします。

+0

私はあなたが正しいと思います。私は象限を正しくシフトしていません。私はそれをどうやって行うのかを考えています。 – MikeT

関連する問題