如何将2D FFT图标准化为正确的频率(Matlab)?

时间:2016-09-29 03:32:05

标签: matlab image-processing 2d fft

首先,请参阅How to plot temporal frequency as a function of spatial frequency from a MATLAB FFT2 output of a time-space image?了解此问题的更多背景信息。

假设在此样本信号的情况下: -

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);

这里的变量F range是从

中对x轴的归一化进行分类的

enter image description here

以下

enter image description here

然而,我正在努力想出一种方法来标准化2D FFT图的x和y轴值(图的图像可以在本文第一句的上面给定的链接上获得。)

有没有人知道我应该怎么做呢?

我的代码的工作部分的片段是: -

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');

我一直在努力寻找指南并在线帮助但到目前为止无济于事。任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:1)

我认为这是一个非常简单的答案 - 您看起来正在寻找的是沿X轴和Y轴的刻度,表示标准化频率。当您使用fftshift时,DC项将位于图的中间,因此您的比例应该从-0.5到0.5。使用imagesc(x,y,C)命令可以轻松完成此操作,而不仅仅是当前正在执行的imagesc(C)。 (您使用X,但Matlab帮助使用C代表色彩图。)

将您的第二行更改为:

imagesc([-0.5,0.5],[-0.5,0.5],X);

它会给你我认为你要求的东西。

答案 1 :(得分:1)

每当我对轴和缩放不确定时,我就会回到基础:复指数(一个复杂的正弦曲线,其中有实数= cos和虚数= sin)。

我知道service的1D FFT,对于时间样本exp(j * 2 * pi * f * t)(以秒为单位)和频率t(以Hz为单位)的向量,将在{{ 1}},只要fffmin < f < fmax,并且峰值的值 1.0

完全相同的事情适用于2D情况。具有频率fmax = 1 / diff(t(1:2)) / 2的2D复指数将在各个轴的fmin = -1.0 * fmax(fx, fy)处具有峰值,并且峰值将 1.0

这是一个完整的Matlab示例,它通过详细信息和约定来获得此已知结果。它模拟2D复指数,x频率为2 Hz,y频率为-3 Hz,矩形2D网格。然后在零填充后进行FFT。

fx

这是输入的时域数据:

Time-domain data

确认您在x维度中看到两个峰峰值周期,并且在y维度中看到三个周期 - 它很容易看到这些如果你研究图的左下边缘。

这里是2D FFT,适当移位(使用fy),轴正确缩放(请参阅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 fftshift),并且峰值缩放正确(请参阅我的方法)将fx的输出除以fy)。

Frequency-domain data

确认峰值位于对应于fft2的(2,-3)Hz处,并且峰值几乎为1.0(由于量化网格,它略小)。

所以,我做了三件事来完成所有这些工作:

  • numel(im) [fx, fy]的输出,
  • 正确生成fftshiftfft2以匹配fx
  • fy的输出按其在零填充之前在上操作的元素数量进行缩放。

希望您可以将此完整示例扩展到您自己的案例中。