Hello,

I am required to implement a 1D then 2D DFT on an image. The problem is, I can implement both 1D & 2D DFT on a 2D array and it produces the "right result" except:

1. my answer often floats in 0 i.e.

for(int u = 0; u < n; u++)
	{
		gReal_output[u] = 0;
		gImagi_output[u] = 0;

		if(!inverse) // bool = 0
			{
		for (int x = 0; x < n; x++)
		{
			//cos theta and sin theta
			double factor = (-2 * PI * u * x) /n;
			double cos_factor = cos(factor);
			double sin_factor = sin(factor);

			gReal_output[u] += ((gReal_input[x] * cos_factor)- (gImagi_input[x] * sin_factor));
			gImagi_output[u] += ((gReal_input[x] * sin_factor) - (gImagi_input[x] * cos_factor));

		}
			}
		if(inverse) //  bool = 1
			{
			for (long x = 0; x < n; x++)
		{
			double factor = (2 * PI * u * x) / n;
			double cos_factor = cos(factor);
			double sin_factor = sin(factor);

			gReal_output[u] += (((gReal_input[x] * cos_factor) - (gImagi_input[x] * sin_factor)) / n);
			gImagi_output[u] += (((gReal_input[x] * sin_factor)- (gImagi_input[x] * cos_factor)) / n);
		}
			}
	cout /*<< fixed << setprecision(0)*/ << gReal_output[u] << " + j " << gImagi_output[u] << endl;
	}
//Output when fReal_input[4] = {1,2,4,4}
1D DFT:
11 + j0 //correct
-3 + j2 //correct
-1 + j2.46124e-009 // not correct. Answer should be -1+j0
-3 + j-2 //correct
//Inverse DFT
1D DFT(inverse)
1 + j -2.25614e-009 // not correct. Answer should be 1 + j0
2 + j 3.1791e-009 // not correct. Answer should be 2 + j0
4 + j 2.05103e-0.009 // not correct. Answer should be 4 + j0
4 + j -2.35869e-009 // not correct. Answer should be 4 + j0

2. My second problem !!IMPORTANT!! is that I have implemented my 2D DFT using a 2D array. Which works... (except for the floating in 0). But I want to implement the 2D DFT on an image. I have read that I have to shift the output images to center (DON'T UNDERSTAND HOW TO). OR how to output my real, imaginary and amplitude values to their respective output images. Here is my 2D DFT implementation. It is not outputting my real and imaginary values. And I don't know how to center the images.. PLS HELP!!

void TwoDFT(int n, int m,/* bool inverse,*/ double  *gReal_input, double *gImagi_input, double *gReal_output, double *gImagi_output)
{
       std::vector<double> TempReal(m*n);
	std::vector<double> TempImagi(m*n);

	//calculate the FT of the width of the image
	for(int x = 0; x < n; x++)
	{
		//1D-DFT function
		for (int w = 0; w < m; w++)
		{
			TempReal[m*x + w] = 0;
			TempImagi[m*x + w] = 0;
			for (int y = 0; y < m; y++)
			{
				double factor = (-2 * PI * w * y) / (float) m;
				double cos_factor = cos(factor);
				double sin_factor = sin(factor);
				TempReal[m*x + w] += ((gReal_input[m*x + y] * cos_factor) - (gImagi_input[m*x + y] * sin_factor));
				TempImagi[m*x + w] += ((gReal_input[m*x + y] * sin_factor) - (gImagi_input[m*x + y] * cos_factor));

			}
			cout << TempReal[m*x + w] << endl;
			cout << " j: " << TempImagi[m*x + w] << endl;
		}
	}
	//calculate the FT of the height of the image
	for(int y = 0; y < m; y++)
	{
		//1D-DFT function
		for (int w = 0; w < n; w++)
		{
			for (int x = 0; x < n; x++)
			{
				double factor = (-2 * PI * w * x) / (float) n;
				double cos_factor = cos(factor);
				double sin_factor = sin(factor);
				gReal_output[m*w + y] += ((TempReal[m*x + y] * cos_factor) - (TempImagi[m*x + y] * sin_factor));
				gImagi_output[m*w + y] += ((TempReal[m*x + y] * sin_factor) - (TempImagi[m*x + y] * cos_factor));
			}
			cout << gReal_output[m*w + y] << endl;
			cout << " j " << gImagi_output[m*w + y] << endl;
		}
		
	}
/* Inverse code not included intentionally */
}

//then at the main function...
void DFTFunction()
{
	
	//Load image
	img = cvLoadImage("Images/CH04/LENAG.bmp", 1);
	image = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
	cvCvtColor(img, image,CV_BGR2GRAY);

	//Calculate the height and width of the image
	height = image->height;
	width = image->width;
	step  = image->widthStep;
	cout << "Height :" << height << endl;
	cout << "Width :" << width << endl;
	data = (uchar*) image->imageData;
IplImage *realImage = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
	uchar *realImage_data = (uchar*)realImage->imageData;

	//set the arrays to the input image. Input image is real.
	for(int j = 0; j < width; j++) // note: width j comes before height in order to access the transform in columns
	{
		for(int i = 0; i < height; i++)
		{
			 f2DReal_input[j][i] = data[((width * i) + j)];
			 realImage_data[((width * i) + j)] = f2DReal_input[j][i]; 
		}
	}
	//imaginary array is set to zero.
	IplImage *imagImage = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
	uchar *imagImage_data = (uchar*)imagImage->imageData;

	for(int j = 0; j < width; j++) // note: width j comes before height in order to access the transform in columns
	{
		for(int i = 0; i < height; i++)
		{
			 f2DImagi_input[j][i] = 0;
			 imagImage_data[((width * i) + j)] = f2DImagi_input[j][i]; 
		}
	}

cvSaveImage("real_Image_out.png", realImage);
	cvSaveImage("imag_Image_out.png", imagImage);

	cout << endl <<  "2D DFT: " << endl << endl;
	TwoDFT(N, M, f2DReal_input[0], f2DImagi_input[0], f2DReal_output[0], f2DImagi_output[0]);
	
	IplImage *real2DImage = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
	uchar *real2DImage_data = (uchar*)real2DImage->imageData;

	for(int j = 0; j < width; j++) // note: width j comes before height in order to access the transform in columns
	{
		for(int i = 0; i < height; i++)
		{
			// f2DImagi_input[j][i] = 0;
			 real2DImage_data[((width * i) + j)] = f2DReal_output[j][i]; 
		}
	}

	IplImage *imag2DImage = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
	uchar *imag2DImage_data = (uchar*)imag2DImage->imageData;

	for(int j = 0; j < width; j++) // note: width j comes before height in order to access the transform in columns
	{
		for(int i = 0; i < height; i++)
		{
			 imag2DImage_data[((width * i) + j)] = f2DImagi_output[j][i]; 
		}
	}

	cvSaveImage("real_Image_out1.png", real2DImage);
	cvSaveImage("imag_Image_out1.png", imag2DImage);

        cvReleaseImage(&image);
	cvReleaseImage(&id);
	cvReleaseImage(&realImage);
	cvReleaseImage(&imagImage);
	cvReleaseImage(&real2DImage);
	cvReleaseImage(&imag2DImage);
}

For the zero problem you can have a cutoff value. Example :

float bandwidthCuttoff(const float value, const float width = 0.000001f){
 if(-width <= value && value <= width) return 0.0f;
 else return value;
}

then you just pass the j (imaginary part) to this function to make a cut if needed.

This article has been dead for over six months. Start a new discussion instead.