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
- java使用傅里叶变换,得到变换之后的傅里叶频谱图像。
- 图像的傅里叶频谱
- Matlab显示一副图像的傅里叶变换后的频谱图
- 6. 对一幅灰度图像进行离散傅里叶变换,用图像的形式显示其(中心化后的)频谱。改变频谱,在进行 反变换,观察变换前后的区别
- [openCV]图像的傅里叶频谱
- OpenCV17(图像二维频谱的理解,傅里叶频谱分析)
- 傅里叶变换网文精粹:图像傅立叶变换的物理意义
- 用opencv求图像的快速傅里叶变换和反变换
- 解释图像的频谱
- 第10章 图像变换-图像傅里叶变换
- Chapter3-图像变换-(1)傅里叶变换
- 重温傅里叶--深入篇1--傅里叶级数与傅里叶变换的关系以及频谱图的介绍
- 基于OpenCV的图像配准之后的透视变换
- 图像的离散傅里叶变换
- 图像的二维傅里叶变换
- 图像的傅里叶变换
- 图像的傅里叶变换
- 图像处理的傅里叶变换
- 22. Generate Parentheses My Submissions QuestionEditorial Solution
- Java 类 内部类的使用
- CGGeometry
- 各种有用的PHP开源库收集
- Eclipse之Git修改文件标记
- java使用傅里叶变换,得到变换之后的傅里叶频谱图像。
- MySQL 登录报错 1045
- jQuery URL Parser
- memcached 在 windows的配置
- Appium遇到的问题和解决方法
- JS产生随机数的几个用法!
- 如何优雅的实现界面跳转 之 统跳协议
- 88 boost智能指针(二)
- 第七周周赛——字典树 + 线段树 + 树状数组等等(去师大比赛前的最后一场)