我创建了一个过滤器,用于渲染图像的2D FFT(快速傅里叶变换)。在实际应用中,图像来自实时数据馈送。问题是只有极低的频率才能记录,所以我看到的是一个平坦的灰色图像,左上角有一个点(最低频率)。任何人都可以建议一种修复此代码的方法,以便它显示的不仅仅是左上角有几个点的平面图像吗?
我相信这是代码中的问题区域。这使2D FFT结果平方以消除虚部,然后对其进行缩放。
ctmp.setTo(result_r[x][y]); // Copy Result to ctmp
ctmp.mult(result_r[x][y]); // Square the result to eliminate imaginary part
cval = 127 + (127 * ctmp.real/ max);
tmpc = (int) Math.floor(cval);
//System.out.println(String.format("tmpc=%d %f",tmpc,ctmp.real));
if (tmpc > 255d) {
rgb |= 255 << 16;
} else if (tmpc >= 0d){
rgb |= ((tmpc << 16) & (255 << 16));
}
完整来源
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package physics.filters;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
import physics.Filter;
// http://www.cs.virginia.edu/~wm2a/applets/Transformation/Complex.java
import physics.helpers.Complex;
// http://www.cs.virginia.edu/~wm2a/applets/Transformation/Fourier2D.java
import physics.helpers.Fourier2D;
/**
*
* @author rritoch
*/
public class FFTFilter
implements Filter {
BufferedImage last = null;
boolean is_init = false;
int imageW;
int imageH;
int fftW;
int fftH;
BufferedImage fftImage;
Fourier2D fourier2d;
Complex[][] complex2d_r; // red buffer
Complex[][] complex2d_g; // green buffer
Complex[][] complex2d_b; // blue buffer
public static BufferedImage cloneImage(BufferedImage bi) {
ColorModel cm = bi.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = bi.copyData(null);
return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}
/**
* Init/Re-init Cache
*
*/
void computeParams(BufferedImage in) {
imageW = in.getWidth();
imageH = in.getHeight();
fftW = 1;
fftH = 1;
while(fftW < imageW) {
fftW = fftW << 1;
}
while(fftH < imageH) {
fftH = fftH << 1;
}
fftImage = new BufferedImage(fftW, fftH, in.getType());
fourier2d = new Fourier2D(fftW,fftH);
complex2d_r = new Complex[fftW][];
complex2d_g = new Complex[fftW][];
complex2d_b = new Complex[fftW][];
for(int idx=0;idx<fftW;idx++) {
complex2d_r[idx] = new Complex[fftH];
complex2d_g[idx] = new Complex[fftH];
complex2d_b[idx] = new Complex[fftH];
for(int idy=0;idy<fftH;idy++) {
complex2d_r[idx][idy] = new Complex();
complex2d_g[idx][idy] = new Complex();
complex2d_b[idx][idy] = new Complex();
}
}
System.out.println(String.format("Init FFTFilter (%d,%d)!",fftW,fftH));
}
void fft(BufferedImage img)
{
Graphics2D gr;
Complex[][] result_r;
Complex[][] result_g;
Complex[][] result_b;
int x,y;
Complex ctmp = new Complex();
double cval;
int rgb,tmpc;
gr = fftImage.createGraphics();
gr.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
gr.drawImage(img, 0, 0, fftW, fftH, 0, 0, img.getWidth(), img.getHeight(), null);
gr.dispose();
// Copy values from img to complex2d
for(y=0;y<fftH;y++) {
for(x=0;x<fftW;x++) {
rgb = fftImage.getRGB(x,y);
double r = new Double(rgb & 255);
double g = new Double((rgb >> 8) & 255);
double b = new Double((rgb >> 16) & 255);
complex2d_r[x][y].imag = 0;
complex2d_r[x][y].real = r - 127d;
complex2d_g[x][y].imag = 0;
complex2d_g[x][y].real = g - 127d;
complex2d_b[x][y].imag = 0;
complex2d_b[x][y].real = b - 127d;
}
}
// Calculate FFT
result_r = fourier2d.fft(complex2d_r);
result_g = fourier2d.fft(complex2d_g);
result_b = fourier2d.fft(complex2d_b);
// Scan result for Min & Max
double max = 0;
double min = 0;
for(y=0;y<fftH;y++) {
for(x=0;x<fftW;x++) {
ctmp.setTo(result_r[x][y]);
ctmp.mult(result_r[x][y]);
if (ctmp.real > max) {
max = ctmp.real;
} else if (ctmp.real < min) {
min = ctmp.real;
}
ctmp.setTo(result_g[x][y]);
ctmp.mult(result_g[x][y]);
if (ctmp.real > max) {
max = ctmp.real;
} else if (ctmp.real < min) {
min = ctmp.real;
}
ctmp.setTo(result_b[x][y]);
ctmp.mult(result_b[x][y]);
if (ctmp.real > max) {
max = ctmp.real;
} else if (ctmp.real < min) {
min = ctmp.real;
}
}
}
System.out.println(String.format("Size: %f,%f",min,max));
// compute absolute max
max = Math.abs(min) > max ? Math.abs(min) : max;
// Map result onto fftImage
for(y=0;y<fftH;y++) {
for(x=0;x<fftW;x++) {
rgb = 0;
ctmp.setTo(result_r[x][y]);
ctmp.mult(result_r[x][y]);
cval = 127 + (127 * ctmp.real/ max);
tmpc = (int) Math.floor(cval);
//System.out.println(String.format("tmpc=%d %f",tmpc,ctmp.real));
if (tmpc > 255d) {
rgb |= 255 << 16;
} else if (tmpc >= 0d){
rgb |= ((tmpc << 16) & (255 << 16));
}
ctmp.setTo(result_g[x][y]);
ctmp.mult(result_g[x][y]);
cval = 127 + (127 * ctmp.real/ max);
tmpc = (int) Math.floor(cval);
if (tmpc > 255d) {
rgb |= 255 << 8;
} else if (tmpc >= 0d){
rgb |= ((tmpc << 8) & (255 << 8));
}
ctmp.setTo(result_b[x][y]);
ctmp.mult(result_b[x][y]);
cval = 127 + (127 * ctmp.real/ max);
tmpc = (int) Math.floor(cval);
if (tmpc > 255d) {
rgb |= 255;
} else if (tmpc >= 0d){
rgb |= (tmpc & 255);
}
fftImage.setRGB(x, y, rgb);
}
}
// Copy fft Image to image
gr = img.createGraphics();
gr.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
gr.drawImage(fftImage, 0, 0, img.getWidth(), img.getHeight(), 0, 0, fftImage.getWidth(), fftImage.getHeight(), null);
gr.dispose();
}
@Override
public BufferedImage filter(BufferedImage in) {
if (last == null || last.getWidth() != in.getWidth() || last.getHeight() != in.getHeight()) {
computeParams(in);
}
BufferedImage ret = cloneImage(in);
fft(ret);
last = in;
return ret;
}
}
注意:这是我第一次使用这个特殊的FFT,我还没有验证FFT算法是否正确,所以我假设FFT算法是正确的。
答案 0 :(得分:1)
请注意,这些行不会消除虚部
ctmp.setTo(result_r[x][y]); // Copy Result to ctmp
ctmp.mult(result_r[x][y]); // Square the result to eliminate imaginary part
(a + i * b)(a + i * b)= a ^ 2 - b ^ 2 + i *(a + b)
我建议您需要复数的幅度(模数)
Amp = Sqrt(ctmp.real^2 + ctmp.imaginary^2)
(可能你在复杂的课程中有特殊功能)