什么是numpy.fft.rfft和numpy.fft.irfft以及在MATLAB中的等效代码

5

我将一段Python代码转换为MATLAB,其中一段代码使用了numpy rfft。在numpy的文档中,它指出输入是实数。

计算实数输入的一维离散傅里叶变换。

因此,在MATLAB中,我使用了abs函数,但结果不同。

Python代码:

ffta = np.fft.rfft(a) 

MATLAB 代码

ffta = abs(fft(a));

我理解有误了吗?

1个回答

11
在numpy中,实数FFT利用了实值函数的傅里叶变换是所谓的“斜对称”的事实,即频率为k的值是频率为N-k的值的复共轭,其中k=1..N-1(正确的术语是厄米)。因此,rfft仅返回与非正频率对应的结果部分。
对于大小为N的输入,rfft函数返回与频率在或低于N/2处的FFT输出相对应的部分。因此,如果N是偶数(从0N/2的所有频率),rfft的输出大小为N/2+1,如果N是奇数(从0(N-1)/2的所有频率),rfft的输出大小为(N+1)/2。请注意,函数floor(n/2+1)对于偶数和奇数输入大小都返回正确的输出大小。
因此,要在matlab中复现rfft
function rfft = rfft(a)
     ffta = fft(a);
     rfft = ffta(1:(floor(length(ffta)/2)+1));
end

例如
a = [1,1,1,1,-1,-1,-1,-1];
rffta = rfft(a)

会产生
rffta =

 Columns 1 through 3:

   0.00000 + 0.00000i   2.00000 - 4.82843i   0.00000 + 0.00000i   

 Columns 4 through 5:

   2.00000 - 0.82843i   0.00000 + 0.00000i
   

现在将其与Python进行比较。
>>> np.fft.rfft(a)
array([ 0.+0.j        ,  2.-4.82842712j,  0.-0.j        ,  
        2.-0.82842712j,  0.+0.j        ])

重现irfft

要重现irfft的基本功能,您需要从rfft的输出中恢复丢失的频率。如果所需的输出长度是偶数,则输出长度可以根据输入长度计算为2 (m - 1)。否则,它应该是2 (m - 1) + 1

以下代码将起作用。

function out = irfft(x, even)
    if nargin == 1
        even = true;
    end
    % `n`: the output length
    % `s`: the variable that will hold the index of the highest
    %      frequency below N/2, s = floor((n+1)/2)
    N = numel(x);  % function assumes 1D input
    if even
        n = 2 * (N - 1);
        s = N - 1;
    else
        n = 2 * (N - 1) + 1;
        s = N;
    end
    outf = zeros(1, n);
    outf(1:N) = x;
    outf(N+1:n) = conj(x(s:-1:2));
    out = ifft(outf);
end

现在你应该有了
>> irfft(rfft(a))
ans =

   1.00000   1.00000   1.00000   1.00000  -1.00000  -1.00000  -1.00000  -1.00000

而且
abs( irfft(rfft(a)) - a ) < 1e-15

对于奇数长度的输出,您将获得
>> irfft(rfft(a(1:7)),even=false)
ans =

   1.0000   1.0000   1.0000   1.0000  -1.0000  -1.0000  -1.0000

谢谢,现在它可以工作了。我还想再现irfft,我使用了2 *(m-1),但它显示索引超出矩阵维度。我应该把它放在一个新主题上吗? function irfft = irfft(a) iffta = ifft(a); irfft = iffta(1:(2*(length(iffta)-1))); end - iHateUni
“-a”的目的是什么?“<1e-15”又是什么意思? - iHateUni
如果没有数值精度问题,那么 @iHateUni irfft(rfft(a)) 应该等于 a。因此,abs(x-y) < 1e-15 意味着使用双精度浮点数时,x 几乎等于 y,只是存在一些累积的舍入误差。 - Dima Chubarov
1
Dmitri,这段代码对于奇数长度的输入不能正常工作,你能修改一下吗? - Ahmed Fasih
对于rfft,它必须是rfft = ffta(1:(((length(ffta)+1)/2)); :) - iHateUni
@iHateUni 说得好。请注意,对于偶数而言,floor(n/2)+1 等于 n/2+1,对于奇数而言,等于 (n+1)/2,因此我们上面的代码应该可以直接使用,无需更改。 - Dima Chubarov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接