CSE 417 Homework 5, Winter 2011

Do this assignment independently. Submit your written results and graph in class on Wednesday, March 2. Submit your program code via Catalyst by 2:00 PM, Wednesday March 2.

Overall description

Implement, describe, and compare two methods of computing the Discrete Fourier Transform: (a) the direct method, working from the definition on slide 12 of the Powerpoint set on the Fast Fourier Transform. (b) the Fast Fourier Transform, using the form given in the pseudocode on slide 15.

Details

Implement both algorithms. Use either Java or Python. Implement two functions: DirectDFT and FFT. Each should accept its arguments in the following form: FFT(n, cvector) where n is an integer (assumed to be a power of 2) and cvector is a one-dimensional array of complex numbers. In Java the complex vector should be an array of Complex elements, i.e., Complex[]; (for a recommended Java library of complex number methods, see GoPost). In Python, it should be a list of complex numbers, such as [5.0+2.3j, -1.2-0.5j].

Each of DirectDFT and FFT should return a similar cvector containing the Discrete Fourier Transform of the input.

Set up your program so that input to it can be provided in a file of complex numbers. The five-line example below gives one example of the file format. Notice that n is a power of 2, but it is not given explicitly. There just happen to be n complex numbers in the file (and in the example below, n=8). Also, notice that some of the numbers appear to be real numbers, with no imaginary part; the program should simply assume that the imaginary parts of those numbers are zero. We'll use the Python convention that the imaginary unit vector is denoted by "j" (not "i"). Complex numbers on the same line are separated by commas. Spaces are optional and they may occur before or after a number. A complex number will not be split across multiple lines. No comma is necessary at the end of a line, but if it is there, it will not cause an error. A line that begins with "#" is a comment.

2-3j, -2.5+7.75j, 0, -3j, -127
  -101.2999999-102.1j,
# This line is a comment.
# The following line contains the last two numbers.
  2.2,    3+j
This file format has been designed to make it easy for the program to handle both complex data (in which the imaginary parts of numbers are sometimes nonzero) and real data (in which the imaginary parts of numbers are consistently zero). Also, the built-in Python conversion function "complex" can be applied to any of the numbers here (given as strings), and it will properly construct the corresponding complex number. (If you use Java, you may need to write a method that will handle the various cases that are illustrated in the example.)

Test cases

Case 1:
 n = 4
 A(x) = [1.0, 0+j, -1.0, -j]

Case 2:

 n = 8
 (The data is that in the above example input file.)

Case 3:

n = 256
A(x) = 16 cos (4 pi x / 256)

Comparison cases

Using any data of the right dimensions, compare the performance of your two procedures for n = 2, 4, 8, 16, 32, 64, 128, 256, 512, and if your DirectDFT doesn't take too long, also 1024, 2048, and 4096. Give the running times in millisec, and draw a graph that shows how they compare.

Coding

Comment your code clearly using any format you like. The comments should explain how each part of your code implements its part of the algorithm, or whatever else it is there for.

Points

(a) DirectDFT: 10 points
(b) FFT: 20 points
(c) Test cases: 10 + 10 + 10
(d) Comparison runs and Graph: 20
(e) Comments: 20
Items a, b, c and e should be submitted via Catalyst. (Your comments will be in your code. Your DirectDFT and FFT can either be in the same file or separate files. The output for the three test cases can be cut and pasted into a single file, with identifying comments added to show clearly which is which.) Item d should be submitted as hardcopy at the beginning of class: the comparison runs should be presented as a table, with the runtimes given in milliseconds. The graph may be hand-drawn, and it should clearly show your data points as well as the diverging growth rates for the algorithms.

Extra credit (10)

Apply the FFT to the problem of image filtering as follows:
(a) read in a 512 x 512 black-and-white or color image and store it in an array such at the individual pixel values can be easily accessed.
(b) compute the 2D DFT of the image by first transforming each row of the image (obtaining an intermediate array whose elements are complex) and then transforming each column of the intermediate array.
(c) zero out the set of (high) frequency components of the transform, where the set is defined as the union of a region of high horizontal frequency components and a region of high vertical frequency components. Each region should be about half of the transform array. This means roughly one fourth of the transform values will remain potentially nonzero after this step.
(d) inverse-transform the columns of this array getting a new intermediate array.
(e) inverse-transform the rows of the new intermediate array getting a filtered array.
(f) convert the filtered array to an image by taking the modulus of each element and restricting the final value to the range of legal pixel values (typically 0 to 255).
(g) write out the filtered image as a .PNG file.
 
Turn in the extra credit materials via Catalyst. Turn in your extra code in a file ExtraCredit.java or ExtraCredit.py. Turn in both your original and your final .PNG images.
 
Last updated: Feb. 17, 2011.