Tải bản đầy đủ (.doc) (51 trang)

Biến đổi fourier rời rạc sử dụng trong Xử lý ảnh số

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (457.87 KB, 51 trang )

Chơng
6
Biến đổi Fourier rời rạc
6.1 Chỉ dẫn
Trong chơng 2,chúng ta đã chứng minh rằng đáp ứng tần số của hệ thống của hệ thống
tuyến tính bất biến (LSI ) 2-D đợc cho bởi:


=

=
+
=
1 2
2211
)(
2121
),(),(
k k
kkj
ekkhH


(6.1)
Nếu h(k
1
,k
2
) chỉ có chỉ tồn tại với k
1


0, k
2


0 và tổng quát đợc xác định trong miền
hữu hạn có kích thớc N
ì
N thì


=

=
+
=
1
0
1
0
)(
2121
1 2
2211
),(),(
N
k
N
k
kkj
ekkhH



(6.2)
Công thức này chứng tỏ rằng
H( , )

1 2
là tuần hoàn, chu kỳ tuần hoàn là 2. Nếu
chúng ta lấy mẫu dới dạng
1
,
2
, và miền xác định là (0
1
2) và (0
2
2), N
ì
N mẫu, chúng ta có thể viết:



1 1
2
=
N
n




2 2
2
=
N
n
(6.3)
vì thế
( )


=
+



=
=
1
0
2
1
0
2121
1
2211
2
),(),(
N
k
knkn

N
j
N
k
ekkhnnH

(6.4)
Biểu thức (6.4) đợc gọi là biến đổi Fourier rời rạc 2-D hay còn gọi là DFT. Công thức
này đợc áp dụng vào nhiều ứng dụng nh lọc, nén ảnh, phóng đại ảnh. Trong chơng này
chúng ta sẽ nghiên cứu 2-D DFT và các kỹ thuật tính toán. Đầu tiên, chúng ta sẽ xem xét
1-D DFT, sau đó mở rộng ra cho 2-D.
6.2 Biến đổi Fourier 1-D
Biến đổi Fourier 1-D cho tín hiệu thời gian rời rạc f(kT) tính theo công thức :



=

=
1
0
2
)()(
N
k
nk
N
j
ekTfnF



(6.5)
Công thức này có thể viết lại dới dạng



=

=
1
0
Ư)()(
N
n
nk
N
WkfnF
(6.6)
75
ở đây f(k) = f(kT) và W
N
= e
- j2 /N
.
W
N
đợc gọi là hạt nhân của phép biến đổi. Tổng
quát, F(n) có dạng

)(

)()(
nj
enAnF

=
(6.7)
Ký hiệu A(n),

(n) gọi là phổ khuyếch đại và phổ pha của F(n).
6.2.1 Biến đổi ngợc DFT
Hàm f(k) là biến đổi ngợc DFT của F(n) cho bởi theo biểu thức



=
=
1
0
2
)(
1
)(
N
n
nk
N
j
enF
N
kf



(6.8)
Chứng minh: Từ định nghĩa của DFT




=

=


=

=


=
=






=
1
0
1

0
)(
1
0
1
0
1
0
)(
1
)(
1
)(
1
N
m
N
n
mkn
N
kn
N
N
n
N
m
nm
N
N
n

nk
N
Wmf
N
WWmf
N
WnF
N
(6.9)
Đặt


=

=
1
0
)(
N
n
mkn
N
WS
Nếu (k = m) thì S = N.
Nếu (k

m), chúng ta có thể viết:
S = 1 + W
N


(k -m )
+ W
N

2(k -m )
+ + W
N

(N-1)(k -m )

hoặc

)(
2
))(2(
m)-(k
N
m)-N(k
N
1
1
W-1
W-1
mk
N
j
mkj
e
e
S





=
=


Khi e
j2

(k-m)
= 1 và e
j2

/N. (k-m)
1 với (k m), vì vậy S = 0 với (k m ).
Vì vậy, biểu thức (6. 9) có thể rút gọn thành
f(k).N
1
)(
1
1
0
N
WnF
N
N
n
nk

N
==


=
Kết quả này giống nh biểu thức (6.8).
Khi f(k) có thể rút ra từ F(n) và ngợc lại, chúng gọi là cặp biến đổi. Cặp biến đổi này
có dạng

)()( nFkf
76
Chú ý từ biểu thức (6.8) ta có thể dễ dàng chứng minh:

)(
)(
1
)(
1
1
0
.
2
1
0
)(
2
kf
enF
N
enF

N
N
n
nk
N
j
N
n
Nkn
N
j
=
=
=



=

=
+


(6.10)
Mặc dù f(k) đợc xác định trên miền k

[0,N], nó vẫn là tín hiệu tuần hoàn với chu kỳ
NT. (T đợc bao hàm và rút ra từ biểu thức 6.5).
6.2.2 Một vài tính chất của DFT
Tuyến tính. Nếu ta có hai dãy tuần hoàn cùng f

1
(n) và f
2
(n), và cả hai dãy này tuần
hoàn với chu kỳ N, đợc dùng để tính
f
3
(k) = af
1
(k) + bf
2
(k) (6.11)
là kết quả của biến đổi DFT f
3
(n) cho bởi
F3(n) = aF1(n) + bF2(n) (6.12)
ở đây a, b là hằng số và
F
1
(n) = DFT của f
1
(k)
F2(n) = DFT của f2(k)
Tính đối xứng. Tính đối xứng của DFT rất hay đợc dùng.
nk
N
j
N
k
nk

N
j
N
k
N
N
j
N
k
nNk
N
eekf
eekf
WkfnNF


=


=


=




=
=
=



2
1
0
2
1
0
2
1
0
)(
)(
)(
)()(
Nếu f(k) là thực thì




=

=









=

)()()(
1
0
.
2
nFekfnNF
N
k
nk
N
j

(6.13)
Dấu * có nghĩa là liên hợp phức.

Tích chập tuần hoàn. Coi f
1
(k) và f
2
(k) là hai dãy tuần hoàn có chu kỳ N, với biến
đổi Fourier rời rạc là F
1
(n) và F
2
(n). Xem xét tích F(n
1
).F(n

2
)
77
)( Nkf +
khi
)()(
1
0
1111
1
11


=

=
N
k
kn
N
WkfnF

)()(
1
0
2222
2
22



=

=
N
k
kn
N
WkfnF

và tại các vị trí n
1
= n
2
= n
Đặt f
3
(k) = IDFT của F
1
(n).F
2
(n)
hay
( )
nk
N
n
WnFnF
N
kf



=
=
1
0
213
)().(
1
)(
vì vậy









=








=




=
+

=

=

=

=

=
+
1
0
)(
1
0
22
1
0
11
1
0
1
0
1
0

)(
2211
21
21
1 2
21
1
)()(
)()(
1
N
n
kkkn
N
N
k
N
k
nk
N
N
n
N
k
N
k
kkn
N
3
W

N
kfkf
WWkfkf
N
(k)f
Chú ý là



=


=
+
0
1
1
1
0
)(
21
N
n
kkkn
W
N
ở đây l là số nguyên. Vì vậy mà
)()()(
12
1

01
113
lNkkfkfkf
N
k
=


=
(6.14)
ở đây k = 0 đến 2N - 1.
Biểu thức trên biểu diễn tích chập của hai tín hiệu tuần hoàn. Chú ý rằng biêủ thức này
chỉ áp dụng cho hai dãy có chung một chu kỳ, và chiều dài của dãy tính theo biểu thức
trên là 2N - 1. Kết quả này chứng minh rằng trong DFT, tín hiệu có số mẫu lớn hơn N sẽ
đợc biến đổi thành dãy tuần hoàn có chu kỳ N. Khi dùng DFT cho một tín hiệu không có
chu kỳ, mà kết quả thu đợc từ tích hai dãy, ta sẽ phạm một sai lầm gọi là lỗi wraparound.
Đó là lý do ta phải làm cho cả hai dãy có chu kỳ bằng nhau. Để sửa lỗi này, một số số 0
cần phải thêm vào cả hai dãy để chiều dài hai dãy bằng nhau. Ví dụ, nếu một dãy có
chiều dài A, một dãy có chiều dài B, kết quả ta phải thêm các số 0 cho cả hai dãy có
chiều dài ít nhất là A + B - 1.
78
cho k = k
1
+ k
2
+ lN
các trờng hợp còn lại.
W =
.=
2

n-
N
2
1
11
1
2
22
1
11
1
0
2211
1
0
1
0
12
1
0
111111
)()(
)()()().(
k
N
k
kn
N
N
n

N
k
kn
N
N
k
kn
N
Wkfkf
WkfWkfnFnF



=


=

=


=

Bài tập 6.1
Cho hai dãy sau




=

0
1
)(
1
kf




=
0
1
)(
2
kf
1. Tính bằng tay tích chập của hai dãy trên. Vẽ một lu đồ biểu diễn thuật toán.
2. Làm lại phần 1, nhng lần này sử dụng tích chập tuần hoàn.
3. Lập một chơng trình C rút ra f
3
(k) từ biểu thức f
3
(k) = IDFT{DFT[f
1
(k)].
DFT[f
1
(k)]}. So sánh kết quả của phần 1 và phần hai.
4. Bây giờ thêm các số không vào f
1
(k) và f

2
(k) để chu kỳ của chúng = 5 + 6 - 1. Làm
lại phần 3 và so sánh kết quả.
6.3 Thuật toán biến đổi nhanh Fourier
Tính trực tiếp giá trị của DFT bao gồm N phép nhân phức và N - 1 phép cộng phức
cho mỗi giá trị của F(n). Khi N giá trị đợc tính toán thì N
2
phép nhân và N(N - 1) phép
cộng đợc tính toán. Cũng nh vậy, cho N có giá trị rất lớn, tính trực tiếp giá trị của DFT sẽ
đòi hỏi một số phép tính lớn đến mức không thể chấp nhận đợc. Để ví dụ, cho N = 1024
= 2
10
ta sẽ phải tính 2
20
= 1,048,576 phép nhân số phức và một số gần bằng nh vậy các
phép cộng.
Hoàn thiện có nghĩa là phải giảm số phép tính trong biến đổi Fourier xuống. Dới đây
chúng ta sẽ giới thiệu hai thuật toán hay dùng là thuật toán phân chia thời gian và thuật
toán phân chia tần số. DFT dùng các thuật toán trên gọi là Fast Fourier transform (FFT).
6.3.1 Thuật toán phân chia thời gian
Xem xét tính toán của DFT cho bởi (5.6) với N= 2
r
(r là một số nguyên bất kỳ). Cơ sở
của thuật toán phân chia thời gian thì rõ ràng. Tuy nhiên, việc thiết kế phần mềm cũng
đòi hỏi một số phân tích chi tiết. Để làm rõ các bớc của thuật toán này chúng ta sẽ bắt
đầu phân tích với N = 16 và sau đó mở rộng ra áp dụng cho N bất kỳ.
Cơ sở của thuật toán phân chia thời gian dựa trên cơ sở chiến lợc chia và chiếm. Các
bớc sau sẽ làm sáng tỏ thuật toán. Vì trong trờng hợp này N =16; nên,



=

=
15
0
16
)()(
k
nk
WkfnF

Chia dãy f(k) thành hai dãy, một dãy đợc rút ra từ phần tử chẵn và một dãy từ những
phần tử lẻ. Đó là,


=

=

+=
15
0
16
15
0
16
)()()(
k
nk
k

nk
WkfWkfnF

k chẵn k lẻ
Chúng có thể viết thành
79
0 k
1
4
các trờng hợp còn lại.
0 k
1
5
các trờng hợp còn lại.

=
+
=

++=
7
0
)12(
16
7
0
)2(
16
)12()2()(
k

kn
k
kn
WkfWkfnF
(6.15)
Chú ý là

nk
nkjknj
kn
W
eeW



=
==
8
.
8
2
)2(.
16
2
)2(
16

vì thế

=


=

++=
7
0
816
7
0
8
)12()2()(
k
nkn
k
nk
WkfWWkfnF
đặt

f(2k)(k)f
10
=

1)f(2k(k)f
11
+=
Ta đợc

=

=


+=
7
0
81116
7
0
810
)()()(
k
nkn
k
nk
WkfWWkfnF
(6. 16)
Đặt

=

=
7
0
81010
)()(
k
nk
WkfnF
(6.17)

=


=
7
0
81111
)()(
k
nk
WkfnF
(6.18)
Viết lại biểu thức (6.16) chúng ta đợc

(n)FW (n)F F(n)
11
-n
1610
+=
(6.19)
Cũng nh vậy, phát triển cho một biểu thức
(n)FW -(n)F 8)F(n
11
-n
1610
=+
(6.20)
Biểu thức (6.19) và (6.20) định dạng những đơn vị tính toán gọi là bớm. Hình 6.1 là
biểu đồ của phần tử bớm. Ký hiệu W
16
-n
thờng gọi là trọng lợng hay hệ số xoay. Hai biểu

thức này biểu diễn bớc cuối cùng trong lu đồ tính toán của hình 6.2.
Bây giờ xem xét biểu thức


=

=
7
0
81010
)()(
k
nk
WkfnF
Xử lý nh trên chúng ta có
80

∑∑
=
−−
=

++=
7
0
4108
3
0
41010
)12()2()(

k
nkn
k
nk
WkfWWkfnF
DÔ thÊy

-2n
16
-n
8
WW =
®Æt

1)(2kf(k)f
(2k)f(k)f
1021
1020
+=
=

H×nh 6.1 (a) Bím; (b) BiÓu diÔn rót gän.
81
F
10
(n) F(n)

F
11
(n) F(n+8)

F
10
(n) F(n)

F
11
(n) F(n+8)
1
W
16
-n
n
Hình 6.2 Bớc cuối cùng của thuật toán biến đổi FFT phân chia miền thời gian.
X(k) ký hiệu vector chứa giá trị đợc tính qua phép biến đổi FFT.
Vì vậy,

=

=

+=
3
0
421
3
0
2
1642010
)()()(
k

nk
k
nnk
WkfWWkfnF

(n)FW (n)F (n)F
21
-2n
162010
+=
(6.21)

(n)FW - (n)F 4)(nF
21
-2n
162010
=+
(6.22)
ở đây

=

=
3
0
42020
)()(
k
nk
WkfnF

(6.23)

=

=
3
0
42121
)()(
k
nk
WkfnF
(6.24)
Tơng tự

(n)FW (n)F (n)F
23
-2n
162211
+=
(6.25)
(n)FW - (n)F 4)(nF
23
-2n
162211
=+
(6.26)
ở đây

=


=
3
0
42222
)()(
k
nk
WkfnF
(6.27)
82
012!4567
012!4567
012!4567
891011121!
1415
F
10
(n)
F(n)
F
11
(n)
X(k)
X(k)

=

=
3

0
42323
)()(
k
nk
WkfnF
(6.28)

(2k)f (k)f
1122
=

1)(2kf (k)f
1123
+=
Biểu thức (6.21), (6.22), (6.25) và (6.26) có thể biểu diễn bằng sơ đồ hình 6.3. Biểu
thức (6.23), (6.24), (6.27) và (6.28) có thể tiếp tục chia nhỏ ra nh các bớc đã làm ở trên
nh sau:

(n)FW (n)F (n)F
31
-4n
163020
+=
(6.29)
(n)FW - (n)F 2)(nF
31
-4n
163020
=+

(6.30)

(n)FW (n)F (n)F
33
-4n
163221
+=
(6.31)
(n)FW - (n)F 2)(nF
33
-4n
163221
=+
(6.32)
(n)FW (n)F (n)F
35
-4n
163422
+=
(6.33)
(n)FW - (n)F 2)(nF
35
-4n
163422
=+
(6.34)

(n)FW (n)F (n)F
37
-4n

163623
+=
(6.35)
(n)FW - (n)F 2)(nF
37
-4n
163623
=+
(6.36)
ở đây
F n f k W
nk
k
30 30 2
0
1
( ) ( )=

=

(6.37)
F n f k W
nk
k
31 31 2
0
3
( ) ( )=

=


(6.38)
, vv.
Các biểu thức từ (6.29) đến (6.36) cho kết quả trong bớc thứ ba của thuật toán và biểu
diễn trong lu đồ hình 6.4.Mỗi phần tử từ F
30
(n) đến F
37
(n) có thể chia tiếp thành hai phần
tử nữa và bớc này tạo thành sơ đồ cuối cùng (bớc đầu tiên) trong lu đồ.
8!
012!012!
012!012!
012!4567
012!4567
0
F
20
(n)
2
F
21
(n)
4
6
F
22
(n)
0
F

2!
(n)
4
2
6
F
10
(n)
F
11
(n)
X(k)
X(k)
W
-2n
Hệ số xoay
n=0 đến !
H×nh 6.3 Bíc thø hai sau bíc cuèi cïng trong thuËt to¸n FFT.
84
Hình 6.4 Bớc đầu tiên của lu đồ FFT.
Hình 6.5 giới thiệu sơ đồ thuật toán FFT cho N = 16. Chú ý rằng do yêu cầu ban đầu
của chơng trình mà dãy vào đợc sắp xếp lại và chứa ở X(k), ví dụ

x(q) X(k) =
k = 0 đến 15
Bạn sẽ chú ý trên sơ đồ rằng q là giá trị bit của k.
Cho N = 2
4
= 16 chúng ta phải có bốn bớc trong lu đồ. Trong mỗi bớc cần phải có tám
bớm. Trong mỗi bớm chỉ có một phép nhân phức, hai phép cộng hoặc trừ phức. Tổng số

phép nhân phức là 8/2 . 4. Tổng quát cho N = 2
r
số phép nhân phức là (N/2) . r = (N/2 )
log
2
N và số phép cộng là Nlog
2
N. Chú ý, thực tế số phép nhân sẽ giảm xuống một ít, vì
trong bớc đầu tiên hệ số xoay W
0
= 1 và trong các bớc còn lại chúng ta cũng có các bớm
với hệ số xoay = 1.
Xem xét trờng hợp N = 1024 = 2
10
. Số phép nhân cần dùng cho FFT là (N/2).10 =
1024 ì 5 = 5120 so với 1 triệu phép nhân cho tính trực tiếp biến đổi DFT, đây là phơng
pháp tiết kiệm thực sự cho tính toán.
Bây giờ, chúng ta sẽ vạch ra thuật toán FFT. Đó không đơn thuần chỉ là sự phát triển
một chơng trình từ lu đồ. Tuy nhiên, chúng ta có thể nghiên cứu lu đồ và vạch ra các bớc
có thể dùng để phát triển một chơng trình. Từ lu đồ của hình 6.5 chúng ta có thể viết:
Bớc thứ nhất. Trong bớc này ta có tám bớm với trọng lợng (hệ số xoay) W
0
= 1.
Chúng ta có thể viết (xem hình 6.6)

for (j=0 đến 15 với bớc tăng 2)
{
T=X(j+1);
X(j+1)=X(j) - T;
X(j)=X(j) + T;

}
85
0
0
0
0
0
0
0
01010101
0101010101
0
F
!0
(n)
F
!1
(n)
F
!2
(n)
F
!!
(n)
F
!4
(n)
F
!5
(n)

F
!6
(n)
F
!7
(n)
X(k)
X(k)
Dãy
đầu
vào
đã
đ ợc
sắp
xếp
lại
Bớc thứ hai. Chúng ta có:
1.Bốn bớm với trọng lợng bằng 1.
for (j=0 đến 15 với bớc tăng 4)
{
T=X(j);
X(j+2)=X(j) - T;
X(j)=X(j) + T;
}
2. Bốn bớm với trọng lợng W
4
= W(3). Chú ý rằng chúng ta coi rằng các hệ số xoay
W, W
2
, , W

7
đã đợc tính và đợc chứa trong W(0), W(1), W(6).
for (j=0 đến 15 với bớc tăng 4)
{
T=X(j)W(3);X(j+2)=X(j) - T;
X(j)=X(j) + T;
}
Bớc thứ ba. Chúng ta có :
1. Hai bớm với trọng lợng bằng 1.
for (j=0 đến 15 với bớc tăng 8)
{
T=X(j);
X(j+4)=X(j) - T;
X(j)=X(j) + T;
}
86
Hình 6.5 Lu đồ thuật toán thuật toán phân chia miền thời gian.
2. Hai bớm với trọng lợng bằng W

(1) = W
2
.
for (j=1 đến 15 với bớc tăng 8)
{
T=X(j)W(1);
X(j+4)=X(j) - T;
X(j)=X(j) + T;
}



3. Hai bớm với trọng lợng bằng W(3) = W
4
.
for (j=2 đến 15 với bớc tăng 8)
{
87
0
1
2
3
4
5
6
7
0
2
4
6
0
2
4
6
0
4
0
4
0
4
0
4

0
0
0
0
0
0
0
0
0
8
4
12
2
10
6
14
1
9
5
13
3
11
7
15
0000
1000
0100
1100
0010
1010

0110
1110
0001
1001
0101
1101
0011
1011
0111
1111
0
8
4
12
2
10
6
14
1
9
5
13
3
11
7
15
0
4
8
12

2
6
12
14
1
5
9
13
3
7
11
15
0
2
4
6
8
10
12
14
1
3
5
7
9
11
13
15
0
1

2
3
4
5
6
7
8
9
10
11
12
13
14
15
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111

n=0 n=0 đến 1 n=0 đến 3 n=0 đến 7
n
W
8

n
W
4

n
W
2

n
W

Bậc của dãy vào biểu diễn
dạng nhị phân
Bậc của dãy ra biểu diễn
dạng nhị phân
b ớc 0 b ớc 1 b ớc 2 b ớc 3
T=X(j)W(3);
X(j+4)=X(j) - T;
X(j)=X(j) + T;
}
Hình 6.6 (a) Bớm cho thuật toán phân chia miền tần số;(b) Một bớm đơn giản.
4. Hai bớm với trọng lợng bằng W

(5) = W
6

.
for (j=3 đến 15 với bớc tăng 8)
{
T=X(j)W(5);
X(j+4)=X(j) - T;
X(j)=X(j) + T;
}
Bớc thứ t và là bớc cuối cùng.
1.Một bớm với trọng lợng bằng 1.
T = X(0)
X(8)= X(0) - T
X(0) = X(8) +T
2. Một bớm với trọng lợng bằng W

(0) = W.


T = X(1)W(0)
X(1+8)= X(1) - T
X(1) = X(1) +T
3. Một bớm với trọng lợng bằng W

(1) = W
2
.


T = X(1)W(1)
X(2+8)= X(0) - T
X(2) = X(2) +T

.
.
.
8. Một bớm với trọng lợng bằng W

(6) = W
7
.
88
F(2n)
F(2n+1)
)(
10
kf
)(
11
kf
(a)
F(2n)
F(2n+1)
)(
10
kf
)(
11
kf
(b)
T = X(7)W(6)
X(7+8)= X(7)-T
X(7) = X(7) +T

Các bớc dẫn chúng ta đến thuật toán với N = 16.
Thuật toán
ip=1
kk=8
incr=2
cho iter=0 đến 3 trong các bớc của 1
{
cho j=0 đến 15 trong các bớc của incr
{
i = j + ip
T = X(j)
X(i) = X(j) - T
X(j) = X(j) +T
nếu (iter không bằng 0) thì
{
cho k=1 đến ip-1 trong các bớc của 1
{
r = k*kk - 1
cho j=k đến 15 trong các bớc của 15
{
i=j+ip
T=X(i)*W(r)
X(i)=X(j)-1
X(j)=X(j)+T
}
}
}
kk=kk/2
ip= ip*2
inc=inc*2

}
Thuật toán trên có thể dễ dàng mở rộng cho tất cả các trờng hợp của N. Chỉ có một
lĩnh vực còn lại cần phải giải thích là sự sắp xếp lại các dãy dữ liệu đầu vào. Điều này có
thể tạo ra dễ dàng nếu chúng ta tạo ra một bảng (LUT) L(i), L(i) là các giá trị đảo ngợc
bit của i. Nếu dữ liệu đợc đọc từ một file thì tất cả các việc mà chúng ta phải làm là
chuyển địa chỉ vùng của chúng trong file qua bảng LUT và lu các dữ liệu này trong địa
chỉ chứa kết quả trong dãy đầu vào, X. Bớc này có thể chuyển sang ngôn ngữ C nh sau:
for (i=0; i<N; i++)
fscanf (fptr, %f , &X[L[i]]);

Kết quả của LUT đợc chuyển thẳng và đợc cung cấp với chơng trình của thuật toán
tính FFT trong Listing 6.1 dới dạng modun con dới tên bit_reversal( ).
Chơng trình 6.1 FFTDT.C FFT 1-D Thập phân trong miền thời gian.
/***********************************
* Program developed by: *
* M.A.Sid-Ahmed. *
* ver. 1.0 1992. *
89
* @ 1994 *
*********************************/
/* FFT - Decimation-in-time routine with examplemain
programing proper usage. */
#define pi 3.141592654
#include <stdio.h>
#include <math.h>
#include <alloc.h>
#include <stdlib.h>
void bit_reversal(unsigned int *, int , int);
void WTS(float *, float *, int, int);
void FFT(float *xr, float *xi, float *, float *,

int , int);
void main()
{
int i,k,m,N,n2,sign;
unsigned int *L;
float *wr,*wi,*xr,*xi;
char file_name[14];
FILE *fptr;
printf("\nEnter name of file containing data points-> ");
scanf("%s",file_name);
if((fptr=fopen(file_name,"rb"))==NULL)
{
printf("file %s does not exist.");
exit(1);
}
printf("Enter # of data points to be read >");
scanf("%d",&N);
m=(int)(log10((double)N)/log10((double)2.0));
k=1;
for(i=0;i<m;i++)
k<<=1 ;
if (k!=N)
{
printf("n Length of file has to be multiples of 2. ");
exit(1);
}
/* Allocating memory for bit reversal LUT. */
L=(unsigned int *)malloc(N*sizeof(unsigned int));
/* Generate Look-up table for bit reversal. */
bit_reversal(L,m,N);

/* Allocating memory for FFT arrays ( real and imag.) */
xr=(float *)malloc(N*sizeof(float));
xi=(float *)malloc(N*sizeof(float));
/* Setting-up the data in real and imag. arrays.*/
for(i=0;i<N;i++)
90
{
k=L[i] ;
xr[k]=(float)getc(fptr);
xi[k]=0.0 ;
}
fclose(fptr);
/* Allocating memory for twiddle factors. */
n2=(N>>1)-1;
wr=(float *)malloc(n2*sizeof(float));
wi=(float *)malloc(n2*sizeof(float));
/*Generating LUT for
twiddle factors. */
WTS(wr,wi,N,-1);
/* Taking FFT. */
FFT(xr, xi, wr, wi, m, N);
printf("Enter file name for storing FFT output >");
scanf("%s",file_name);
fptr=fopen(file_name,"w");
for(i=0;i<N;i++)
fprintf(fptr," %e %e",xr[i], xi[i]);
fclose(fptr);
}
void bit_reversal(unsigned int *L, int m, int N)
/* Routine for generating LUT for bit reversal.

Note: N=(2 to the power of m).
LUT will reside in LI]*/
{
unsigned int MASK,C,A,j,k,i;
for(k=0;k<N;k++)
{
MASK=1;
C=0;
for(i=0,j=m-1;i<m;i++,j )
{
A=(k&MASK)>>i;
A<<=j ;
C|=A;
MASK=MASK<<1;
}
L[k]=C;
}
}
void WTS(float *wr, float *wi, int N, int sign)
/* Generating LUT for twiddle factors.
Note:
sign=-1 for FFT, and
sign=1 for IFFT */
{
int n2,i ;
float theta;
91
n2=(N>>1)-1;
/* Generate look-up tables for twiddle factor. */
theta=2.0*pi/((float)N);

for(i=0;i<n2;i++)
{
wr[i]=(float)cos((double)((i+1)*theta));
wi[i]=(float)sin((double)((i+1)*theta));
if(sign==(int)(-1)); wi[i]=-wi[i];
}
}
/********************************************/
void FFT
(float *xr, float *xi, float *wr, float *wi, int m, int N)
{
/* FFT algorithm,
Decimation-in-time algorithm.
Note:
1. N=2 to the power of m.
2. The input arrays are assumed to be rearranged in bit-reverse order.
You will need to use routine "bitreversal" for that purpose.
3. The twiddle factors are assumed to be stored in LUT's wr[I and wi[j. You will
need to use routine LUT for calculating and storing twiddle factors.*/
int ip,k,kk,l,incr,iter,j,i;
float Tr,Ti;
ip=1;
kk=(N>>1);
incr=2 ;
for(iter=0; iter<m; iter++)
{
for(j=0; j<N; j+=incr)
{
i=j+ip;
Tr=xr[i];

Ti=xi[i];
xr[i]=xr[j]-Tr;
xi[i]=xi[j]-Ti;
xr[j]=xr[j]+Tr;
xi[j]=xi[j]+Ti;
}
if(iter!=0)
{
for(k=1; k<ip; k++)
{
l=k*kk-1 ;
for(j=k; j<N; j+=incr)
92
{
i=j+ip ;
Tr=xr[i]*wr[l]-xi[i]*wi[l];
Ti=xr[i]*wi[l]+xi[i]*wr[l];
xr[i]=xr[j]-Tr;
xi[i]=xi[j]-Ti;
xr[j]=xr[j]+Tr;
xi[j]=xi[j]+Ti;
}
}
}
kk>>=1;
ip<<=1;
incr<<=1;
}
}
Chú ý rằng trong chơng trình 6.1 chúng ta giả thiết là dữ liệu đợc lu nh dãy của các ký

tự không dấu. Nếu bạn muốn xử lý trên một số dấu phẩy động bạn cần thay đổi các câu
lệnh mở và đọc dữ liệu trong file dữ liệu. Chơng trình này cũng cho phép lựa chọn FFT
hoặc IFFT. Cho FFT, chơng trình con "WTS( ) " tính toán và lu các hệ số dịch xoay
trong một LUT đợc gọi lên vói tham số "sign" đợc gán giá trị -1, ví dụ, WTS(wr,wi,N,-1)
và cho IFFT, WTS(wr,wi,N,1). Với IFFT, bạn cần chia dãy ra cho N trong chơng trình gọi
hoặc là chơng trình chính.

Bài tập 6.2 Kiểm tra chơng trình FFT bằng cách làm lại chơng trình 6.1. Chú ý rằng
trong trờng hợp này bạn phải thêm các giá trị 0 để làm cho các dãy có chiều dài 2
4
= 16
và tất nhiên là lớn hơn chiều dài dãy nhỏ nhất đòi hỏi là (6 + 5 - 1). Mối tơng quan của
hai dãy cho kết quả trong một tín hiệu tuần hoàn có chu kỳ bằng 16.
6.3.2 Thuật toán phân chia tần số.
Thay vì chia dãy vào thành các vị trí chẵn và lẻ, chúng ta sẽ đa ra một chơng trình
giống nh chơng trình trên nhng lần này ta bắt đầu từ dãy ra. Chơng trình này bao gồm
các bớc sau:

kn
N
N
k
nN
N
Nk
kn
N
N
k
kn

N
W
N
kfWkf
WkfWkfnF


=


=


=









++=
+=
12/
0
2/
1
2/

12/
0
)
2
()(
)()()(

Bây giờ, chia dãy F(n) thành hai dãy dựa trên giá trị chẵn và lẻ của n.


)]
2
()([)2(
2/
2/).2(
12/
0
kn
N
Nn
N
k
W
N
kfWkfnF


=
++=


9!


)]
2
()([)12(
)12(
2/
2/).12(
12/
0
+
+

=
++=+

nk
N
Nn
N
k
W
N
kfWkfnF

Chú ý rằng
0.1
2
==

njnN
N
eW

0.1
)12(
2/).12(
==
+
+
nj
Nn
N
eW

Vì vậy

)]
2
()([)2(
2/
12/
0
kn
N
N
k
W
N
kfkfnF



=
++=

[ ]

])
2
()([)12(
2/
12/
0
kn
N
k
N
N
k
WW
N
kfkfnF


=
+=+

Đặt
f k f k f k
N

10
2
( ) ( ) ( )= + +
f k f k f k
N
W
N
k
11
2
( ) [ ( ) ( )]= +

Vì vậy


.)()2(
2/
12/
0
10
kn
N
N
k
WkfnF


=

=

(6.39)

.)()12(
2/
12/
0
11
kn
N
N
k
WkfnF


=

=+
(6.40)
Các biểu thức (6.39) và (6.40) có thể biểu diễn bằng dới dạng biểu đồ bớm nh trong
hình 6.6.
Chúng ta có thể tiếp tục chia nhỏ các tổng cho trong các biểu thức (6.39) và (6.40),
tiếp tục làm nh vậy cho tới khi mỗi tổng giảm xuống chỉ còn lại một phần tử. Giải thuật
này giống nh giải thuật thuật toán phân chia thời gian và để lại cho bạn nh một bài tập
cho bạn. Một lu đồ cho FFT phân chia tần số với N = 4 trình bày trong hình 6.7. Bạn cần
chú ý đến bậc của dữ liệu đầu ra là bit đợc đảo. Phần mềm thực hiện thuật toán trên thì
rất giống phần mềm thực hiện FFT phân chia miền thời gian, và một chơng trình C đợc
cung cấp ở Chơng trình 6.2.
94
Có lẽ bạn sẽ tự hỏi: nếu phân chia miền thời gian đã thực hiện đợc công việc thì tại
sao lại phải xem xét thêm FFT phân chia tần số. Để trả lời câu hỏi này, chúng ta sẽ cần

xem xét phần kế tiếp, FFT giảm lợc.
Chơng trình 6.2 FFTDF FFT phân chia tần số.
/****************************
* Program developed by: *
* M.A.Sid-Ahmed. *
* ver. 1.0 1992.1994 *
*****************************/
/* FFT - Decimation-in-frequency routine.*/
#define pi 3.141592654
void bit_reversal (unsigned int *, int, int);
void WTS(float *, float *, int, int) ;
void FFT(float *xr, float *xi , float, float, int, int);
void FFT
(float *xr, float *xi, float *wr, float *wi, int m, int N)
{
/* FFT algorithm.
Decimation-in-frequency algorithm.
Note :
1. N=2 to the power of m.
2. The output arrays are left in bit-reverse
order. You will need to use routine "bit-reversal" to place them in normal ascending
order.
3. The twiddle factors are assumed to be stored in LUT's wr[j and wiEj. You will
need to use routine LUT for calculating and storing twiddle factors. */
int ip,k,kk,l,incr,iter,j,i;
float Tr,Ti,diffr,diffi;
95
H×nh 6.7 N = 4, ph©n chia miÒn tÇn sè FFT.
ip= (N>>1) ;
kk=1;

incr=N;
for(iter=0; iter<m; iter++)
{
for(j=0; j<N; j+=incr)
{
i=i+ip;
Tr=xr[i];
Ti=xi[i];
xr[i]=xr[j]-Tr;
xi[i]=xi[j]-Ti;
xr[j]=xr[j]+Tr;
xi[j]=xi[j]+Ti;
}
for(k=1;k<ip; k++)
{
l=k*kk-1;
for(j=k; j<N; j+=incr)
96
0
1
2
3
4
5
6
7
0
2
4
6

0
2
4
6
0
4
0
4
0
4
0
4
0
0
0
0
0
0
0
0
0
8
4
12
2
10
6
14
1
9

5
13
3
11
7
15
0
8
4
12
2
10
6
14
1
9
5
13
3
11
7
15
0
4
8
12
2
6
12
14

1
5
9
13
3
7
11
15
0
2
4
6
8
10
12
14
1
3
5
7
9
11
13
15
0
1
2
3
4
5

6
7
8
9
10
11
12
13
14
15
n
W
8

n
W
4

n
W
2

n
W

{
i=j+ip;
Tr=xr[j]+xr[i];
Ti=xi[j]+xi[i];
diffr=xr[j]-xr[i];

diffi=xi[j]-xi[i];
xr[j]=Tr;
xi[j]=Ti ;
Tr=diffr*wr[1]-diffi*wi[1];
Ti=diffr*wi[1]+diffi*wr[1];
xr[i]=Tr;
xi[i]=Ti ;
}
}
kk<<=1;
ip>>=1 ;
incr>>=1;
}
}
6.3.3 FFT giảm lợc
Vấn đề có thể bắt đầu từ: cho 2
M
điểm dữ liệu, chúng ta sẽ phải làm thế nào tính toán
nhanh nhất khi dùng FFT có 2
L
điểm ra với M

L? Nếu M < L, có một số bớm sẽ bị
giảm lợc (xem hình 6.8). Một giải thuật dựa trên tính toán các phần tử của bớm khi việc
tính toán tất cả các phép tính là không cần thiết trong trờng hợp M < L gọi là giải thuật
giảm lợc đầu vào FFT. Trong trờng hợp M > L thuật toán gọi là thuật toán giảm lợc đầu
ra FFT.
Thuật toán giảm lợc đầu vào FFT. Trờng hợp này sẽ làm hoàn thiện hơn thuật toán
phân chia tần số. Hình 6.8 giới thiệu trờng hợp M = 1 và L = 4. Từ hình 6.8 chúng ta
nhận thấy (L-M) bớc đầu tiên có các phần tử bớm và L bớc cuối cùng có toàn bộ các b-

ớm. Sơ đồ này giúp chúng ta thay đổi chơng trình 6.2 thành chơng trình 6.3.
Chơng trình 6.3 "FFTIP.C". Giảm lợc đầu vào FFT.
/****************************
* Program developed by: *
* M.A.Sid-Ahmed. *
* ver. 1.0 1992. *
* @ 1994 *
***************************/
/* FFT - input pruning routine. */
void bit_reversal(unsigned int *, int , int);
void WTS(float *, float *, int, int);
void FFTP(float *xr, float *xi, float *, float *, int,int,int, int);
void FFTP(float *xr, float *xi, float *wr, float *wi,
int m_output, int N_output,
int m_input, int N_input )
{
/* FFT pruning algorithm.
Deimation-in-frequency algorithm.
97
Note:
1. Noutput=2 to the power of m_output.
N_output=Number of samples in the output sequence.
M_input=Number of samples in the input sequence. This should also be a multiple of
2.
2. The output arrays are left in bit-reverse order.
You will need to use routine "bit-reversal" to place them in normal ascending order.
3. The twiddle factors are assumed to be stored in LUT's wr[I and wi[I. You will
need to use routine LUT for calculating and storing twiddle factors. */
int ip,k,kk,l,inc r,iter,j,i;
float Tr,Ti,diffr,diffi;

ip=N_output>>1;
kk=l ;
incr=N_output;
for(iter=0; iter<(m_output-m_input); iter++)
{
for(j=0; j<N_output; j+=incr)
{
i=i+ip ;
xr[i]=xr[j];
xi[i]=xi[j];
}
for(k=l; k<N_input; k++)
{
l =k*kk- 1 ;
for(j=k; j<N_output; j+=incr)
{
i=j+ip ;
xr[i]=xr[j]*wr[l]-xi[j]*wi[l];
xi[i]=xr[j]*wi[l]+xi[j]*wr[l];
}
}
kk<<=1;
ip>>=1;
incr>>=1;
}
98
01
0246
8101214
1!57911

1!15
04812
26101415
91!!7111
5
08412210
6141951!
!11715
08412
21061419
51!!1171
5
W
-n
W
-6n
W
-4n
W
-2n
Hình 6.8 Lu đồ thuật toán giảm lợc đầu vào, N=4
for(iter=(m_output-m_input);iter<m_output;iter++)
{
for(j=0; j<N_output; j+=incr)
{
i=j+ip ;
Tr=xr [i];
Ti =xi [i] ;
xr[i]=xr[j]-Tr;
xi[i]=xi[j]-Ti;

xr[j]=xr[j]+Tr;
xi[j]=xi[j]+Ti;
}
for(k=l; k<ip; k++)
{
l=k*kk-1;
for(j=k; j<N_output; j+=incr)
{
i=j+ip;
Tr=xr[j]+xr[i];
Ti=xi[j]+xi[i];
diffr=xr[j]-xr[i];
diffi=xi[j]-xi[i];
xr[j]=Tr;
xi[j]=Ti ;
Tr=diffr*wr[l]-diffi*wi[l];
Ti=diffr*wi[l]+diffi*wr[l];
xr[i]=Tr;
xi[i]=Ti;
}
}
kk<<=l;
ip>>=l;
incr>>=l;
}
}
Bài tập 6.3
1.Cho dãy đầu vào :
x(k) = 1 k = 0,1,2, , 31.
x(k) = 0 các trờng hợp còn lại.

Tính 1024 điểm trong phổ tần số dùng chơng trình giảm lợc đầu vào FFT.
99

×