问题
I am trying to apply the FFT on the color images. I extract the three components: red, green and blue then I apply fft2
to each one separately then I applied a Gaussian filter in each plane. Now I am trying to show the red, green and blue components after blurred. After, I apply ifft2
to get the result.
My problem is I see a gray image in each component. I am trying to show just the color planes alone but my code does not work. In addition, I want to combine these three components together to return back to the full color image. I wrote the following code below. Can anyone tell me what I'm doing wrong?
% Calculate FFT for R , G , B images
I = imread ('lena.jpg');
% Extract three images
Red = I (: , : , 1);
Green = I (: , : , 2);
Blue = I(: , : , 3);
f_r = fftshift (Red);
F_r = fft2 (f_r);
f_g = fftshift (Green);
F_g = fft2 (f_g);
f_b = fftshift (Blue);
F_b = fft2 (f_b);
% Calculate the gaussian filter then find its FFT
h = fspecial( 'gaussian', [512 512] , 3.0 );
h = fftshift (h);
H = fft2(h); % Fourier Transform of 2D Gaussian
FF_R = H .* F_r ;
FF_G = H .* F_g;
FF_B = H .* F_b;
% This is to get red, green and blue images
b = zeros(512, 512);
% Inverse IFFT _RED
Ir = ifftshift(FF_R);
Irr= ifft2 (Ir);
I_R = fftshift (Irr);
IFF_R = 1 + log (abs(I_R));
figure , imshow (IFF_R , [ ]);
Con1 = im2uint8(IFF_R);
just_red_2 = cat(3, Con1, b, b);
figure, imshow (just_red_2);
% Inverse IFFT _Green
Ig = ifftshift(FF_G);
Igg= ifft2 (Ig);
I_G = fftshift (Igg);
figure , imshow (1+ log(abs(I_G)), [ ]);
just_green_2 = cat(3, b, I_G, b);
%figure, imshow (1 + log(abs(just_green_2)) );
% Inverse IFFT Blue
Ib = ifftshift(FF_B);
Ibb= ifft2 (Ib);
I_B = fftshift (Ibb);
figure , imshow (1+ log(abs(I_B)), [ ]);
just_blue_2 = cat(3, b,b, I_B);
%figure, imshow (1 + log(abs(just_blue_2)) );
%Combine the three component togather
%full_image2 = cat (3, FF_R , FF_G , FF_B);
full_image2 = cat (3, just_red_2 (:,:,1) , just_green_2(:,:,2) , just_blue_2(:, :, 3));
%full_image2 (: , : , 1) = FF_R (: , : , 1);
%full_image2 (: , : , 2) = FF_G (: , : , 2);
%full_image2 (: , : , 3) = FF_B (: , : , 3);
Full = ifft2 ( ifftshift(full_image2));
figure, imshow (Full , [ ])
Final = fftshift(Full);
figure , imshow ( full_image2 )
回答1:
You're doing a lot of unnecessary computations. Once you filter the planes separately, you can combine them immediately. Also, your red component is performing a log
transformation, while the other colour channels don't have this performed. In addition, you actually need to perform the fftshift
once you transform the image so that you can centre the spectrum. You did the fftshift
first, which is incorrect. The same thing needs to be applied to your filter definition. Once you filter the image, you have to reverse your operations carefully. The forward transformation consists of doing fft2
followed by fftshift
. The reverse operations require you to ifftshift
, then ifft2
after. You go in the reverse direction of your operations.
One thing I need to stress is that you need to cast your image planes to double to keep the precision of the computation intact. You don't do this, and so all of the computation is done in uint8
.
It also is good to note that there may be some residual imaginary values after you perform the ifft2
, so it's best to use real
to eliminate the imaginary components. As per your comments, I've made a figure that displays the red, green and blue components with their hues intact, as well as the final blurred image in a 2 x 2 pane.
With this, here's your code modified to suit my comments. You also did not include your image with your post, but I used a version of Lena on Wikipedia:
Now, bear in mind that I removed a lot of your code to achieve your objective:
% Calculate FFT for R , G , B images
I = imread ('https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png');
I = double(I); %// Change - cast to double
% Extract three images
Red = I (: , : , 1);
Green = I (: , : , 2);
Blue = I(: , : , 3);
% // Change - Transform, then shift
f_r = fft2(Red);
F_r = fftshift(f_r);
f_g = fft2(Green);
F_g = fftshift(f_g);
f_b = fft2(Blue);
F_b = fftshift(f_b);
% Calculate the gaussian filter then find its FFT
h = fspecial( 'gaussian', [512 512] , 3.0 );
%// Change - Filter, then FFT shift
H = fft2(h); % Fourier Transform of 2D Gaussian
H = fftshift(H);
% // Now filter
FF_R = H .* F_r ;
FF_G = H .* F_g;
FF_B = H .* F_b;
%// Change - perform ifftshift, then ifft2, then cast to real
% Inverse IFFT _RED
Ir = ifftshift(FF_R);
Irr = fftshift(real(ifft2(Ir)));
% Inverse IFFT _Green
Ig = ifftshift(FF_G);
Igg = fftshift(real(ifft2(Ig)));
% Inverse IFFT _Blue
Ib = ifftshift(FF_B);
Ibb = fftshift(real(ifft2(Ib)));
%// Visualize the red, green and blue components
b = zeros(512, 512, 'uint8');
image_red = cat(3,Irr, b, b);
image_green = cat(3, b, Igg, b);
image_blue = cat(3, b, b, Ibb);
%Combine the three component together
%// Change - Removed fluff
b = uint8(cat(3, Irr, Igg, Ibb));
%// NEW - Display each component as well as the final image in a new figure
figure;
subplot(2,2,1);
imshow(image_red);
subplot(2,2,2);
imshow(image_green);
subplot(2,2,3);
imshow(image_blue);
subplot(2,2,4);
imshow(b);
This is the figure I get:
来源:https://stackoverflow.com/questions/26744673/low-pass-filtering-a-color-image-using-the-fft-and-ifft