- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我的问题类似于,但比 this post 更笼统,而且我认为在规范化方面存在错误,无论如何使用最新版本的 Matlab(2015)。我犹豫是否将其发布到 CodeReview SE 上,如果您认为更合适,请在评论中告诉我。
我要验证以下代码 使用 Matlab 的 fft
的傅立叶变换,因为我在网络上发现了相互矛盾的信息来源,包括在 Matlab 帮助本身中,并且我无法用某些此类“食谱”验证 Parseval 定理(包括来自 MathWorks 团队的 answers,见下文) ,尤其是那些为实际输入提取单边光谱的人。
例如,在提取正频率时,通常在网上发现的用于解释实值信号的对称谱的倍幅似乎是错误的(Parseval 定理失败),而似乎有必要使用Matlab 中的两个系数(我不知道为什么)。有些人似乎也直接对 DFT 系数进行归一化,如 Y = fft(X)/L
,但我认为这是令人困惑的,应该劝阻;振幅为defined由于复数 DFT 系数的模数除以信号长度,系数本身不应被除。一旦经过验证,我打算将此代码作为要点发布在 GitHub 上。
function [frq,amp,phi] = fourier_transform( time, vals )
% FOURIER_TRANSFORM computes the Fast Fourier Transform of a given time-series.
%
% [freq,amp,phi] = fourier_transform(time,vals)
%
% Inputs:
%
% time - Nx1 column vector of equally-spaced timepoints (if not, input will be resampled).
% vals - NxM matrix of real- or complex-valued observations at previous timepoints.
%
% Outputs:
%
% frq - column vector of frequencies in Hz
% amp - corresponding matrix of amplitudes for each frequency (row) and signal (column)
% phi - corresponding unwrapped phase for each frequency (row) and signal (column)
%
% Note:
% To compute the power from the output amplitude, you need to multiply by the number of timepoints:
% power = numel(time) * amp.^2;
%
% References:
% https://en.wikipedia.org/wiki/Discrete_Fourier_transform
% make sure input time-series is uniformly sampled
assert( iscolumn(time), 'Input time should be a column vector.' );
assert( ismatrix(vals) && size(vals,1) == numel(time), 'Input values should be a matrix with same number of rows than of timepoints.' );
if std(diff(time)) > 1e-6
warning('Input time-course does not appear to be uniformly sampled. Resampling before continuing.');
[vals,time] = resample(vals,time);
end
% sampling information
nt = numel(time);
dt = time(2)-time(1);
fs = 1/dt;
df = fs/nt;
% complex spectrum coefficients
coef = fft(vals);
% real input
if isreal(vals)
% extract one-sided spectrum (spectrum is symmetric)
nfft = floor( nt/2 + 1 ); % eg 8 -> 5, and 7 -> 4
coef = coef( 1:nfft, : );
frq = (0:nfft-1)*df;
% correct amplitude values to account for previous extraction
fac = sqrt(2);
amp = fac*abs(coef)/nt;
amp(1,:) = amp(1,:)/fac; % .. except for the DC component
if mod(nt,2) == 0
amp(end,:) = amp(end,:)/fac; % .. and for the Nyquist frequency (only if nt is even)
end
% complex input
else
% shift the spectrum to center frequencies around 0
coef = fftshift( coef );
frq = fftshift( (0:nt-1)*df );
amp = abs(coef)/nt;
end
% make sure frq is a column vector and compute phases
frq = frq(:);
phi = unwrap(angle(coef));
end
>> fs=1e3; t=transpose(0:1/fs:10); nt=numel(t); X=rand(nt,1);
>> [frq,amp,phi] = fourier_transform( t, X );
>> sum( abs(X).^2 ) - nt*sum( amp.^2 ) % Parseval's theorem
ans =
-2.7285e-11
>> Fs = 1000; % Sampling frequency
T = 1/Fs; % Sample time
L = 1000; % Length of signal
t = (0:L-1)*T; % Time vector
x = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
y = x + 2*randn(size(t)); % Sinusoids plus noise
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Y = fft(y,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
>> sum(abs(y).^2) - NFFT*sum(abs(Y).^2) % Parseval's theorem
ans =
-220.4804
Y = fft(y,NFFT)/L
.
>> Y = fft(y,NFFT);
Ya = abs(Y)/NFFT; % correctly normalised amplitudes
sum(abs(y).^2) - NFFT*sum(Ya.^2) % Parseval's theorem
>> Fs = 1000; % Sampling frequency
T = 1/Fs; % Sample time
L = 1000; % Length of signal
t = (0:L-1)*T; % Time vector
% Sum of a 50 Hz sinusoid and a 120 Hz sinusoid
x = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
y = x + 2*randn(size(t)); % Sinusoids plus noise
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Y = fft(y,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
NumUniquePts = ceil((NFFT+1)/2);
Y=Y(1:NumUniquePts);
MX=2*abs(Y);
MX(1)=MX(1)/2; % DC component
if ~rem(NFFT,2) % when NFFT is even, Y(1+Y/2) is the Nyquist frequency component of x, and needs to make sure it is unique.
MX(length(MX))=MX(length(MX))/2;
end
>> sum( abs(y).^2 ) - NFFT*sum( MX.^2 )
ans =
-5.3812e+03
Y = fft(y,NFFT)/L;
来自
Y = fft(y,NFFT)
,据说
MX=2*abs(Y);
来自
MX=2*abs(Y)/NFFT;
.但是这里出现了幅度加倍的问题;修正系数似乎是
sqrt(2)
而不是
2
.
>> Fs = 1000; % Sampling frequency
T = 1/Fs; % Sample time
L = 1000; % Length of signal
t = (0:L-1)*T; % Time vector
x = 0.7*sin(2*pi*Fs/8*t) + sin(2*pi*Fs/4*t);
NFFT = 2^nextpow2(L); % Next power of 2 from length of y
Y = fft(x,NFFT)/L;
f = Fs/2*linspace(0,1,NFFT/2+1);
>> sum( abs(x).^2 ) - NFFT*sum( abs(Y).^2 )
ans =
-36.1891
Y = fft(x,NFFT);
Ya = abs(Y)/NFFT;
sum( abs(x).^2 ) - NFFT*sum( abs(Ya).^2 )
最佳答案
TL; DR(摘要)
网上很难找到fft
的例子。与 Matlab 一起使用以正确归一化幅度/功率值(例如,可以使用 Parseval's theorem 进行验证)。如果您想比较不同长度的信号之间的光谱,这一点至关重要。实值信号还有一个额外的问题,因为在这种情况下,频谱通常仅针对正频率计算,因此需要缩放幅度或功率值以考虑频率折叠。 按照下面的帖子和答案,here is a gist我认为它可以正确且一致地为实值和复值输入调整系数。
带回家的消息是:
Y = fft(x)/L
); fft(x,nfft)
),则归一化器为 nfft
而不是 numel(x)
; 1/N
总和前面的因数。这在某种意义上是很自然的,因为在时间到频率方向上的移动可以看作是在具有不同频率的(正交)波的基础上的投影,而在频率到时间方向上的移动可以看作是加权叠加的波浪。 |Xk| / N
.同样,电源每波是|Xk|^2 / N
. Matlab 也使用归一化(好吧,FFTW 确实如此)。 N * amp_adjusted[k]^2 = N * (2*|Xk|/N)^2
不等于 2*|Xk|^2 / N
(这是 OP 中 2 的平方根的来源)。因此需要计算独立 来自 DFT 系数的幅度和功率值(另一个不缩放它们的好理由)。 Y = fft(x,NFFT)
哪里
NFFT
通常是 2 的幂,使用 FFTW 使计算更高效。
NFFT >= N
)是
x
在其末尾用 0 填充,直到达到 NFFT 时间点的长度。这意味着分解中的频率数发生了变化,因此应该相对于
NFFT
进行归一化。波分量,而不是原来的
N
时间点。
Y = fft(x,NFFT)/N
,但是
Y = fft(x,NFFT)/NFFT
- 另一个很好的理由来摆脱对复数系数进行归一化的习惯。
关于matlab - Matlab 傅里叶变换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35177274/
我正在尝试从底层叶进程写入命名管道并从顶层进程的管道读取。 为此,我首先在顶级进程中创建 FIFO,然后使用 for 循环派生更多进程。在 for 循环中,我正在检查叶子进程,如果它是叶子,我正在写入
我需要一个XPath表达式来验证XML列表元素是否只有某种类型的节点。 例: 我需要知道列表中是否只有图像。
我想从层次结构表中获取所有叶子及其根。叶子是最低层节点,根是最顶层节点。 给定一棵树: A --B --C --D E --F --G --H 叶子是节点:C, D根是:A、E 该表如下所
尝试从嵌套数组中删除相同的 sibling (叶子)/相同的数组。 例如 $data = [ 'test' => [ 'a' => [
我可以遍历目录并只打印文件夹/目录名称,但我想排除包含其他目录的目录的文件夹名称。出于某种原因,我称其为树结构中的“最终节点”,但我很可能是在自欺欺人,这不是第一次了。 =) 在审查其他答案列表时,也
我现在经常使用 Folium,在 Python 中拥有如此易于使用的东西真的很棒。但是他们的文档严重落后,我理解。所以我有2个问题。 我在尝试获得更多标记颜色时做错了什么?这是我尝试过的:map.si
我正在尝试使用 ape 包中的 plot.phylo 命令为 R 中系统发育类型图的边缘(线)添加颜色。这个例子是一个“粉丝”类型的图,虽然我希望这个方法与“系统图类型”或其他任何东西相同。 libr
我正在尝试呈现一个 JTree 叶以具有包含可编辑 JTextArea 的 JPanel,以便用户可以输入文本并能够在添加文本时向下滚动, 并且还使用包装器来限制文本的宽度,使其向下延伸以留出更多空间
这是要修改的正确 Linux 内核代码吗?我如何进行更改以模拟 CPUID 代码以及我需要更改哪个函数。谢谢 #include #include #include #include #incl
我是一名优秀的程序员,十分优秀!