Diskretna furijeova transformacija
Diskretna Furijeova transformacija ili DFT jeste Furijeova transformacija diskretnog i konačnog (ili periodičnog) signala. Diskretna Furijeova transformacija je time i specijalni oblik Z-transformacije kod koje se z nalazi na jediničnom krugu. Često se koristi pri obradi digitalnih signala, a najpoznatiji algoritam za to je brza furijeova transformacija (FFT, Fast Fourier Transformation, engl.).
Diskretna Furijeova transformacija može da posluži takođe za aproksimaciju (u određenim slučajevima i rekonstrukciju) funkcije koja odgovara signalu ili kao implementacija digitalnih filtera.
Putem inverzne Furijeove transformacije se iz Furijeovih koeficijenata sklapa izlazni signal, a povezivanjem DFT i inverzne DFT možemo da manipulišemo frekvencijama (nalazi primenu pri ekvilajzerima i filterima).
Definicija
Uzmimo da je komutativan, unitaran prsten, u kojem je broj jedinica. Dalje, u je jedinični koren.
Za vektor je diskretna furijeova transformacija na sledeći način definisana:
za
A za , inverzna furijeova transformacija je
za
DFT i IDFT u kompleksnom domenu
U kompleksnom domenu koristimo .
Onda je DFT za : za ,
a IDFT za : za
DFT i IDFT u realnom domenu
Računica u realnom domenu je:
Ojlerov identitet glasi: . Takođe važi i .
Stoga možemo još uprostiti izraz:
Što će reći, nije realan, ali samo N nezavisnih vrednosti (umesto 2N).
Za IDFT možemo zaključiti sledeće: Ukoliko za važi za sve , onda je IDFT realan vektor .
Pomeranje i skaliranje u vremenu i frekvenciji
Ako je signal periodičan, onda nije bitno da li transformišemo u opsegu ili . Indeksna promenljiva j treba da obuhvati N opseg, ali nije bitno gde on počinje odnosno gde se završava (ovo važi samo za slučaj da je signal periodičan, tj. da se vektor periodično ponavlja). Prisetimo se: za važi . Onda .
U praksi često želimo da razlika u indeksima bude istovremeno i razlika u vremenu ili razdaljini dva merenja
- , je perioda našeg merenja.
Često želimo i da koeficijentima dodelimo frekvenciju tako da su centrirane oko
- , je negde u blizini .
Uzmimo neku funkciju kojoj dodeljujemo tako da .
DFT je onda .
Iz toga sledi:
a IDFT je
Primeri
Primer filtera
Naš cilj je da izbacimo sve frekvencije koje su „tiše“ (tj. koje imaju amplitudu) od 1 V. Prvo pravimo tabelu:
| 0.5000 | 0.6000 | 0.7000 | 0.8000 | 0.9000 | 1.0000 | 1.1000 | 1.2000 | 1.3000 | 1.4000 | |
| 12.5000 | 10.0995 | 7.6644 | 6.8554 | 9.7905 | 13.5000 | 11.7546 | 7.4815 | 8.2905 | 12.0636 |
Imamo 10 vrednosti na 1 sekundu, što će reći perioda našeg merenja je , a frekvencija . Stoga mi možemo da rekonstruišemo talas do 5 Hz. Ukoliko u našem originalnom signalu ima frekvencija viših od 5 Hz onda će naša rekonstrukcija imati grešku. Ali, kao i uvek u životu, čovek mora biti optimističan te ćemo mi pretpostaviti da nema viših frekvencija (to je uostalom i jedan od razloga zašto kompakt-disk ima frekvenciju od oko 41 kHz; ljudsko uho može da registruje tek do 20 kHz!).
Sledi izračunavanje . Nas zanimaju samo vrednosti vezane za pozitivne indekse:
Sada imamo sve vrednosti i možemo da počnemo sa računanjem:
Izračunavanje ostalih koeficijenata ide analogno, te ćemo ih ovde samo navesti kao rezultate:
Imamo , sada želimo da izbacimo sve previše „tihe“ tonove. Trebaju nam :
10 -0.35i 1.5 - 0i 0.25 - 0.3i 0 + 0i
Znamo da važi: . Na taj način možemo da izračunamo i :
Ostale amplitude:
Iz možemo da zaključimo da frekvencija od 4 Hz nema u našem signalu. Često je vrlo zgodno navesti sve amplitude u grafikonu. Amplituda za neku frekvenciju je .
Sve i za koje važi izbacujemo i na kraju dobijamo rekonstruisanu i obrađenu funkciju:
Sada možemo da ponovo da izračunamo ili da se poslužimo IDFT i tako prerađen signal snimimo u memoriju.
Primer u C-u
#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;
}
Literatura
- Šablon:Cite book
- Šablon:Cite book
- Šablon:Cite book
- Šablon:Cite book esp. section 30.2: The DFT and FFT, pp. 830–838.
- Šablon:Cite journal
- Šablon:Cite journal
- Šablon:Cite journal
- Šablon:Cite journal
- Šablon:Cite journal
- Šablon:Cite journal
- Šablon:Cite journal
- Šablon:Cite journal
- Šablon:Cite journal
- Šablon:Cite journal
- Šablon:Cite journal
- Šablon:Cite journal