Reputation: 51
I'm trying to implement a 2d fourier transform on an image. I have it so my DFT and inverse DFT work on an image. But when I apply the filter, by multiplying the complex numbers, and inverse the result I just get image noise.
Here is my 2d DFT
public void dft(double[][] inreal, double[][] inimag) {
int n = inreal.length;
double[][] tempreal = new double[n][n];
double[][] tempimag = new double[n][n];
realArray = new double[n][n];
imagArray = new double[n][n];
for(int row = 0; row < n; row++) {
for (int col = 0; col < n; col++) {
double sumreal = 0;
double sumimag = 0;
for (int t = 0; t < n; t++) {
double angle = 2 * Math.PI * t * col / n;
sumreal += inreal[row][t] * Math.cos(angle) + inimag[row][t] * Math.sin(angle);
sumimag += -inreal[row][t] * Math.sin(angle) + inimag[row][t] * Math.cos(angle);
}
//System.out.println("r" + row + " " + "c" + col + " " + sumreal + " " + sumimag);
tempreal[row][col] = sumreal;
tempimag[row][col] = sumimag;
}
}
//now do it over the columns
for (int col = 0; col < n; col++) {
for (int row = 0; row < n; row++) { // For each output element
double sumreal = 0;
double sumimag = 0;
for (int t = 0; t < n; t++) { // For each input element
double angle = 2 * Math.PI * t * row / n;
sumreal += tempreal[t][col] * Math.cos(angle) + tempimag[t][col] * Math.sin(angle);
sumimag += -tempreal[t][col] * Math.sin(angle) + tempimag[t][col] * Math.cos(angle);
}
realArray[row][col] = sumreal;
imagArray[row][col] = sumimag;
//System.out.println(realArray[row][col] + " " + imagArray[row][col] + "i");
}
}
}
And here is my inverse DFT
public void inverseDFT(double[][] inRealArray, double[][] inImagArray) {
int n = realArray.length;
outRealArray = new double[n][n];
outImagArray = new double[n][n];
outputarray = new int[n][n];
double[][] tempreal = new double[n][n];
double[][] tempimag = new double[n][n];
for (int col = 0; col < n; col++) {
for (int row = 0; row < n; row++) { // For each output element
double sumreal = 0;
double sumimag = 0;
for (int t = 0; t < n; t++) { // For each input element
double angle = 2 * Math.PI * t * row / n;
sumreal += inRealArray[t][col] * Math.cos(angle) - inImagArray[t][col] * Math.sin(angle);
sumimag += inRealArray[t][col] * Math.sin(angle) + inImagArray[t][col] * Math.cos(angle);
}
//System.out.println("r" + row + " " + "c" + col + " " + sumreal + " " + sumimag);
tempreal[row][col] = sumreal;
tempimag[row][col] = sumimag;
}
}
//now do it over the columns
for(int row = 0; row < n; row++) {
for (int col = 0; col < n; col++) { // For each output element
double sumreal = 0;
double sumimag = 0;
for (int t = 0; t < n; t++) { // For each input element
double angle = 2 * Math.PI * t * col / n;
sumreal += tempreal[row][t] * Math.cos(angle) - tempimag[row][t] * Math.sin(angle);
sumimag += tempreal[row][t] * Math.sin(angle) + tempimag[row][t] * Math.cos(angle);
}
outRealArray[row][col] = sumreal / (n * n);
outImagArray[row][col] = sumimag / (n * n);
outputarray[row][col] = (int)Math.abs(outRealArray[row][col]);
//System.out.println(outRealArray[row][col] + " " + outImagArray[row][col] + "i");
}
}
}
The image goes through and comes back the same. I shifted the image to the center and got the spectral image to test if it works.
This is the magnitude of the complex number and shifted to the center
The Low Pass Filter
The Filter put through the DFT.
Here's my code to multiply the two.
public void applyLowPassFilter(String filename, double[][] realArray, double[][] imagArray) throws IOException {
ReadPGMFile readPGM = new ReadPGMFile(filename);
double[][] filterArrayR = readPGM.loadArray();
double[][] filterArrayI = new double[filterArrayR.length][filterArrayR.length];
FourierTransform ft = new FourierTransform();
ft.dft(filterArrayR, filterArrayI);
filterReal = ft.getRealArray();
filterImag = ft.getImagArray();
int n = realArray.length;
resultRealArray = new double[n][n];
resultImagArray = new double[n][n];
for(int i = 0; i < n; i++){
int colValue = 0;
int rowValue = 0;
for(int j = 0; j < n; j++) {
if(j < n / 2 ){
colValue = (n / 2) - j;
} else {
colValue = (n - 1) - (j - ((n - 1) / 2));
}
if (i < n / 2) {
rowValue = (n / 2) - i;
} else {
rowValue = (n - 1) - (i - ((n - 1) / 2));
}
resultRealArray[i][j] = realArray[rowValue][colValue] * filterReal[i][j] - imagArray[rowValue][colValue] * filterImag[i][j];
resultImagArray[i][j] = realArray[rowValue][colValue] * filterImag[i][j] + imagArray[rowValue][colValue] * filterReal[i][j];
}
}
}
This is the result that I am getting. Sorry for the long post. If anyone has any insights I would appreciate them. I've been struggling with this for a few weeks now.
Upvotes: 0
Views: 1310
Reputation: 2682
Here's the code I use to test it:
int[] pix=bim.getRGB(0, 0, wc, hc, null, 0, wc);
double[][] ri=new double[hc][hc], ii=new double[hc][hc], ro=new double[hc][hc], io=new double[hc][hc];
for(i=0; i<hc; 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[i][j]=0.2126*rr+0.7152*rg+0.0722*rb;
}
double[][] ff=new double[hc][hc];
ff[hc/2][hc/2]=ff[hc/2][hc/2+1]=ff[hc/2][hc/2-1]=ff[hc/2+1][hc/2]=ff[hc/2-1][hc/2]=1;
// ff[hc/2][hc/2]=ff[hc/2][hc/2+1]=ff[hc/2][hc/2-1]=ff[hc/2+1][hc/2]=ff[hc/2-1][hc/2]=ff[hc/2-1][hc/2-1]=ff[hc/2-1][hc/2+1]=ff[hc/2+1][hc/2-1]=ff[hc/2+1][hc/2+1]=0.125;
filterDFT(ff, ri, ro, io);
int[] pix2=new int[hc*hc];
for(i=0; i<hc; i++)
for(j=0; j<hc; j++) pix2[i+j*hc]=0xff000000|(int)Math.abs(ro[i][j]);
BufferedImage b2=new BufferedImage(hc, hc, BufferedImage.TYPE_INT_RGB);
b2.setRGB(0, 0, hc, hc, pix2, 0, hc);
Now b2 is your image; and it shows well - you have to reshuffle the quadrants.
Therefore I suggest you take a second look at what your filter reading downloads.
Upvotes: 1