2016-09-29 48 views
1

まず、この質問の背景の詳細​​については、How to plot temporal frequency as a function of spatial frequency from a MATLAB FFT2 output of a time-space image?を参照してください。2D FFTプロットを正しい周波数(Matlab)に正規化する方法は?

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の範囲は、以下に

enter image description here

からx軸の正規化をソートするものである: - このサンプル信号の場合に仮定

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

私はこれまでのガイドを見つけて、オンライン助けようとしたが無駄にされています。どんな助けでも大歓迎です!

答えて

1

軸とスケールについてわからないときは、複素指数関数(複素正弦関数、実= cosと虚数= sin)を基本に戻します。

Iは時間(秒)サンプルtのベクトルと周波数(Hz)fため限りfmin < f < fmaxfmax = 1/diff(t(1:2))/2fmin = -1.0 * fmaxとして、fにピークを有するであろう、exp(j * 2 * pi * f * t)の1D FFTことを知っている、およびピークは値1.0を持つことになります。

全く同じことが2Dの場合に適用されます。周波数が(fx, fy)の2次元複素指数は、それぞれの軸にfxfyにピークを持ち、ピーク値は1.0となります。

ここでは、この既知の結果を得るための細部と慣習で動作する完全なMatlabの例を示します。これは、矩形の2Dグリッド上で、2Hzのx周波数と-3Hzのy周波数を持つ指数関数的な2次元複素数をシミュレートします。次に、ゼロパディングの後にFFTを実行します。ここで

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 

は、入力時間領域のデータです:あなたはy軸にx次元でピーク・ツー・ピーク周期とサイクルを参照してください

Time-domain data

確認ディメンション - 図の下部と左端を調べると、これらを確認するのは簡単です。

ここ2D FFTは、適切に正しくスケーリング正しくスケーリング軸(fxfyを参照)、ピーク(Iはnumel(im)fft2の出力を分割する方法を参照)、(fftshiftで)シフトです。ピークは[fx, fy]に対応する(2、-3)Hzであり、ピークの値はほぼ1.0であることを

Frequency-domain data

確認は、(それがあるため、量子化グリッドの少し小さいです)。

だから、私は三つのことはすべて、この作業を行うことがあります:

  • fftshiftfft2の出力、
  • fxと正しくfyfftshiftに一致するように生成し、
  • スケール出力のfft2の数で除算すると、ゼロパディングの前にに作用します。

この完全な例を独自のケースに拡張することをおすすめします。

+0

こんにちは、ありがとう!私はこれでどこかになっていると思う。私が今見ている1つの問題は、オリジナルの刺激画像のプロットが、あなたの事例であらかじめ定義された-2と3Hzよりもはるかに複雑であることです。私が働いているのは、完全な罪の動きサイクルが800ms(すなわち80フレーム)で完了し、刺激が15.35度/秒で移動し、合計15.35/1000 * 800度の視角が80ms以内にあるということです。私はそれがあなたの例のためにfxとfyを定義しているので、それがどのようにHz(ここでは物理ダミー)に変換できるかについてはあまりよく分かりません。あなたはこれについて助言を持っていますか? –

+0

私の直感は、x軸が160列にわたって0〜16度の範囲を表し、y軸が0〜160度の範囲を表すので、xの隙間値を(0,16,160)に、yを(0,2,200) 200行以上2秒。私はそうする権利がありますか?私はこれを試してみましたが、y軸は信じられない範囲(-40〜40Hz)を作りましたが、x軸は10倍小さい(-4〜4)と思われました。 0〜16の間。 –

+0

(-2、3)で複素指数を表示するという私の目標は、周波数領域データを生成する手順が正しいことを確認することでした。コードスニペットを 'x'、' y'、 'im'(時間領域データ' im'の水平 'x'と垂直' y'サンプリング位置)を受け取り、 fx'、 'fy'、および' imF'(周波数領域データ 'imF'の水平および垂直サンプリング位置' fx'および 'fy')の3つの出力は正しいものでなければなりません:正しい最小値/周波数については、そして、周波数領域データの正しいスケーリング。これは理にかなっていますか? –

1

これは非常に簡単な答えです - あなたが探しているように見えるのは、正規化された周波数を表すX軸とY軸に沿ったスケールです。 fftshiftを使用していたので、DC項はプロットの途中にあるので、スケールは-0.5から0.5まで実行する必要があります。これは現在実行中のimagesc(C)の代わりにimagesc(x,y,C)コマンドで簡単に実行できます。 (あなたはXを使いますが、Matlabのヘルプはカラーマップを表すのでCを使います)。

変更は、あなたの最後から二番目の行:

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

、それは私はあなたが求めていると思う何を与えます。

+0

ありがとうございます。しかし、私はあなたが私の古いスレッドの最後のイメージを参照する場合、その男がどのように-30〜30の範囲まで軸を生成することができたのか分かりません。これは私の主な目的です。生の-0.5から0.5の値をそれぞれの時間的および空間的な周波数に変換することができる。 –

+0

OK - 時間および空間周波数を固定するには、より多くの情報が必要です。時間と空間の領域でのサンプルの間隔はどれくらいですか?例えば、時間領域におけるサンプルの間隔delta_tが(サンプリングレート50Hzに対応する)20msであった場合、対応する周波数軸は、-25Hzから25Hzの範囲であり、±1である/(2 * delta_t)。空間周波数については、同様の議論が適用されますが、Hz単位(1秒あたりのサイクル数)ではなく、単位距離あたりのサイクル数(m、cmなど)で測定されます。 – Dave

+0

ああ、右ある列/行から次の行への変化を意味するサンプルのだから私は時間ドメイン(y軸)に200秒を2秒間(10msごとに)反映しました。それは+/- 1 /(2 * 0.01)で、-50〜50Hzの範囲を与えますか? –

関連する問題