Discrete Fourier transformation

A discrete Fourier transformation of a 1D or 2D array, or in other words—an image, is one of the many ways to analyze an image in computer vision. The interpretation of the result depends completely on the field it is being used for and that is not what we are concerned with in this book, however, how to perform a discrete Fourier transformation is what we're going to learn in this section.

Simply put, you can use the dft function to calculate the Fourier transformation of an image. However, there are some preparations needed before the dft function can be safely called. The same applies to the result of the Fourier transformation. Let's break this down with an example code, and by calculating and displaying the Fourier transformation of our example image used in the previous sections.

The dft function can process matrices of certain sizes (powers of 2, such as 2, 4, and 8) a lot more efficiently, that is why it is always best to increase the size of our matrix to the nearest optimum size and pad it with zeroes before calling the dft function. This can be done by using the getOptimalDFTSize function. Assuming that image is the input image that we want to calculate its discrete Fourier transformation, we can write the following code to calculate and resize it to the optimum size for the dft function:

int optRows = getOptimalDFTSize( image.rows ); 
int optCols = getOptimalDFTSize( image.cols ); 
 
Mat resizedImg; 
copyMakeBorder(image, 
               resizedImg, 
               0, 
               optRows - image.rows, 
               0, 
               optCols - image.cols, 
               BORDER_CONSTANT, 
               Scalar::all(0)); 

As you can see, the getOptimalDFTSize function must be called twice, for rows and columns separately. You are already familiar with the copyMakeBorder function. Resizing an image and padding the new pixels with zeroes (or any other desired value) is one of countless example use cases for the copyMakeBorder function.

The rest is quite easy, we need to form a two-channel image and pass it to the dft function and get the complex (real and imaginary) result in the same matrix. This will later simplify the process of displaying the result. Here's how it's done:

vector<Mat> channels = {Mat_<float>(resizedImg), 
                   Mat::zeros(resizedImg.size(), CV_32F)}; 
 
Mat complexImage; 
merge(channels, complexImage); 
 
dft(complexImage, complexImage); 

We have already learned how to use the merge function. The only important thing to note in the preceding code is the fact that the result is saved into the same image as the input. complexImage now contains two channels, one for the real and the other for the imaginary part of the discrete Fourier transformation. That's it! We now have our result, however, to be able to display it, we must calculate the magnitude of the result. Here's how it's done:

split(complexImage, channels); 
 
Mat mag; 
magnitude(channels[0], channels[1], mag); 

In the preceding code, we have split the complex result into its consisting channels and then calculated the magnitude using the magnitude function. Theoretically, mag is a displayable result, but in reality, it contains values much higher than what is displayable using OpenCV, so we need to perform a couple of conversions before being able to display it. First, we need to make sure the result is in the logarithmic scale, by performing the following conversion:

mag += Scalar::all(1); 
log(mag, mag); 

Next, we must make sure the result values are scaled and normalized to fit between 0.0 and 1.0, to be displayable by the imshow function in OpenCV. You need to use the normalize function for this reason:

normalize(mag, mag, 0.0, 1.0, CV_MINMAX);

You can now try to display the result using the imshow function. Here's an example that displays the result of the discrete Fourier transformation:

The problem with this result is that the quadrants need to be swapped before the origin of the result is at the center of the image. The following image depicts how the four quadrants of the result must be swapped before the result has an origin point at the center:

The following is the code needed to swap the four quadrants of the Fourier transform result. Notice how we first find the center of the result, then create four region of interest (ROI) matrices, and then swap them:

int cx = mag.cols/2; 
int cy = mag.rows/2; 
 
Mat Q1(mag, Rect(0, 0, cx, cy)); 
Mat Q2(mag, Rect(cx, 0, cx, cy)); 
Mat Q3(mag, Rect(0, cy, cx, cy)); 
Mat Q4(mag, Rect(cx, cy, cx, cy)); 
 
Mat tmp; 
Q1.copyTo(tmp); 
Q4.copyTo(Q1); 
tmp.copyTo(Q4); 
 
Q2.copyTo(tmp); 
Q3.copyTo(Q2); 
tmp.copyTo(Q3); 

The dft function accepts an additional parameter that can be used to further customize its behavior. This parameter can be a combination of values from the DftFlags enum. For instance, to perform an inverse Fourier transformation, you need to call the dft function with the DFT_INVERSE parameter:

dft(input, output, DFT_INVERSE); 

This can also be done by using the idft function:

idft(input, output); 

Make sure to check out the DftFlags enum and the dft function documentation for more information about how the discrete Fourier transform is implemented in OpenCV.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.219.81.43