2

我正在尝试在 matlab 中运行一个程序来获取灰度图像的直接和逆 DFT,但在应用逆向后我无法恢复原始图像。我得到复数作为我的逆输出。就像我正在丢失信息。对此有什么想法吗?这是我的代码:

%2D discrete Fourier transform
%Image Dimension

M=3;
N=3;
f=zeros(M,N);
f(2,1:3)=1;
f(3,1:3)=0.5;
f(1,2)=0.5;
f(3,2)=1;
f(2,2)=0;

figure;imshow(f,[0 1],'InitialMagnification','fit')


%Direct transform


for u=0:1:M-1
   for v=0:1:N-1
       for x=1:1:M
           for y=1:1:N

             F(u+1,v+1)=f(x,y)*exp(-2*pi*(1i)*((u*(x-1)/M)+(v*(y-1)/N)));


            end
        end
    end
end


Fab=abs(F);

figure;imshow(Fab,[0 1],'InitialMagnification','fit')



%Inverse Transform

for x=0:1:M-1
    for y=0:1:N-1
       for u=1:1:M
            for v=1:1:N

                z(x+1,y+1)=(1/M*N)*F(u,v)*exp(2*pi*(1i)*(((u-1)*x/M)+((v-1)*y/N)));


            end
        end
    end
end

figure;imshow(real(z),[0 1],'InitialMagnification','fit')
4

2 回答 2

1

您的代码有几个问题:

  1. 您没有正确应用 DFT(或 IDFT)的定义:您需要对原始变量求和以获得变换。请参阅此处的公式;注意总和。

  2. 在 IDFT 中,归一化常数应该是1/(M*N)(不是1/M*N)。

还要注意,通过矢量化可以使代码更加紧凑,避免循环;或仅使用fft2andifft2功能。我假设您想手动计算它并“低级”验证结果。

经过两次更正的代码如下。修改用注释标记。

M=3;
N=3;
f=zeros(M,N);
f(2,1:3)=1;
f(3,1:3)=0.5;
f(1,2)=0.5;
f(3,2)=1;
f(2,2)=0;

figure;imshow(f,[0 1],'InitialMagnification','fit')

%Direct transform

F = zeros(M,N); % initiallize to 0
for u=0:1:M-1
   for v=0:1:N-1
       for x=1:1:M
           for y=1:1:N
               F(u+1,v+1) = F(u+1,v+1) + ...
                   f(x,y)*exp(-2*pi*(1i)*((u*(x-1)/M)+(v*(y-1)/N))); % add term
            end
        end
    end
end

Fab=abs(F);
figure;imshow(Fab,[0 1],'InitialMagnification','fit')

%Inverse Transform

z = zeros(M,N);
for x=0:1:M-1
    for y=0:1:N-1
       for u=1:1:M
            for v=1:1:N
                z(x+1,y+1) = z(x+1,y+1) + (1/(M*N)) * ... % corrected scale factor
                    F(u,v)*exp(2*pi*(1i)*(((u-1)*x/M)+((v-1)*y/N))); % add term
            end
        end
    end
end

figure;imshow(real(z),[0 1],'InitialMagnification','fit')

现在原始图像和恢复图像仅相差很小的值,大约为eps,由于通常的浮点不准确:

>> f-z
ans =
   1.0e-15 *
  Columns 1 through 2
  0.180411241501588 + 0.666133814775094i -0.111022302462516 - 0.027755575615629i
  0.000000000000000 + 0.027755575615629i  0.277555756156289 + 0.212603775716506i
  0.000000000000000 - 0.194289029309402i  0.000000000000000 + 0.027755575615629i
  Column 3
 -0.194289029309402 - 0.027755575615629i
 -0.222044604925031 - 0.055511151231258i
  0.111022302462516 - 0.111022302462516i  
于 2020-02-27T23:34:52.033 回答
1

首先,最大的错误是您错误地计算了傅里叶变换。计算时F,您需要对 x 和 y 求和,而您没有这样做。以下是纠正方法:

F = zeros(M, N);

for u=0:1:M-1
   for v=0:1:N-1
       for x=1:1:M
           for y=1:1:N
             F(u+1,v+1)=F(u+1,v+1) + f(x,y)*exp(-2*pi*(1i)*((u*(x-1)/M)+(v*(y-1)/N)));
            end
        end
    end
end

其次,在逆变换中,您的包围不正确。应该1/(M*N)不是(1/M*N)


顺便说一句,以更多内存为代价,您可以通过不嵌套这么多循环来加快计算速度。即,在计算 FFT 时,请改为执行以下操作

x = (1:1:M)'; % x is a column vector
y = (1:1:N) ; % y is a row vector

for u = 0:1:M-1
    for v = 0:1:N-1
        F2(u+1,v+1) = sum(f .* exp(-2i * pi * (u*(x-1)/M + v*(y-1)/N)), 'all');
    end
end

要将这种方法发挥到极致,即根本不使用任何循环,您将执行以下操作(尽管不建议这样做,因为您会失去代码可读性并且内存成本会成倍增加)

x = (1:1:M)'; % x is in dimension 1
y = (1:1:N) ; % y is in dimension 2
u = permute(0:1:M-1, [1, 3, 2]); % x-freqs in dimension 3
v = permute(0:1:N-1, [1, 4, 3, 2]); % y-freqs in dimension 4
% sum the exponential terms in x and y, which are in dimensions 1 and 2. 
% If you are using r2018a or older, the below summation should be 
%    sum(sum(..., 1), 2) 
% instead of 
%    sum(..., [1,2])
F3 = sum(f .* exp(-2i * pi * (u.*(x-1)/M + v.*(y-1)/N)), [1, 2]); 
% The resulting array F3 is 1 x 1 x M x N, to make it M x N, simply shiftdim or squeeze
F3 = squeeze(F3);
于 2020-02-27T23:37:40.727 回答