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

标签 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

这就是我得到的结果。抱歉发了这么长的帖子。如果有人有任何见解,我将不胜感激。我已经为此苦苦挣扎了几个星期。

最佳答案

这是我用来测试它的代码:

      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 就是你的图像;它显示得很好 - 你必须重新洗牌象限。

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

关于java - 如何使用离散傅里叶变换在频域中的图像上实现低通滤波器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36878830/

相关文章:

java - Android/Gradle/Unity - 在 AAR 插件中包含所有依赖项

ios - 使用带有opencv的haarcascade的手语,可能吗?

c++ - 无法使用 C++ 在 Matlab 上打开重新采样的图像

java - 如何将数据库表绑定(bind)到我的 JTable 并使用 JTable 更改和添加行

java - 如何跟踪应用程序的首次启动?

html - 在 Firefox 中显示返回 HTTP 503 的图像

ios - 图像到 UInt8 的转换 Swift 会扭曲图像

image-processing - 如何通过命令行为图像添加水印 - 希望使用 Irfanview

java - 在静态方法中定义内部类的目的是什么?

ios - 链接器命令失败,退出代码为 1(使用 -v 查看调用)架构 x86_64 的重复符号