I am trying to implement a 2D DFT using a combination of 1D DFT in Matlab. When comparing my results against Matlab's inbuilt function (fft2) I realized that I have the following issues:
This image shows the comparison between the two results. The red numbers on the side are there to indicate the reordering issue.
My code is as follows:
x = imread('img.png');
x = double(x);
x = x(1:12,1:5)
% FFT
Xw = complex(zeros(size(x)));
for row = 1:size(x,1)
Xw(row,:) = fft(x(row,:));
end
for col = 1:size(x,2)
Xw(:,col) = fft(Xw(:,col)');
end
Could someone kindly indicate where my problem is please? Thanks
The '
operator is for the complex transpose, which means that the matrix is transposed and the conjugate of the values is taken. This means that the signs of the complex values are reversed. You don't notice this with real numbers because technically, the imaginary component is zero.
You want to use .'
instead to preserve the sign of the imaginary component as performing the intermediate FFT per row will result in complex values. Using just '
will change the imaginary components of the intermediate results, which will give you the wrong results:
for col = 1:size(x,2)
Xw(:,col) = fft(Xw(:,col).');
end
BTW, as a minor note, there is no need to transpose the intermediate columns of your result at all. If you provide a single vector, fft
will operate along the first non-singleton dimension, and so using a transpose is superfluous. It would actually help if you didn't transpose your result at all:
for col = 1:size(x,2)
Xw(:,col) = fft(Xw(:,col));
end
Here's an example. I've generated a random 10 x 10 matrix:
rng(123);
x = rand(10);
Using your code with correcting the transpose (and without the indexing at the beginning), we get:
>> Xw
Xw =
Columns 1 through 5
50.1429 + 0.0000i -0.4266 - 0.2624i 0.8803 + 0.9311i -0.0526 + 1.7067i 0.7187 + 0.7161i
0.5066 - 2.4421i 2.7551 - 1.7421i -1.9994 + 0.6052i 0.2891 + 3.4182i 0.5300 + 2.4417i
0.1956 + 0.1790i 4.1461 + 1.9648i -1.3781 - 1.0303i -0.6872 - 1.0103i -1.2184 - 0.5783i
-0.3645 - 1.6193i -1.8470 - 1.3445i 4.1555 + 0.7432i 2.3707 + 3.8265i -1.9526 + 1.9464i
-3.1136 - 0.3704i 2.4132 - 1.0795i -0.2255 + 1.3062i 0.8436 - 0.5157i -0.3493 - 0.9994i
-1.5962 + 0.0000i -0.3780 - 1.4055i 1.6242 - 0.4842i 0.4457 + 0.4718i -0.1794 - 2.0014i
-3.1136 + 0.3704i 0.0134 + 0.1267i 1.0630 + 1.4563i -0.8864 - 0.3174i -0.5720 + 1.3041i
-0.3645 + 1.6193i 0.7028 + 0.2797i 0.1064 + 2.0705i 2.1644 + 0.1685i 0.3095 + 0.7426i
0.1956 - 0.1790i 2.3511 + 2.1440i 0.7301 - 0.8264i -1.1974 - 0.3794i -2.4981 + 1.2363i
0.5066 + 2.4421i -3.5897 + 0.7444i 1.2191 - 3.6386i -2.9659 - 1.6626i -2.0339 + 0.0880i
Columns 6 through 10
2.0373 + 0.0000i 0.7187 - 0.7161i -0.0526 - 1.7067i 0.8803 - 0.9311i -0.4266 + 0.2624i
-1.8782 - 0.9047i -2.0339 - 0.0880i -2.9659 + 1.6626i 1.2191 + 3.6386i -3.5897 - 0.7444i
2.3752 + 1.8811i -2.4981 - 1.2363i -1.1974 + 0.3794i 0.7301 + 0.8264i 2.3511 - 2.1440i
4.5213 + 0.9237i 0.3095 - 0.7426i 2.1644 - 0.1685i 0.1064 - 2.0705i 0.7028 - 0.2797i
-1.2259 + 2.1690i -0.5720 - 1.3041i -0.8864 + 0.3174i 1.0630 - 1.4563i 0.0134 - 0.1267i
6.2411 + 0.0000i -0.1794 + 2.0014i 0.4457 - 0.4718i 1.6242 + 0.4842i -0.3780 + 1.4055i
-1.2259 - 2.1690i -0.3493 + 0.9994i 0.8436 + 0.5157i -0.2255 - 1.3062i 2.4132 + 1.0795i
4.5213 - 0.9237i -1.9526 - 1.9464i 2.3707 - 3.8265i 4.1555 - 0.7432i -1.8470 + 1.3445i
2.3752 - 1.8811i -1.2184 + 0.5783i -0.6872 + 1.0103i -1.3781 + 1.0303i 4.1461 - 1.9648i
-1.8782 + 0.9047i 0.5300 - 2.4417i 0.2891 - 3.4182i -1.9994 - 0.6052i 2.7551 + 1.7421i
I've also verified that this works without transposing. You'll get the same thing as if you were to perform .'
. Now, using fft2
, we get:
>> Xw2 = fft2(x)
Xw2 =
Columns 1 through 5
50.1429 + 0.0000i -0.4266 - 0.2624i 0.8803 + 0.9311i -0.0526 + 1.7067i 0.7187 + 0.7161i
0.5066 - 2.4421i 2.7551 - 1.7421i -1.9994 + 0.6052i 0.2891 + 3.4182i 0.5300 + 2.4417i
0.1956 + 0.1790i 4.1461 + 1.9648i -1.3781 - 1.0303i -0.6872 - 1.0103i -1.2184 - 0.5783i
-0.3645 - 1.6193i -1.8470 - 1.3445i 4.1555 + 0.7432i 2.3707 + 3.8265i -1.9526 + 1.9464i
-3.1136 - 0.3704i 2.4132 - 1.0795i -0.2255 + 1.3062i 0.8436 - 0.5157i -0.3493 - 0.9994i
-1.5962 + 0.0000i -0.3780 - 1.4055i 1.6242 - 0.4842i 0.4457 + 0.4718i -0.1794 - 2.0014i
-3.1136 + 0.3704i 0.0134 + 0.1267i 1.0630 + 1.4563i -0.8864 - 0.3174i -0.5720 + 1.3041i
-0.3645 + 1.6193i 0.7028 + 0.2797i 0.1064 + 2.0705i 2.1644 + 0.1685i 0.3095 + 0.7426i
0.1956 - 0.1790i 2.3511 + 2.1440i 0.7301 - 0.8264i -1.1974 - 0.3794i -2.4981 + 1.2363i
0.5066 + 2.4421i -3.5897 + 0.7444i 1.2191 - 3.6386i -2.9659 - 1.6626i -2.0339 + 0.0880i
Columns 6 through 10
2.0373 + 0.0000i 0.7187 - 0.7161i -0.0526 - 1.7067i 0.8803 - 0.9311i -0.4266 + 0.2624i
-1.8782 - 0.9047i -2.0339 - 0.0880i -2.9659 + 1.6626i 1.2191 + 3.6386i -3.5897 - 0.7444i
2.3752 + 1.8811i -2.4981 - 1.2363i -1.1974 + 0.3794i 0.7301 + 0.8264i 2.3511 - 2.1440i
4.5213 + 0.9237i 0.3095 - 0.7426i 2.1644 - 0.1685i 0.1064 - 2.0705i 0.7028 - 0.2797i
-1.2259 + 2.1690i -0.5720 - 1.3041i -0.8864 + 0.3174i 1.0630 - 1.4563i 0.0134 - 0.1267i
6.2411 + 0.0000i -0.1794 + 2.0014i 0.4457 - 0.4718i 1.6242 + 0.4842i -0.3780 + 1.4055i
-1.2259 - 2.1690i -0.3493 + 0.9994i 0.8436 + 0.5157i -0.2255 - 1.3062i 2.4132 + 1.0795i
4.5213 - 0.9237i -1.9526 - 1.9464i 2.3707 - 3.8265i 4.1555 - 0.7432i -1.8470 + 1.3445i
2.3752 - 1.8811i -1.2184 + 0.5783i -0.6872 + 1.0103i -1.3781 + 1.0303i 4.1461 - 1.9648i
-1.8782 + 0.9047i 0.5300 - 2.4417i 0.2891 - 3.4182i -1.9994 - 0.6052i 2.7551 + 1.7421i
We can show these two are equal by ensuring that all of the element-wise differences between the two matrices is less than a small threshold... say 1e-10
:
>> all(abs(Xw(:)-Xw2(:)) <= 1e-10)
ans =
1
Never use '
for the transpose.... ever. Luis Mendo is a strong advocate of this very fact.