简体   繁体   English

我需要在调用 fft 或 ifft 之前调用 fftshift 吗?

[英]Do I need to call fftshift before calling fft or ifft?

In the book "Computational Fourier Optics, A Matlab Tutorial" by David Voelz, it is written that a call to fftshift is needed before a call to fft or ifft , but in the MATLAB documentation of fftshift it's only written that this command在 David Voelz 的“计算傅立叶光学,Matlab 教程”一书中,写道在调用fftifft之前需要调用fftshift ,但在fftshift的 MATLAB 文档中只写了这个命令

rearranges the outputs of fft , fft2 , and fftn by moving the zero-frequency component to the center of the array.通过将零频率分量移动到数组的中心来重新排列fftfft2fftn的输出。

There is no mention in documentation that this command should be called before the call to fft , and I saw some examples that call fft without a call to fftshift beforehand.文档中没有提到应在调用fft之前调用此命令,而且我看到了一些调用fft而不事先调用fftshift的示例。

My question is: Whether or not fftshift needed to be called before a call to fft or ifft ?我的问题是:在调用fftifft之前是否需要调用fftshift

If fftshift doesn't need to be called before a call to fft , and only after a call to fft , then when should we use (if at all) the command ifftshift with relation to a calculation of the fft of a data set?如果fftshift不需要在调用fft之前调用,而仅在调用fft之后调用,那么我们应该什么时候使用(如果有的话)命令ifftshift来计算数据集的fft

The matlab fft only computes half of the frequency spectrum (positive frequencies and the zero frequency if your number of samples is odd) in order to save computation time.为了节省计算时间,matlab fft仅计算频谱的一半(如果您的样本数为奇数,则为正频率和零频率)。 Then, the second half of the frequency spectrum (which is the complex conjugate of the first half) is just added at the end of this vector.然后,频谱的后半部分(即前半部分的复共轭)刚好添加到该向量的末尾。

So what you get after a fft is the following vector:所以你在fft之后得到的是以下向量:

 0 1 2 3 ... Fs/2   -Fs/2 ... -3 -2 -1
<----------------> <------------------>
  positive freq        negative freq

where Fs is the frequency sample.其中Fs是频率样本。

Now, what fftshift does is just shifting the negative frequency bins (2nd part of the frequency spectrum) at the beginning of your vector so that you can display a nice frequency spectrum starting at -Fs/2 and ending at +Fs/2 .现在, fftshift所做的只是在向量的开头移动负频率箱(频谱的第二部分),以便您可以显示从-Fs/2开始到+Fs/2结束的不错的频谱。 The shifted vector becomes:移位向量变为:

 -Fs/2 ... -3 -2 -1   0 1 2 3 ... Fs/2
<------------------> <---------------->
    negative freq      positive freq

So, to answer your question, no you don't need to use fftshift after or before a call to fft or ifft .因此,要回答您的问题,您不需要在调用fftifft之后或之前使用fftshift But if you used a fftshift on your vector, you should undo it by applying an ifftshift or fftshift .但是,如果您在向量上使用了fftshift ,则应该通过应用ifftshiftfftshift来撤消它。 (I think both calls are equivalent.) (我认为这两个调用是等效的。)

If you read onwards in the documentation on fftshift : "It is useful for visualizing a Fourier transform with the zero-frequency component in the middle of the spectrum."如果您继续阅读有关fftshift的文档:“这对于可视化具有频谱中间零频率分量的傅立叶变换很有用。”

The shift is not necessary to perform the fft, but it is handy to visualise the Fourier transform.执行 fft 不需要移位,但可以方便地可视化傅立叶变换。 Whether to use fftshift or not is thus dependent upon whether you want to visualise your transform or not.因此,是否使用fftshift取决于您是否想要可视化您的转换。

Note that ifftshift is different than fftshift because it shifts the negative back to the positive.请注意, ifftshiftfftshift不同,因为它将负数移回正数。 Assume a simple 3 bin unit impulse in frequency domain before fftshift假设在fftshift之前频域中有一个简单的 3 bin 单位脉冲

[0, exp(-jw1), exp(-(jw1-pi)=exp(-jw1+pi)];

fftshift gives fftshift给出

[exp(-jw1+pi)], 0, exp(-jw1)];

you can see the discontinuity in phase.你可以看到相位的不连续性。 If you perform ifftshift , negative freq is shifted back to positive:如果您执行ifftshift ,负频率将移回正值:

[0, exp(-jw1), exp(-jw1+pi)];

whereas, fftshift again gives:fftshift再次给出:

[exp(-jw1), exp(-jw1+pi), 0];

one can see the phase monotonicity is not the same, (aka, fftshift - ifftshift case gives [decrease, increase] and fftshift - fftshift case gives [increase, decrease] in phase).可以看到相位单调性是不一样的,(又名, fftshift - ifftshift情况给出 [减少,增加] 和fftshift - fftshift情况给出 [增加,减少] 相位)。

The simple answer is call to fftshift not needed before a call to fft.简单的答案是在调用 fft 之前不需要调用fftshift fftshift does not influence the calculation of Fast fourier transform. fftshift不影响快速傅立叶变换的计算。 fftshift rearranges values inside a matrix. fftshift 重新排列矩阵内的值。 For eg:例如:

cameraman = imread('cameraman.tif');
fftshifted_cameraman = fftshift(cameraman);
subplot(1,2,1); imshow(cameraman); title('Cameraman');
subplot(1,2,2); imshow(fftshifted_cameraman); title('FFTShifted Cameraman');

Given the title of the book you are studying, I assume you are working with images.鉴于您正在学习的书名,我假设您正在处理图像。 Then the proper way is to call both fftshift and ifftshift before and after you call [i]fft.那么正确的方法是在调用 [i]fft 之前和之后调用 fftshift 和 ifftshift。

Your code should look like你的代码应该看起来像

spectrum = fftshift(fft2(ifftshift(myimage))

It is quite the same when applying the inverse Fourier transform应用傅里叶逆变换时完全相同

myimage = fftshift(ifft2(ifftshift(spectrum))

It depends on what you are going to do with the transformed data.这取决于您将如何处理转换后的数据。 If you don't perform an fftshift before transforming, the fft result will have every other value multiplied by -1.如果您在转换前不执行 fftshift,则 fft 结果将每隔一个值乘以 -1。 This doesn't matter if you plan to view the magnitude or magnitude squared of the result.如果您打算查看结果的幅度或幅度平方,这无关紧要。 However, if you plan to compare adjacent spectral values and phase is important, you'll need to apply fftshift before transforming to avoid the alternating sign.但是,如果您计划比较相邻的光谱值并且相位很重要,则需要在转换之前应用 fftshift 以避免交替符号。

Here is a MATLAB script I use to test basic sound analysis functions of MATLAB including fftshift() in displaying the output of fft() .这是一个 MATLAB 脚本,我用来测试 MATLAB 的基本声音分析功能,包括fftshift()在显示fft()的 output 时。

if ~exist('inputFile', 'var')
    inputFile = 'vibe.wav';
end

[inputBuffer, Fs] = audioread(inputFile);

fileSize = length(inputBuffer);

numSamples = 2.^(ceil(log2(fileSize))); % round up to nearest power of 2

x = zeros(numSamples, 1);                   % zero pad if necessary

x(1:fileSize) = inputBuffer(:,1);           % if multi-channel, use left channel only

clear inputBuffer;                          % free this memory
clear fileSize;

t = linspace(0, (numSamples-1)/Fs, numSamples)';
f = linspace(-Fs/2, Fs/2 - Fs/numSamples, numSamples)';

X = fft(x);

plot(t, x);
xlabel('time (seconds)');
ylabel('amplitude');
title(['time-domain plot of ' inputFile]);
sound(x, Fs);                                           % play the sound
pause;




% display both positive and negative frequency spectrum

plot(f, real(fftshift(X)));
xlabel('frequency (Hz)');
ylabel('real part');
title(['real part frequency-domain plot of ' inputFile]);
pause;

plot(f, imag(fftshift(X)));
xlabel('frequency (Hz)');
ylabel('imag part');
title(['imag part frequency-domain plot of ' inputFile]);
pause;

plot(f, abs(fftshift(X)));                              % linear amplitude by linear freq plot
xlabel('frequency (Hz)');
ylabel('amplitude');
title(['abs frequency-domain plot of ' inputFile]);
pause;

plot(f, 20*log10(abs(fftshift(X))+1.0e-10));            % dB by linear freq plot
xlabel('frequency (Hz)');
ylabel('amplitude (dB)');
title(['dB frequency-domain plot of ' inputFile]);
pause;





% display only positive frequency spectrum for log frequency scale

semilogx(f(numSamples/2+2:numSamples), 20*log10(abs(X(2:numSamples/2))));       % dB by log freq plot
xlabel('frequency (Hz), log scale');
ylabel('amplitude (dB)');
title(['dB vs. log freq, frequency-domain plot of ' inputFile]);
pause;

semilogx(f(numSamples/2+2:numSamples), (180/pi)*angle(X(2:numSamples/2)));      % phase by log freq plot
xlabel('frequency (Hz), log scale');
ylabel('phase (degrees)');
title(['phase vs. log freq, frequency-domain plot of ' inputFile]);
pause;

%
%   this is an alternate method of unwrapping phase
%
%   phase = cumsum([angle(X(1)); angle( X(2:numSamples/2) ./ X(1:numSamples/2-1) ) ]);  
%   semilogx(f(numSamples/2+2:numSamples), phase(2:numSamples/2));                  % unwrapped phase by log freq plot
%

semilogx(f(numSamples/2+2:numSamples), unwrap(angle(X(2:numSamples/2))));       % unwrapped phase by log freq plot
xlabel('frequency (Hz), log scale');
ylabel('unwrapped phase (radians)');
title(['unwrapped phase vs. log freq, frequency-domain plot of ' inputFile]);

If you were windowing segments of audio and passing them to the FFT, then you should use fftshift() on the input to the FFT to define the center of the windowed segment as the t=0 point.如果您对音频片段进行窗口化并将它们传递给 FFT,那么您应该在 FFT 的输入上使用fftshift()来将窗口化片段的中心定义为 t=0 点。

[x_input, Fs] = audioread('vibe.wav');     % load time-domain input
N = 2*floor(length(x_input)/2);            % make sure N is even
x = x_input(1:N);

t = linspace(-N/2, N/2-1, N);              % values of time in units of samples
omega = linspace(-pi, pi*(1-2/N), N);      % values of (normalized) angular frequency

X = fftshift( fft( fftshift( x.*hamming(length(x)) ) ) );

[X_max k_max] = max( abs(X) );

figure(1);
plot(t, x, 'g');

figure(2);
plot(omega, abs(X), 'b');
hold on;
plot(omega(k_max), X_max, 'or');
hold off;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM