Дискретна Фуријеова трансформација

Извор: testwiki
Пређи на навигацију Пређи на претрагу

Дискретна Фуријеова трансформација или ДФТ јесте Фуријеова трансформација дискретног и коначног (или периодичног) сигнала. Дискретна Фуријеова трансформација је тиме и специјални облик Z-трансформације код које се z налази на јединичном кругу. Често се користи при обради дигиталних сигнала, а најпознатији алгоритам за то је брза фуријеова трансформација (FFT, Fast Fourier Transformation, енгл.).

Дискретна Фуријеова трансформација може да послужи такође за апроксимацију (у одређеним случајевима и реконструкцију) функције која одговара сигналу или као имплементација дигиталних филтера.

Путем инверзне Фуријеове трансформације се из Фуријеових коефицијената склапа излазни сигнал, а повезивањем ДФТ и инверзне ДФТ можемо да манипулишемо фреквенцијама (налази примену при еквилајзерима и филтерима).

Дефиниција

Узмимо да је R комутативан, унитаран прстен, у којем је број N јединица. Даље, у R је w јединични корен.

За вектор c=(c0,…,cN−1)∈RN је дискретна фуријеова трансформација ĉ на следећи начин дефинисана:

ĉk=∑j=0N−1wj⋅k⋅cj за k=0,…,N−1

А за ĉk, инверзна фуријеова трансформација је

ck=1N∑j=0N−1w−j⋅k⋅ĉj за k=0,…,N−1

ДФТ и ИДФТ у комплексном домену

У комплексном домену користимо w=e2∗π∗kn,k=0,1,…,n−1.

Онда је ДФТ за c∈ℂN: ĉk=∑j=0N−1e−2πi⋅jkN⋅cj за k=0,…,N−1,

а ИДФТ за ĉ∈ℂN: ck=1N∑j=0N−1e2πi⋅jkN⋅ĉj за k=0,…,N−1

ДФТ и ИДФТ у реалном домену

Рачуница у реалном домену је:

ĉN−k=∑j=0N−1e−2πi⋅j(N−k)N⋅cj=∑j=0N−1e−2πi⋅(jNN−kN)⋅cj=∑j=0N−1e−2πi⋅(jNN)e2πi⋅(kN)⋅cj=∑j=0N−1e−2πi⋅je2πi⋅(kN)⋅cj

Ојлеров идентитет гласи: e2πi=1. Такође важи eiϕ‾=e−iϕ и z1+z2‾=z1‾+z2‾.

Стога можемо још упростити израз:

ĉN−k=∑j=0N−11⋅e2πi⋅(kN)⋅cj=∑j=0N−1e2πi⋅kN⋅cj=∑j=0N−1e−2πi⋅kN‾⋅cj=ĉk‾

Што ће рећи, ĉ∈ℂN није реалан, али само N независних вредности (уместо 2N).

За ИДФТ можемо закључити следеће: Уколико за ĉ∈ℂN важи ĉN−k=ĉk‾ за све k=0,…,N−1, онда је ИДФТ реалан вектор c∈ℝN.

Померање и скалирање у времену и фреквенцији

Ако је сигнал периодичан, онда није битно да ли трансформишемо у опсегу 0,…,N−1 или k,…,N−1+k. Индексна променљива j треба да обухвати N опсег, али није битно где он почиње односно где се завршава (ово важи само за случај да је сигнал периодичан, тј. да се вектор k,…,N−1+k периодично понавља). Присетимо се: за w важи wN=1. Онда wN+k=wN⋅wk=1⋅wk=wk.

У пракси често желимо да разлика у индексима буде истовремено и разлика у времену или раздаљини два мерења

tn=nT,n=1−M,…,N−M, T је периода нашег мерења.

Често желимо и да коефицијентима доделимо фреквенцију тако да су центриране око 0

ωn:=2πnNT,n=1−K,...,N−K, K је негде у близини N2.

Узмимо неку функцију f којој додељујемо x∈ℂN тако да xn=f(tn).

ДФТ је онда yn=f̂(ωn)=F(ωn).

Из тога следи:

F(ωn)=∑j=1−MN−Me−2πinjTNTxj=∑j=1−MN−Me−iωn⋅tjf(tj)

а ИДФТ је

f(tn)=xn=1N∑j=1−KN−Ke−2πinkTNTyj=1N∑j=1−KN−Keiωj⋅tnF(ωj)

Примери

Пример филтера

Ситуација: Звук који желимо да снимимо има следећи облик (када би га снимао аналоган микрофон): Датотека:Dft signal originalan.gif

Пошто је наш микрофон дигиталан, ми можемо само да снимимо појединачне вредности. На нашем компјутеру добијамо: Датотека:Dft signal diskretan.gif

Наш циљ је да избацимо све фреквенције које су „тише“ (тј. које имају амплитуду) од 1 V. Прво правимо табелу:

<math>t_i =\,</math>0.5000    0.6000    0.7000    0.8000    0.9000    1.0000    1.1000    1.2000    1.3000    1.4000
<math>f(t_i) =\,</math>12.5000   10.0995   7.6644    6.8554    9.7905   13.5000   11.7546    7.4815    8.2905    12.0636

Имамо 10 вредности на 1 секунду, што ће рећи периода нашег мерења је T=0.1, а фреквенција freq=1T=10Hz. Стога ми можемо да реконструишемо талас до 5 -{Hz}-. Уколико у нашем оригиналном сигналу има фреквенција виших од 5 -{Hz}- онда ће наша реконструкција имати грешку. Али, као и увек у животу, човек мора бити оптимистичан те ћемо ми претпоставити да нема виших фреквенција (то је уосталом и један од разлога зашто компакт-диск има фреквенцију од око 41 kHz; људско ухо може да региструје тек до 20 kHz!).

Следи израчунавање ωi. Нас занимају само вредности везане за позитивне индексе:

n=1−K,…,N−K;K=N/2=5;
n=−4,…,5
N⋅T=10⋅.1=1
ω0=2π0NT=0,ω1=2π,ω2=4π,…,ω5=10π

Сада имамо све вредности и можемо да почнемо са рачунањем:

F(ω0=0)=∑j=0N−1=9e−i⋅0⋅tj⋅f(tj)=∑j=09f(tj)=100=y0=ĉ0
F(ω1=2π)=∑j=0N−1=9e−i⋅2π⋅tj⋅f(tj)=…=0−3.5i=y1=ĉ1
F(ω2=4π)=∑j=0N−1=9e−i⋅4π⋅tj⋅f(tj)=…=15+0i=y2=ĉ2

Израчунавање осталих коефицијената иде аналогно, те ћемо их овде само навести као резултате:

F(ω3=6π)=2.5−3i=y3=ĉ3
F(ω4=8π)=6.7586e−14+2.8240e−14i=y4=ĉ4

Имамо ĉ, сада желимо да избацимо све превише „тихе“ тонове. Требају нам ck:

c=ĉ/N⇒ci=ĉi/10

ci: 10 -0.35i 1.5 - 0i 0.25 - 0.3i 0 + 0i

Знамо да важи: c0=a0,ci>0=12(ai−bii). На тај начин можемо да израчунамо ai и bi:

a0=10
a1−b1i=−0.7i⇒a1=0,b1=0.7

Остале амплитуде:

a2=3
a3=0.5
b3=0.6
a4=b4=0

Из a4=b4=0 можемо да закључимо да фреквенција од 4 -{Hz}- нема у нашем сигналу. Често је врло згодно навести све амплитуде у графикону. Амплитуда Ak за неку фреквенцију k је Ak=(ak2+bk2). У нашем случају наш фреквентни спектрум изгледа овако:

Датотека:Dft signal amplitude.gif

Све ai и bi за које важи (ai2+bi2)<1 избацујемо и на крају добијамо реконструисану и обрађену функцију:

f(t)=10+3cos⁡(2ωt)

Датотека:Dft signal obradjen.gif

Сада можемо да поново да израчунамо f(ti) или да се послужимо ИДФТ и тако прерађен сигнал снимимо у меморију.

Пример у -{C}--у

#include <stdio.h>
#include <math.h>
#include <complex.h>

#define pi 3.14159265
#define N 1000
#define T 0.001
#define FREQ 25

double my_function (double t )
{
	 /* violina svira ton od 25 -{Hz}- */
	 double ugaona_brzina = 2
  • pi
  • FREQ;
	 return 5 + 10
  • cos(ugaona_brzina
  • t) + 15
  • cos(2
  • (ugaona_brzina
  • t) )
			+ 20
  • sin (3
  • (ugaona_brzina
  • t) );
}

complex double get_fourier_coef (double omega_n, double* t, double* f  )
{
	 complex double coeff = 0;

	int k = 0;

	for (k = 0; k < N; k ++ )
	{
		// f[k] == f(t[k] );
		coeff += cexp (- I
  • omega_n
  • t[k])
  • f[ k] ;
	}
	return coeff;
}

int main()
{
	double t[N];
	double omega[N];
	double f[N];

	double a[N/2+1];
	double phi[N/2+1];
	int n = 0;

	complex double coeff[N];
	
	/* pripremi vektore t i f_t -> nas signal je f_t !*/
	t[0] = 0;
	f[0] = my_function (t[0] );
	omega[0] = 0;

	for (n = 1; n < N; n ++ )
	{
		omega[n] = 2
  • pi
  • n / (N
  • T );
		t[n] = n
  • T;
		f[n] = my_function (t[n] );	
	}

 
	/* izracunavanje koeficijenata */
	for (n = 0; n < N/2+1; n ++ )
	{
		coeff[n] = get_fourier_coef (omega[n], t, f );
		if (cabs(coeff[n]) > 0.1 ){
			printf ("# Koeficijent %d:  %e
  • e^i*%e\n", n, cabs(coeff[n]), carg(coeff[n]) );
		}
	}
	
	

	/* krece inverzija: */		
	a[0] = cabs(coeff[0]) / N;
	phi[0] = 0;
	for (n = 1; n < N/2+1; n++ )
	{
		if (cabs(coeff[n]) > 0.1 )
		{
			// c = 1/2 (a + ib ), zato a = 2
  • |c|, b == 0
			a[n] = 2 
  • cabs(coeff[n]) / N;
			if (abs (carg(coeff[n])) > 0.001 )
			{
				phi[n] = carg(coeff[n] );
			}
			 else 
			{
				phi[n] = 0;
			}
		} 
		else 
		{
			a[n] = 0;
			phi[n] = 0;
		}
	}


	/* predstavljanje rezultata: */
	printf ("Nasa rekonstrukcija:\n f (t) = %e", a[0] );
	for (n = 1; n < N/2+1; n++ )
	{

		if (a[n] )
		{
			if (phi[n] )
			{
				printf (" + %e
  • cos (%d
  • (2
  • pi
  • t + %e) )", a[n], n, phi[n] );
			}
			else
			{
				printf ("+ %e
  • cos (%d
  • 2
  • pi
  • t )", a[n], n );
			}
		}
	}
	printf ("\n" );
	

	return 0;
}

Референце

Шаблон:Литература

Шаблон:Литература крај

Види још

Шаблон:Нумеричка анализа Шаблон:Подножје

cs:Fourierova transformace#Diskrétní Fourierova transformace pt:Transformada de Fourier#Transformada discreta de Fourier fi:Fourier'n muunnos#Diskreetti Fourier'n muunnos