傅立叶变换在java中获得幅度值

时间:2016-12-13 20:25:59

标签: java image image-processing fft

我有以下代码使用简单的算法进行傅里叶变换,但它不能像它应该的那样工作。

public int ft(int x, int y, int br, int a, int height, int width, int[][] pixelTemp, double c){
    int r;
    int g;
    int b;
    double avg;     
    double newCitra = 0;
    int temp;
    for (int i=0; i<height; i++){
        for (int j=0; j<width; j++){
            temp = pixelTemp[i][j];
            r = (temp>>16)&0xff;
            g = (temp>>8)&0xff;
            b = temp&0xff;
            avg = (r+g+b)/3;
            if (Math.sin(Math.toRadians(360*(((double)(i*x)/(double)height)+((double)(j*y)/(double)width))))>0){
                if(-2*(((double)(i*x)/(double)height)+((double)(j*y)/(double)width))>0){
                    newCitra = ((newCitra + (((double)avg/(double)(height*width)))*(sqrt(Math.pow((Math.cos(Math.toRadians(360*(((double)(i*x)/(double)height)+((double)(j*y)/(double)width))))),2)+Math.pow((double)Math.sin(Math.toRadians(360*(((double)(i*x)/(double)height)+((double)(j*y)/(double)width)))),2)))));
                } else {
                    newCitra = ((newCitra + (((double)avg/(double)(height*width)))*(sqrt(Math.pow((Math.cos(Math.toRadians(360*(((double)(i*x)/(double)height)+((double)(j*y)/(double)width))))),2)-Math.pow((double)Math.sin(Math.toRadians(360*(((double)(i*x)/(double)height)+((double)(j*y)/(double)width)))),2)))));
                }                    
            } else {
                if(-2*(((double)(i*x)/(double)height)+((double)(j*y)/(double)width))>0){
                    newCitra = (newCitra + ((double)avg/(double)(height*width))*((Math.cos(Math.toRadians(360*(((double)(i*x)/(double)height)+((double)(j*y)/(double)width)))))+(double)Math.sin(Math.toRadians(360*(((double)(i*x)/(double)height)+((double)(j*y)/(double)width))))));
                } else {
                    newCitra = (newCitra + ((double)avg/(double)(height*width))*((Math.cos(Math.toRadians(360*(((double)(i*x)/(double)height)+((double)(j*y)/(double)width)))))-(double)Math.sin(Math.toRadians(360*(((double)(i*x)/(double)height)+((double)(j*y)/(double)width))))));
                }
            }
            /*System.out.println(newCitra);*/
        }
    }
    newCitra = (int) (Math.log(1+newCitra)*c);
    int j = 30;
    int i = 10;
    /*System.out.println(Math.abs(sqrt(Math.pow((Math.cos(Math.toRadians(360*(((double)(i*x)/(double)height)+((double)(j*y)/(double)width))))),2)-Math.pow((double)Math.sin(Math.toRadians(360*(((double)(i*x)/(double)height)+((double)(j*y)/(double)width)))),2))));*/
    int p = (255<<24) | ((int)newCitra<<16) | ((int)newCitra<<8) | (int)newCitra;

    return p;
}

这是以下结果:

enter image description here

显然我在这里犯了一些错误,但是我无法弄清楚,sqrt root中的值可能是负值会导致NaN,但我遵循傅里叶变换公式。

1 个答案:

答案 0 :(得分:1)

显然你误解了这些公式。从另一个实现我

real +=  tempreal[row][t] * cos[col][t] - tempimag[row][t] * sin[col][t];
imag +=  tempreal[row][t] * sin [col][t] + tempimag[row][t] * cos[col][t];

因此,一旦你有了实部和虚部,就可以做平方根

mag=Math.sqrt(real*real+imag*imag);

也在余弦/正弦

cos[i][t]=Math.cos(2*Math.PI*t*i/n);
sin[i][t]=Math.sin(2*Math.PI*t*i/n);

我看不到广场而是加倍。

-

我已更新您的功能如下:

a)需要分别计算实部和虚部,对复数没有计算 b)一些重新安排

它似乎有效,如果您尝试使用此处显示的图像http://homepages.inf.ed.ac.uk/rbf/HIPR2/fourier.htm,对角条纹将显示该页面上显示的对角线。

public double ft(int x, int y, int br, int a, int height, int width, int[][] pixelTemp, double c){
    int r;
    int g;
    int b;
    double avg;     
    double newCitrar = 0, newCitrai = 0;
    int temp;
    double f=(double)1/(double)(height*width);
    for (int i=0; i<width; i++){
        for (int j=0; j<height; j++){
            temp = pixelTemp[i][j];
//            r = (temp>>16)&0xff;
//            g = (temp>>8)&0xff;
//            b = temp&0xff;
            avg = temp; // (r+g+b)/3;
        newCitrar = newCitrar + avg*Math.cos(2*Math.PI*(((double)(i*x)/(double)width)+((double)(j*y)/(double)height)));
        newCitrai=newCitrai+avg*Math.sin(2*Math.PI*(((double)(i*x)/(double)width)+((double)(j*y)/(double)height)));
      }
    }
    newCitrar *=f;
    newCitrai *=f;
    double newCitra=Math.sqrt(newCitrar*newCitrar+newCitrai*newCitrai);
    return newCitra;
}

在显示方面,我有以下内容:

  BufferedImage bim=null;
  try {
    bim=ImageIO.read(new File("str.gif"));
  }
  catch (Exception ex) { System.err.println("error"); }
  int wc=bim.getWidth(), hc=bim.getHeight();
  BufferedImage b2=new BufferedImage(wc, hc, BufferedImage.TYPE_INT_RGB);

  int[] pix=bim.getRGB(0, 0, wc, hc, null, 0, wc);
  int[][] pix2=new int[wc][hc];
  double ri;
  for(i=0; i<wc; 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=0.2126*rr+0.7152*rg+0.0722*rb;
    pix2[i][j]=(int)ri;
  }
  double max=0;
  for(i=0; i<wc; i++)
  for(j=0; j<hc; j++) {
  if(i%10==0 && j%10==0) System.out.println(i+" "+j);
    double ki=ft(i, j, 0, 0, hc, wc, pix2, 1);
    if(ki>max) max=ki;
    b2.setRGB(i, j, (int)ki);
  }
  saveImageIO(b2, (time/1000)+"f-1");

  double cc=255./Math.log(1+max);
  System.out.println(max+" "+cc);
  for(i=0; i<wc; i++)
  for(j=0; j<hc; j++) {
    b2.setRGB(i, j, (int) (Math.log(1+(b2.getRGB(i, j)&0x00ffffff))*cc));
  }   

  saveImageIO(b2, (time/1000)+"f-2");