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

来源:互联网 发布:腾讯网络电影合作地址 编辑:程序博客网 时间:2024/05/23 01:18

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


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

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

     

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

     

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

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

FFT 类负责一维变换:

package app.fourier;public class FFT {//double r_data[] = null;//double i_data[] = null;// compute the FFT of x[], assuming its length is a power of 2public static void fft(Complex[] src, int row, int width, Complex[] dest) {Complex[] temp = new Complex[width];for (int k = 0; k < width; k++) {temp[k] = src[row * width + k];}temp = fft(temp);//set outputfor (int k = 0; k < width; k++) {dest[row * width + k] = temp[k];}}public static Complex[] fft(Complex[] x) {int N = x.length;// base caseif (N == 1)return new Complex[] { x[0] };// radix 2 Cooley-Tukey FFTif (N % 2 != 0) {throw new RuntimeException("N is not a power of 2");}// fft of even termsComplex[] even = new Complex[N / 2];for (int k = 0; k < N / 2; k++) {even[k] = x[2 * k];}Complex[] q = fft(even);// fft of odd termsComplex[] odd = even; // reuse the arrayfor (int k = 0; k < N / 2; k++) {odd[k] = x[2 * k + 1];}Complex[] r = fft(odd);// combineComplex[] y = new Complex[N];for (int k = 0; k < N / 2; k++) {double kth = -2 * k * Math.PI / N;Complex wk = new Complex(Math.cos(kth), Math.sin(kth));y[k] = q[k].plus(wk.times(r[k]));y[k + N / 2] = q[k].minus(wk.times(r[k]));}return y;}}

Complex类是复数类:

public class Complex {    public  double re;   // the real part    public  double im;   // the imaginary part    public Complex() {        re = 0;        im = 0;    }        // create a new object with the given real and imaginary parts    public Complex(double real, double imag) {        re = real;        im = imag;    }    // return a string representation of the invoking Complex object    public String toString() {        if (im == 0) return re + "";        if (re == 0) return im + "i";        if (im <  0) return re + " - " + (-im) + "i";        return re + " + " + im + "i";    }    // return abs/modulus/magnitude and angle/phase/argument    public double abs()   { return Math.hypot(re, im); }  // Math.sqrt(re*re + im*im)    public double phase() { return Math.atan2(im, re); }  // between -pi and pi    // return a new Complex object whose value is (this + b)    public Complex plus(Complex b) {        Complex a = this;             // invoking object        double real = a.re + b.re;        double imag = a.im + b.im;        return new Complex(real, imag);    }    // return a new Complex object whose value is (this - b)    public Complex minus(Complex b) {        Complex a = this;        double real = a.re - b.re;        double imag = a.im - b.im;        return new Complex(real, imag);    }    // return a new Complex object whose value is (this * b)    public Complex times(Complex b) {        Complex a = this;        double real = a.re * b.re - a.im * b.im;        double imag = a.re * b.im + a.im * b.re;        return new Complex(real, imag);    }    // scalar multiplication    // return a new object whose value is (this * alpha)    public Complex times(double alpha) {        return new Complex(alpha * re, alpha * im);    }    // return a new Complex object whose value is the conjugate of this    public Complex conjugate() {  return new Complex(re, -im); }    // return a new Complex object whose value is the reciprocal of this    public Complex reciprocal() {        double scale = re*re + im*im;        return new Complex(re / scale, -im / scale);    }    // return the real or imaginary part    public double re() { return re; }    public double im() { return im; }    // return a / b    public Complex divides(Complex b) {        Complex a = this;        return a.times(b.reciprocal());    }    // return a new Complex object whose value is the complex exponential of this    public Complex exp() {        return new Complex(Math.exp(re) * Math.cos(im), Math.exp(re) * Math.sin(im));    }    // return a new Complex object whose value is the complex sine of this    public Complex sin() {        return new Complex(Math.sin(re) * Math.cosh(im), Math.cos(re) * Math.sinh(im));    }    // return a new Complex object whose value is the complex cosine of this    public Complex cos() {        return new Complex(Math.cos(re) * Math.cosh(im), -Math.sin(re) * Math.sinh(im));    }    // return a new Complex object whose value is the complex tangent of this    public Complex tan() {        return sin().divides(cos());    }        // a static version of plus    public static Complex plus(Complex a, Complex b) {        double real = a.re + b.re;        double imag = a.im + b.im;        Complex sum = new Complex(real, imag);        return sum;    }}

FourierTransformer 为主调类:

import java.awt.Graphics;import java.awt.Image;import java.awt.image.BufferedImage;import java.awt.image.ColorModel;import java.awt.image.PixelGrabber;import java.awt.image.WritableRaster;import java.io.File;import java.io.IOException;import javax.imageio.ImageIO;import javax.swing.JFrame;@SuppressWarnings("serial")public class FourierTransformer  extends JFrame{Image im;BufferedImage imageAuth = null;int iw;int ih;int[] pixels;int[] newPixels;public FourierTransformer() {try {this.im = ImageIO.read(getClass().getResource("fft8.bmp"));} catch (IOException e1) {e1.printStackTrace();}this.iw = im.getWidth(null);this.ih = im.getHeight(null);pixels = new int[iw * ih];try {PixelGrabber pg = new PixelGrabber(im, 0, 0, iw, ih, pixels, 0, iw);pg.grabPixels();} catch (InterruptedException e3) {e3.printStackTrace();}}public void paint(Graphics g) {super.paint(g);g.drawImage(this.im, 0, 100, this.iw, this.ih, this);if(imageAuth != null)g.drawImage(imageAuth, 250, 100, imageAuth.getWidth(), imageAuth.getHeight(), this);}public static void main(String[] args){FourierTransformer frame = new FourierTransformer();frame.setSize(600, 500);frame.setTitle("ImageMenu");frame.setName("hello my dongjing");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);frame.convert(frame.getGraphics());}public Image convert(Graphics g) {// 赋初值int w = 1;int h = 1;// 计算进行付立叶变换的宽度和高度(2的整数次方)while (w * 2 <= iw) {w *= 2;}while (h * 2 <= ih) {h *= 2;}// 分配内存Complex[] src = new Complex[h * w];Complex[] dest = new Complex[h * w];newPixels = new int[h * w];// 初始化newPixelsfor (int i = 0; i < h; i++) {for (int j = 0; j < w; j++) {newPixels[i * w + j] = pixels[i * iw + j] & 0xff;}}// 初始化src,destfor (int i = 0; i < h; i++) {for (int j = 0; j < w; j++) {dest[i * w + j] = new Complex();src[i * w + j] = new Complex(newPixels[i * w + j], 0);}}// 在y方向上进行快速傅立叶变换for (int i = 0; i < h; i++) {FFT.fft(src, i, w, dest);}/** * 以下一定要进行转换,高手指点一下原因 (^ - ^) */for (int i = 0; i < h; i++) {for (int j = 0; j < w; j++) {src[j * h + i] = dest[i * w + j];//System.out.println("dest " + j*h+i + ",  src " + i*w+j);}}// 对x方向进行傅立叶变换for (int i = 0; i < w; i++) {FFT.fft(src, i, h, dest);}/** * 将图像看做二维函数,图像灰度值为函数在相应XY处的函数值,对其进行二维快速傅里叶变换, * 得到一个复数矩阵,将此矩阵水平循环移动半宽,垂直循环移动半高。 */for (int i = 0; i < h; i++) {for (int j = 0; j < w; j++) {double re = dest[j * h + i].re;double im = dest[j * h + i].im;int ii = 0, jj = 0;int temp = (int) (Math.sqrt(re * re + im * im) / 100);if (temp > 255) {temp = 255;}if (i < h / 2) {ii = i + h / 2;} else {ii = i - h / 2;}if (j < w / 2) {jj = j + w / 2;} else {jj = j - w / 2;}newPixels[ii * w + jj] = temp;}}imageAuth = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);ColorModel colorModel = imageAuth.getColorModel();WritableRaster raster = colorModel.createCompatibleWritableRaster(w, h);raster.setPixels(0, 0, w, h, newPixels);imageAuth.setData(raster);try {ImageIO.write(imageAuth, "bmp", new File("fft_result.bmp"));} catch (IOException e) {e.printStackTrace();}this.update(g);return imageAuth;}}


0 0
原创粉丝点击