java使用傅里叶变换,得到变换之后的傅里叶频谱图像。

使用傅里叶变换来处理图像,可以滤波,去噪。 但是网络上java实现很少,可以运行的就更少,我总结了一些代码,并加以调试,


保证速度的情况下得以运行成功。 这些代码仅对灰度图验证通过。学习之用。

调用结果可以用http://cns-alumni.bu.edu/~slehar/fourier/fourier.html#filtering 网站的图片验证:

     

输入图像:ff8.bmp                  输出图像fft_result.bmp

     

输入图像:ff8.bmp                  输出图像fft_result.bmp

所有FFT变换都已经验证通过。  但是傅里叶逆变换没有成功。  有高手可以指点一下。 如何使逆变换的图片显示出来。

FFT 类负责一维变换:

[java]  view plain  copy
  1. package app.fourier;  
  2.   
  3. public class FFT {  
  4.   
  5. //  double r_data[] = null;  
  6. //  double i_data[] = null;  
  7.       
  8.     // compute the FFT of x[], assuming its length is a power of 2  
  9.     public static void fft(Complex[] src, int row, int width, Complex[] dest) {  
  10.           
  11.         Complex[] temp = new Complex[width];  
  12.         for (int k = 0; k < width; k++) {  
  13.             temp[k] = src[row * width + k];  
  14.         }  
  15.         temp = fft(temp);  
  16.         //set output  
  17.         for (int k = 0; k < width; k++) {  
  18.             dest[row * width + k] = temp[k];  
  19.         }  
  20.     }  
  21.     public static Complex[] fft(Complex[] x) {  
  22.         int N = x.length;  
  23.   
  24.         // base case  
  25.         if (N == 1)  
  26.             return new Complex[] { x[0] };  
  27.   
  28.         // radix 2 Cooley-Tukey FFT  
  29.         if (N % 2 != 0) {  
  30.             throw new RuntimeException("N is not a power of 2");  
  31.         }  
  32.   
  33.         // fft of even terms  
  34.         Complex[] even = new Complex[N / 2];  
  35.         for (int k = 0; k < N / 2; k++) {  
  36.             even[k] = x[2 * k];  
  37.         }  
  38.         Complex[] q = fft(even);  
  39.   
  40.         // fft of odd terms  
  41.         Complex[] odd = even; // reuse the array  
  42.         for (int k = 0; k < N / 2; k++) {  
  43.             odd[k] = x[2 * k + 1];  
  44.         }  
  45.         Complex[] r = fft(odd);  
  46.   
  47.         // combine  
  48.         Complex[] y = new Complex[N];  
  49.         for (int k = 0; k < N / 2; k++) {  
  50.             double kth = -2 * k * Math.PI / N;  
  51.             Complex wk = new Complex(Math.cos(kth), Math.sin(kth));  
  52.             y[k] = q[k].plus(wk.times(r[k]));  
  53.             y[k + N / 2] = q[k].minus(wk.times(r[k]));  
  54.         }  
  55.         return y;  
  56.     }  
  57. }  

Complex类是复数类:

[java]  view plain  copy
  1. public class Complex {  
  2.     public  double re;   // the real part  
  3.     public  double im;   // the imaginary part  
  4.   
  5.     public Complex() {  
  6.         re = 0;  
  7.         im = 0;  
  8.     }  
  9.       
  10.     // create a new object with the given real and imaginary parts  
  11.     public Complex(double real, double imag) {  
  12.         re = real;  
  13.         im = imag;  
  14.     }  
  15.   
  16.     // return a string representation of the invoking Complex object  
  17.     public String toString() {  
  18.         if (im == 0return re + "";  
  19.         if (re == 0return im + "i";  
  20.         if (im <  0return re + " - " + (-im) + "i";  
  21.         return re + " + " + im + "i";  
  22.     }  
  23.   
  24.     // return abs/modulus/magnitude and angle/phase/argument  
  25.     public double abs()   { return Math.hypot(re, im); }  // Math.sqrt(re*re + im*im)  
  26.     public double phase() { return Math.atan2(im, re); }  // between -pi and pi  
  27.   
  28.     // return a new Complex object whose value is (this + b)  
  29.     public Complex plus(Complex b) {  
  30.         Complex a = this;             // invoking object  
  31.         double real = a.re + b.re;  
  32.         double imag = a.im + b.im;  
  33.         return new Complex(real, imag);  
  34.     }  
  35.   
  36.     // return a new Complex object whose value is (this - b)  
  37.     public Complex minus(Complex b) {  
  38.         Complex a = this;  
  39.         double real = a.re - b.re;  
  40.         double imag = a.im - b.im;  
  41.         return new Complex(real, imag);  
  42.     }  
  43.   
  44.     // return a new Complex object whose value is (this * b)  
  45.     public Complex times(Complex b) {  
  46.         Complex a = this;  
  47.         double real = a.re * b.re - a.im * b.im;  
  48.         double imag = a.re * b.im + a.im * b.re;  
  49.         return new Complex(real, imag);  
  50.     }  
  51.   
  52.     // scalar multiplication  
  53.     // return a new object whose value is (this * alpha)  
  54.     public Complex times(double alpha) {  
  55.         return new Complex(alpha * re, alpha * im);  
  56.     }  
  57.   
  58.     // return a new Complex object whose value is the conjugate of this  
  59.     public Complex conjugate() {  return new Complex(re, -im); }  
  60.   
  61.     // return a new Complex object whose value is the reciprocal of this  
  62.     public Complex reciprocal() {  
  63.         double scale = re*re + im*im;  
  64.         return new Complex(re / scale, -im / scale);  
  65.     }  
  66.   
  67.     // return the real or imaginary part  
  68.     public double re() { return re; }  
  69.     public double im() { return im; }  
  70.   
  71.     // return a / b  
  72.     public Complex divides(Complex b) {  
  73.         Complex a = this;  
  74.         return a.times(b.reciprocal());  
  75.     }  
  76.   
  77.     // return a new Complex object whose value is the complex exponential of this  
  78.     public Complex exp() {  
  79.         return new Complex(Math.exp(re) * Math.cos(im), Math.exp(re) * Math.sin(im));  
  80.     }  
  81.   
  82.     // return a new Complex object whose value is the complex sine of this  
  83.     public Complex sin() {  
  84.         return new Complex(Math.sin(re) * Math.cosh(im), Math.cos(re) * Math.sinh(im));  
  85.     }  
  86.   
  87.     // return a new Complex object whose value is the complex cosine of this  
  88.     public Complex cos() {  
  89.         return new Complex(Math.cos(re) * Math.cosh(im), -Math.sin(re) * Math.sinh(im));  
  90.     }  
  91.   
  92.     // return a new Complex object whose value is the complex tangent of this  
  93.     public Complex tan() {  
  94.         return sin().divides(cos());  
  95.     }  
  96.       
  97.   
  98.   
  99.     // a static version of plus  
  100.     public static Complex plus(Complex a, Complex b) {  
  101.         double real = a.re + b.re;  
  102.         double imag = a.im + b.im;  
  103.         Complex sum = new Complex(real, imag);  
  104.         return sum;  
  105.     }  
  106. }  

FourierTransformer 为主调类:

[java]  view plain  copy
  1. import java.awt.Graphics;  
  2. import java.awt.Image;  
  3. import java.awt.image.BufferedImage;  
  4. import java.awt.image.ColorModel;  
  5. import java.awt.image.PixelGrabber;  
  6. import java.awt.image.WritableRaster;  
  7. import java.io.File;  
  8. import java.io.IOException;  
  9.   
  10. import javax.imageio.ImageIO;  
  11. import javax.swing.JFrame;  
  12.   
  13. @SuppressWarnings("serial")  
  14. public class FourierTransformer  extends JFrame{  
  15.     Image im;  
  16.     BufferedImage imageAuth = null;  
  17.     int iw;  
  18.     int ih;  
  19.     int[] pixels;  
  20.     int[] newPixels;  
  21.   
  22.     public FourierTransformer() {  
  23.           
  24.         try {  
  25.             this.im = ImageIO.read(getClass().getResource("fft8.bmp"));  
  26.         } catch (IOException e1) {  
  27.             e1.printStackTrace();  
  28.         }  
  29.           
  30.         this.iw = im.getWidth(null);  
  31.         this.ih = im.getHeight(null);  
  32.         pixels = new int[iw * ih];  
  33.         try {  
  34.             PixelGrabber pg = new PixelGrabber(im, 00, iw, ih, pixels, 0, iw);  
  35.             pg.grabPixels();  
  36.         } catch (InterruptedException e3) {  
  37.             e3.printStackTrace();  
  38.         }  
  39.           
  40.     }  
  41.   
  42.     public void paint(Graphics g) {  
  43.         super.paint(g);  
  44.                   
  45.         g.drawImage(this.im, 0100this.iw, this.ih, this);  
  46.         if(imageAuth != null)  
  47.             g.drawImage(imageAuth, 250100, imageAuth.getWidth(), imageAuth.getHeight(), this);  
  48.           
  49.     }  
  50.       
  51.     public static void main(String[] args){  
  52.         FourierTransformer frame = new FourierTransformer();  
  53.           
  54.         frame.setSize(600500);  
  55.         frame.setTitle("ImageMenu");  
  56.         frame.setName("hello my dongjing");  
  57.           
  58.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);         
  59.           
  60.           
  61.           
  62.         frame.setVisible(true);  
  63.         frame.convert(frame.getGraphics());  
  64.     }  
  65.     public Image convert(Graphics g) {  
  66.         // 赋初值  
  67.         int w = 1;  
  68.         int h = 1;  
  69.         // 计算进行付立叶变换的宽度和高度(2的整数次方)  
  70.         while (w * 2 <= iw) {  
  71.             w *= 2;  
  72.         }  
  73.         while (h * 2 <= ih) {  
  74.             h *= 2;  
  75.         }  
  76.         // 分配内存  
  77.         Complex[] src = new Complex[h * w];  
  78.         Complex[] dest = new Complex[h * w];  
  79.         newPixels = new int[h * w];  
  80.         // 初始化newPixels  
  81.         for (int i = 0; i < h; i++) {  
  82.             for (int j = 0; j < w; j++) {  
  83.                 newPixels[i * w + j] = pixels[i * iw + j] & 0xff;  
  84.             }  
  85.         }  
  86.         // 初始化src,dest  
  87.         for (int i = 0; i < h; i++) {  
  88.             for (int j = 0; j < w; j++) {  
  89.                 dest[i * w + j] = new Complex();  
  90.                 src[i * w + j] = new Complex(newPixels[i * w + j], 0);  
  91.             }  
  92.         }  
  93.         // 在y方向上进行快速傅立叶变换  
  94.         for (int i = 0; i < h; i++) {  
  95.             FFT.fft(src, i, w, dest);  
  96.         }  
  97.         /** 
  98.          * 以下一定要进行转换,高手指点一下原因 (^ - ^) 
  99.          */  
  100.         for (int i = 0; i < h; i++) {  
  101.             for (int j = 0; j < w; j++) {  
  102.                 src[j * h + i] = dest[i * w + j];  
  103. //              System.out.println("dest " + j*h+i + ",  src " + i*w+j);  
  104.             }  
  105.         }  
  106.         // 对x方向进行傅立叶变换  
  107.         for (int i = 0; i < w; i++) {  
  108.             FFT.fft(src, i, h, dest);  
  109.         }  
  110.         /** 
  111.          * 将图像看做二维函数,图像灰度值为函数在相应XY处的函数值,对其进行二维快速傅里叶变换, 
  112.          * 得到一个复数矩阵,将此矩阵水平循环移动半宽,垂直循环移动半高。 
  113.          */  
  114.         for (int i = 0; i < h; i++) {  
  115.             for (int j = 0; j < w; j++) {  
  116.                 double re = dest[j * h + i].re;  
  117.                 double im = dest[j * h + i].im;  
  118.                 int ii = 0, jj = 0;  
  119.                 int temp = (int) (Math.sqrt(re * re + im * im) / 100);  
  120.                 if (temp > 255) {  
  121.                     temp = 255;  
  122.                 }  
  123.                 if (i < h / 2) {  
  124.                     ii = i + h / 2;  
  125.                 } else {  
  126.                     ii = i - h / 2;  
  127.                 }  
  128.                 if (j < w / 2) {  
  129.                     jj = j + w / 2;  
  130.                 } else {  
  131.                     jj = j - w / 2;  
  132.                 }  
  133.                 newPixels[ii * w + jj] = temp;  
  134.             }  
  135.         }  
  136.   
  137.         imageAuth = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);  
  138.         ColorModel colorModel = imageAuth.getColorModel();  
  139.         WritableRaster raster = colorModel.createCompatibleWritableRaster(w, h);      
  140.         raster.setPixels(00, w, h, newPixels);  
  141.         imageAuth.setData(raster);  
  142.           
  143.         try {  
  144.             ImageIO.write(imageAuth, "bmp"new File("fft_result.bmp"));  
  145.         } catch (IOException e) {  
  146.             e.printStackTrace();  
  147.         }  
  148.         this.update(g);  
  149.           
  150.           
  151.         return imageAuth;  
  152.     }  
  153. }  
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值