fft2的abs函数在MATLAB中不起作用

时间:2014-08-24 17:24:47

标签: matlab image-processing fft

我试图在命令窗口中使用以下代码绘制图像的FFT幅度图:

a= imread('lena','png')
figure,imshow(a)
ffta=fft2(a)
fftshift1=fftshift(ffta)
magnitude=abs(fftshift1)
figure,imshow(magnitude),title('magnitude')

但是,标题大小的数字没有显示任何内容,即使MATLAB显示它已在abs()上计算fftshift。这个数字仍然是空的,没有错误。另外,为什么我们需要在幅度之前计算相移?

2 个答案:

答案 0 :(得分:3)

可能发生这种情况的原因是由于以下原因:

  1. 当您拍摄图像的2D fft时,即使您的图像大部分是无符号的8位整数,它也会产生双值结果。 MATLAB假设double格式化图像的强度/颜色介于[0,1]之间。通过仅对幅度本身进行imshow,您很可能会获得完全白色图像,因为我怀疑大多数FFT系数大于1.这可能是空白认为你指的是。
  2. 即使您重新调整幅度以使其在[0,1]之间,DC系数也会如此之大,以至于如果您尝试显示图像,您只会在中间看到一个白点其他所有组件都是黑色的。
  3. 作为旁注,你正在做fftshift的原因是因为默认情况下,MATLAB假设2D的FFT的原点位于左上角。执行fftshift将允许原点位于中间,这是我们直观地期望的2D FFT。


    为了解决这种情况,我建议对FFT系数进行log转换,以便您可以直观地看到结果。我会在log转换系数后对系数进行标准化,使它们在[0,1]之间。 不要实际修改FFT系数,因为这是不合适的。你需要保持它们的相同方式,因为如果你打算对光谱进行任何处理,你将首先处理原始图像。进行滤波器设计或任何类型的操作将需要原始光谱,因为最终滤波器将取决于未触及的这些系数。除非您确实想要将log操作作为管道的一部分,否则请保留这些系数。因此,这可以通过以下MATLAB代码完成:

    imshow(log(1 + magnitude), []);
    

    我将展示一个示例,使用您提供的代码,但使用其他图片,因为您还没有在此处提供。我将使用cameraman.tif图像作为MATLAB系统路径的一部分。就这样:

    a= imread('cameraman.tif');
    figure,imshow(a);
    ffta=fft2(a);
    fftshift1=fftshift(ffta);
    magnitude=abs(fftshift1);
    figure;
    imshow(log(1 + magnitude), []); %// NEW
    title('magnitude')
    

    这就是我得到的:

    enter image description here

    enter image description here


    正如您所看到的,幅度显示得更好。此外,由于fftshift,DC系数位于频谱的中间。


    如果要将其应用于彩色图像,fft2仍应有效。它将自己将2D fft应用于每个颜色平面。但是,如果您希望这样做,您不仅需要进行log转换,而且还需要分别对每个平面进行标准化。你必须这样做,因为如果我们尝试执行之前做过的imshow命令,它会将其标准化,以便将彩色图像光谱中的最大值标准化为1。将不可避免地产生我们之前谈到过的同样小点效应。

    让我们尝试一下内置于MATLAB的彩色图像:onion.png。我们将使用您在上面使用的相同代码,但我们需要一个额外的步骤来自行规范化每个颜色平面。就这样:

    a = imread('onion.png');
    figure,imshow(a);
    ffta=fft2(a);
    fftshift1=fftshift(ffta);
    magnitude=abs(fftshift1);
    logMag = log(1 + magnitude); %// New
    for c = 1 : size(a,3); %// New - normalize each plane
        logMag(:,:,c) = mat2gray(logMag(:,:,c));
    end
    figure; imshow(logMag); title('magnitude');
    

    请注意,我必须遍历每个颜色平面并使用mat2gray将每个平面标准化为[0,1]。另外,我必须创建一个名为logMag的新变量,因为我必须单独修改每个颜色平面,而且您无法通过单个imshow调用来执行此操作。

    有了这个,这些是我得到的结果:

    enter image description here

    enter image description here

    与此光谱的不同之处在于我们将FFT分别应用于每个色彩平面,因此您会看到一大堆色彩飞溅,因为对于此图像中的每个位置,我们都可视化红色,绿色和蓝色通道的组件的线性组合。对于每个位置,我们在每个颜色平面的[0,1]之间都有一个值,这些颜色平面的组合会在此位置为您提供颜色。您可以说较暗的颜色适用于至少一个颜色通道具有相对较低幅度的位置,而较亮的位置对于至少一个颜色通道具有相对较高的幅度。

    希望这有帮助!

答案 1 :(得分:0)

无法确定您的" lena.png"的版本,但如果它是彩色RGB图片,则需要先将其转换为灰度,或者至少选择哪个你要检查的RGB平面。

即,以下适用于http://optipng.sourceforge.net/pngtech/img/lena.png(颜色png):

clear; close all;

a  = imread('lena','png');
ag = rgb2gray(a);
ag = im2double(ag);

figure(1);
imshow(ag);

F = fftshift( fft2(ag) );  % also try fft2(ag, N, N) where N < image size. Say N=128.
magnitude=abs(F);

figure(2);
imshow(magnitude);