我试图实现的是离散傅里叶变换。
利用变换的可分离性(实际上是指数函数) 我们可以把它写成两个一维DFT的乘法。然后,我们可以计算出变换的行(下面的矩阵wM)和列(下面的矩阵wN)的指数项。然后,在求和过程中,我们可以将它们相乘为 "F = wM * original_matrix * wN"。
这是我写的代码。
f = imread('cameraman.tif');
[M, N, ~] = size(f);
wM = zeros(M, M);
wN = zeros(N, N);
for u = 0 : (M - 1)
for x = 0 : (M - 1)
wM(u+1, x+1) = exp(-2 * pi * 1i / M * x * u);
end
end
for v = 0 : (N - 1)
for y = 0 : (N - 1)
wN(y+1, v+1) = exp(-2 * pi * 1i / N * y * v);
end
end
F = wM * im2double(f) * wN;
首先,我不想使用两个循环,分别是MxM和NxN次运行。如果我使用一个巨大的矩阵(或图像),这将是一个问题。有什么办法可以使这段代码更快(例如消除循环)?
第二件事是显示傅里叶变换的结果。我使用下面的代码来显示变换结果。
% // "log" method
fl = log(1 + abs(F));
fm = max(fl(:));
imshow(im2uint8(fl / fm))
和...
% // "abs" method
fa = abs(F);
fm = max(fa(:));
imshow(fa / fm)
我用 "腹肌 "法时,只看到黑色的身影,其他什么都看不到。你认为 "abs "方法有什么问题?
最后,当我把自己函数的变换结果与MATLAB的fft2()函数进行比较时,我的变换结果比MATLAB的变换结果显示得更黑。我到底缺了什么?实现错误?
我自己函数的变换结果。
MATLAB fft2()函数的变换结果。
我很高兴你解决了你的问题,但不幸的是你的答案并不完全正确。的确,它做的工作,但正如我所评论的。im2double
会将所有的东西归一,因此会显示出你所拥有的缩放结果。你想要的是(如果你追求的是性能),而不是做什么 im2double
然后再乘以255,但直接投向了 double()
.
你可以通过使用 meshgrid
.比如说:
M = 1024;
tic
[ mX, mY ] = meshgrid( 0 : M - 1, 0 : M - 1 );
wM1 = exp( -2 * pi * 1i / M .* mX .* mY );
toc
tic
for u = 0 : (M - 1)
for x = 0 : (M - 1)
wM2( u + 1, x + 1 ) = exp( -2 * pi * 1i / M * x * u );
end
end
toc
all( wM1( : ) == wM2( : ) )
我系统的计时是:经过时间是0. 130923秒,经过时间是0. 493163秒。