问题描述
首先,请参阅
到以下
然而,我正在努力想出一种规范化x和y的方法2D FFT图的轴值(图中的图像可以在本文第一句的上面给出的链接上找到。)
有没有人有线索至于我应该如何做到这一点?
我的代码的工作部分的片段是: -
明确;
deg_speed = 15.35; %度视角/秒
max_speed = deg_speed / 5.15;以帧为单位转换所需的deg_speed%
nr_of_dots = 10; %点数
sin_cycle_dur = 80;完成正弦波所需的帧数(沿Nt)%。
sineTOTAL = 0;
Nx = 160; %沿x轴框架。 1帧= 0.1 dva
Nt = 200;沿y-asis的%帧数。 1帧= 10ms
start_dot_pos = round(rand(1,nr_of_dots)。* Nx); %spawn的随机起始位置
dot_pos = zeros(Nt,nr_of_dots); %初始化2D刺激数组
dot_pos(1,:) = start_dot_pos; %使用点的起始位置填充第一行2D数组
dot_pos_sim = zeros(Nt,nr_of_dots); %Setup模拟数组,因此最终的dot_pos可以缩放为表示外部条件的速度
dot_pos_sim(1,:) = start_dot_pos; %使用点的起始位置填充第一行2D数组
a = 2:Nt
sine_speed = max_speed。* sin((a-1)/ sin_cycle_dur * 2 * pi ); %正弦公式
sineTOTAL = sineTOTAL + abs(sine_speed); %从正弦公式中添加所有正弦生成的值以获得平均值计算的总计
dot_pos_sim(a,:) = dot_pos_sim(a-1,:) + max_speed。* sin((a-1)/ sin_cycle_dur * 2 * PI); %正弦模拟矩阵(缩放前)
结束
%暂时忽略此for循环。稍后需要将模拟的
%数组标准化为其他条件下的平均速度。 b = 1的
:Nt
dot_pos(b,:) = dot_pos_sim(b,:);
结束
dot_pos = round(dot_pos); %帧是整数,因此所有浮点值都需要向上舍入。
dot_pos = mod(dot_pos,Nx)+1; %将超出边缘的点包裹到图的另一侧
%对于所有填充点的槽,将值设置为0到1.
表示c = 1 :Nt
stim(c,dot_pos(c,:))= 1;
end
figure(1)
x = linspace(0,16,5);
y = linspace(0,2,10);
imagesc(x,y,stim);
xlabel('degrees');
ylabel('秒');
colormap('grey');
X = abs(fft2(刺激));
X = fftshift(X); %规范化数据
X = log(1 + X);
figure(2)
imagesc(X);
colormap('grey');
我一直在努力寻找指南并在线帮助但到目前为止无济于事。任何帮助将不胜感激!
每当我不确定轴和缩放时,我会回到基础:复指数(一个复正弦曲线,其中real = cos和imaginary = sin)。
我知道的一维FFT(j * 2) * pi * f * t)
,对于时间样本向量 t
(以秒为单位)和频率 f
(以Hz为单位)将在 f
处达到峰值,只要 fmin< f< fmax
,其中 fmax = 1 / diff(t(1:2))/ 2
和 fmin = -1.0 * fmax
,峰值的值 1.0 。
完全相同的情况适用于2D情况。频率(fx,fy)
的二维复数指数将在 fx
和 fy达到峰值
在各自的轴上,峰值将 1.0 。
这是一个完整的Matlab示例获得这个已知结果的细节和约定。它模拟2D复指数,x频率为2 Hz,y频率为-3 Hz,矩形2D网格。然后它在零填充后进行FFT。
clearvars
x = linspace(-2,2 ,100); %秒
y = linspace(-3,3,200); %秒
xFreq = 2; %Hz
yFreq = -3; %Hz
im = exp(2j * pi * y(:) * yFreq)* exp(2j * pi * x(:)'* xFreq);
figure; imagesc(x,y,real(im))
xlabel('x(seconds)'); ylabel('y(秒)');
title('time-domain data(real)')
colorbar; colormap(flipud(灰色))
Nfft = 4 * 2. ^ nextpow2(size(im));
imF = fftshift(fft2(im,Nfft(1),Nfft(2)))/ numel(im);
fx =([0:Nfft(2) - 1] / Nfft(2) - 0.5)/ diff(x(1:2));
fy =([0:Nfft(1) - 1] / Nfft(1) - 0.5)/ diff(y(1:2));
数字; imagesc(fx,fy,abs(imF));
colorbar; colormap(flipud(灰色))
xlabel('f_x(Hz)'); ylabel('f_y(Hz)')
title('频域数据(abs)')
grid; axis xy
这是输入的时域数据:
确认您看到两个峰 - 峰值周期y维度中的x维度和三个周期 - 如果你研究图的左下边缘,很容易看到这些。
这是2D FFT,适当移位(使用 fftshift
),轴正确缩放(参见 fx
和 fy
),峰值正确缩放(请参阅如何将 fft2
的输出除以 numel(im)
)。
确认峰值为(2,-3)Hz,对应 [fx,fy]
,并且t帽子峰值的值几乎为1.0(由于量化网格,它略小一些)。
所以,我做了三件事来完成所有这些工作:
-
fftshift
fft2 $ c的输出$ c>,
- 生成
fx
和fy
正确匹配fftshift
, - 按元素数量缩放
fft2
的输出在零填充之前在上运行。
希望你可以将这个完整的例子扩展到你自己的情况。
First, refer to How to plot temporal frequency as a function of spatial frequency from a MATLAB FFT2 output of a time-space image? for a bit more of a background to this question.
Assuming in the case of this sample signal:-
n = [0:1024];
signal = sin(2*pi*n/10) + sin(2*pi*n/20) + sin(2*pi*n/30);
N = 2048; %At least twice of the n value
X = abs(fft(signal,N));
X = fftshift(X); %normalise data
F = [-N/2:N/2-1]/N; %normalise data - shift it to the correct frequency
plot(F,X);
The variable F range here is what sorts out the normalisation of the x-axis from
to the following
However, I'm struggling to figure out a way to normalise the x and y-axis values for a 2D FFT plot (The image for the plots are available on the above given link at the first sentence of this post.)
Does anyone have a clue as to how I should go about doing this?
A snippet of a working portion of my codes are:-
clear;
deg_speed = 15.35; %degrees visual angle/sec
max_speed = deg_speed/5.15; %converting the required deg_speed in terms of frames
nr_of_dots = 10; %number of dots
sin_cycle_dur = 80; %number of frames (along Nt) required to complete a sin wave.
sineTOTAL = 0;
Nx = 160; % Frames along x-axis. 1 frame = 0.1 dva
Nt = 200; % Frames along y-asis. 1 frame = 10ms
start_dot_pos = round(rand(1,nr_of_dots) .* Nx); %spawn random starting positions of dots
dot_pos = zeros(Nt, nr_of_dots); %Initialise 2D stimulus array
dot_pos(1,:) = start_dot_pos; %Fill up first line of 2D array with the starting position of dots
dot_pos_sim = zeros(Nt, nr_of_dots); %Setup simulated array so the final dot_pos can be scaled to mean speed of outher condition
dot_pos_sim(1,:) = start_dot_pos; %Fill up first line of 2D array with the starting position of dots
for a = 2:Nt
sine_speed = max_speed .* sin((a-1) / sin_cycle_dur *2*pi); %Sine formula
sineTOTAL = sineTOTAL + abs(sine_speed); %Add all sine generated values from Sine formula to get an overall total for mean calculation
dot_pos_sim(a,:) = dot_pos_sim(a-1,:) + max_speed .* sin((a-1) / sin_cycle_dur *2*pi); %Sine simulated matrix (before scaling)
end
%Ignore this for loop for now. This is later required for normalising simulated
%array to the mean speed across other conditions.
for b = 1:Nt
dot_pos(b,:) = dot_pos_sim(b,:);
end
dot_pos = round(dot_pos); %Frames are in integers, therefore all float values needed to be rounded up.
dot_pos = mod(dot_pos,Nx)+1; %Wrap the dots the go beyond the edges to the other side of the plot
%For all of the slots filled with dots, set the value from 0 to 1.
for c = 1:Nt
stim(c,dot_pos(c,:)) = 1;
end
figure (1)
x=linspace(0,16,5);
y=linspace(0,2,10);
imagesc(x,y,stim);
xlabel('degrees');
ylabel('seconds');
colormap('gray');
X = abs(fft2(stim));
X = fftshift(X); %normalise data
X = log(1+X);
figure (2)
imagesc(X);
colormap('gray');
I have been trying to find guides and help online but to no avail so far. Any help would be greatly appreciated!
Whenever I'm not sure about axes and scalings, I go back to basics: the complex exponential (a complex sinusoid, with real=cos and imaginary=sin).
I know that the 1D FFT of exp(j * 2 * pi * f * t)
, for a vector of time samples t
(in seconds) and a frequency f
(in Hz) will have a peak at f
, as long as fmin < f < fmax
, where fmax = 1 / diff(t(1:2)) / 2
and fmin = -1.0 * fmax
, and that the peak will have value 1.0.
The exact same thing applies in the 2D case. A 2D complex exponential with frequency (fx, fy)
will have peak at fx
and fy
in the respective axes, and the peak value will be 1.0.
Here's a complete Matlab example that works through the details and conventions to get this known result. It simulates a 2D complex exponential with x-frequency at 2 Hz and y-frequency at -3 Hz over a rectangular 2D grid. Then it takes the FFT after zero-padding.
clearvars
x = linspace(-2, 2, 100); % seconds
y = linspace(-3, 3, 200); % seconds
xFreq = 2; % Hz
yFreq = -3; % Hz
im = exp(2j * pi * y(:) * yFreq) * exp(2j * pi * x(:)' * xFreq);
figure;imagesc(x, y, real(im))
xlabel('x (seconds)'); ylabel('y (seconds)');
title('time-domain data (real)')
colorbar; colormap(flipud(gray))
Nfft = 4 * 2 .^ nextpow2(size(im));
imF = fftshift(fft2(im, Nfft(1), Nfft(2))) / numel(im);
fx = ([0 : Nfft(2) - 1] / Nfft(2) - 0.5) / diff(x(1:2));
fy = ([0 : Nfft(1) - 1] / Nfft(1) - 0.5) / diff(y(1:2));
figure; imagesc(fx, fy, abs(imF));
colorbar; colormap(flipud(gray))
xlabel('f_x (Hz)'); ylabel('f_y (Hz)')
title('Frequency-domain data (abs)')
grid; axis xy
Here's the input time-domain data:
Confirm that you see two peak-to-peak cycles in the x dimension and three cycles in the y-dimension—it's easy to see these if you study the bottom and left edges of the figure.
Here's the 2D FFT, appropriately shifted (with fftshift
), with axes scaled correctly (see fx
and fy
), and peak scaled correctly (see how I divide the output of fft2
with numel(im)
).
Confirm that the peak is at (2, -3) Hz corresponding to [fx, fy]
, and that the value of the peak is almost 1.0 (it's a little smaller because of of the quantized grid).
So, there’s three things I did to make all this work:
fftshift
the output offft2
,- generate
fx
andfy
correctly to match thefftshift
, and - scale the output of
fft2
by the number of elements it operates on before zero-padding.
Hopefully you can extend this complete example to your own case.
这篇关于如何将2D FFT图标准化为正确的频率(Matlab)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!