如何使用离散傅里叶变换在频域图像上实现低通滤波器?

时间:2016-04-27 01:41:36

标签: java image image-processing fft imagefilter

我试图在图像上实现二维傅立叶变换。我有它所以我的DFT和反DFT工作在图像上。但是当我应用滤波器时,通过乘以复数,并反过来得到图像噪声。

这是我的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");
    }
 }

}

这是我的逆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");
       }
  }

}

图像通过并返回相同。 我将图像移动到中心并获得光谱图像以测试它是否有效。

enter image description here

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

这是复数的大小并转移到中心

enter image description here

低通滤波器

enter image description here

过滤器通过DFT。

这是我的代码乘以两者。

    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 个答案:

答案 0 :(得分: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是你的形象;它显示得很好 - 你必须重新调整象限。

因此,我建议您再次查看过滤器阅读的下载内容。