Jnana Parantapa
Jnana Parantapa

Reputation: 13

Fourier transform getting magnitude value in java

I have the following code that use simple algorithm for fourier transform, but it not working like it should.

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;
}

This is the following result:

enter image description here

Obviously I made some mistake here, but I couldn't figure it out, the value in sqrt root can be negative that will result NaN but I am following the fourier transform formula.

Upvotes: 1

Views: 163

Answers (1)

gpasch
gpasch

Reputation: 2682

Obviously you have misinterpreted the formulas. From another implementation I have

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];

So once you have the real and imaginary parts you do the square root

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

Also in the cosine/sine

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

I dont see a square rather a doubling.

--

I have updated your function as follows:

a) the real and imaginary parts need to be computed separately, there is no computation on the complex number b) some rearrangements

It seems to work and if you try with the image shown here http://homepages.inf.ed.ac.uk/rbf/HIPR2/fourier.htm the diagonal stripes you will get the diagonal as shown on that page.

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;
}

On the display side I have the following:

  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");

Upvotes: 1

Related Questions