7.4 離散的コサイン変換 (DCT : discrete cosine transform )

6.4 離散的コサイン変換
(DCT : discrete cosine transform )
(1)DCTとは
DFTの式
N 1
X [k ]   x[n] exp(2 nk j / N ), (k  0,1,, N  1)
n 0
x[n] が偶関数であれば,DFTの式の虚数項を0として
N 1
X [k ]   x[n] cos(2 nk j / N )
n 0
DCTの解釈
半周期分が与えられたものとして,
偶関数になるように拡張し
(Sin成分,すなわち虚数項=0)
周期的に接続したDFTとみなすことができる。
(2)偶関数への拡張の方法
①軸のところを中心とみなす方法
②軸から0.5ずれたところで折り返す方法
① n = 0 を中心として偶関数に拡張
元の信号
① n = -0.5 を中心として偶関数に拡張
軸から0.5ずらす場合の接続方法も2種類
①周期2N-1として接続
②周期2Nとして接続(第Ⅱ種DCTで採用)
①周期2N-1として周期的に接続
②周期2Nとして周期的に接続
(3)DCTの種類
偶関数への拡張方法,周期的な接続方法の違いにより,
以下のような種類がある。
種類
定 義 式
第Ⅰ種
X [k ] 
第Ⅱ種
X [k ] 
第Ⅲ種
X [k ] 
第Ⅳ種
X [k ] 
N 1
2
 nk 
c[k ] c[n]x[n] cos

N
 N 
n 0
N 1
2
 (2n  1)k 
c[k ] x[n] cos

N
2N


n 0
2 N 1
 (2k  1)n 
c[n]x[n] cos


N n 0
2N


2 N 1
 (2n  1)(2k  1)n 
x
[
n
]
cos



N n 0
4N


(4)第Ⅱ種DCT
第Ⅱ種は,JPEG,MPEGなど
画像処理で最もよく使われる方法
X [k ] 
x[n] 


c[k ]  


N 1
2
 (2n  1)k 
c[k ] x[n] cos

N
2N


n 0
2 N 1
 (2n  1)k 
c[k ] X [k ] cos
 (逆変換)第Ⅲ種と同じ

N k 0
2N


1
, k 0
2
1 , k 0
VBAでの記述 ①データ宣言とパルス信号の設定
(色々な信号を設定してみよう)
Private
Private
Private
Private
Private
Const Num = 128
Const PI = 6.28318530717959 / 2
X(Num) As Double
Y(Num) As Double
Z(Num) As Double
Private Sub パルス()
For K = 0 To Num - 1
X(K) = -1
If K >= 30 And K < 80 Then X(K) = 1
Next
X(Num) = X(0)
End Sub
VBAでの記述 ②結果設定とボタンClickイベントハンドラ
Private Sub 結果設定()
With Worksheets("Sheet1")
.Cells(1, 1) = "No.": .Cells(1, 2) = "X"
.Cells(1, 3) = "Y":
.Cells(1, 4) = "Z"
For K = 0 To Num
.Cells(K + 2, 1) = K:
.Cells(K + 2, 2) = X(K)
.Cells(K + 2, 3) = Y(K): .Cells(K + 2, 4) = Z(K)
Next
End With
End Sub
Sub ボタン1_Click()
パルス
DCT
IDCT
結果設定
End Sub
VBAでの記述 ③DCT
Private Sub DCT() 'DCT(離散的コサイン変換)
Dim C0 As Double: Dim Cn0 As Double
C0 = 1 / Sqr(Num): Cn0 = Sqr(2#) * C0
For K = 0 To Num - 1
Y(K) = 0
For j = 0 To Num - 1
Y(K) = Y(K) + X(j) * Cos((2 * j + 1) * K * PI / (2 * Num))
Next
If K = 0 Then
Y(K) = C0 * Y(K)
Else
Y(K) = Cn0 * Y(K)
End If
Next
Y(Num) = 0
End Sub
VBAでの記述 ④IDCT
Private Sub IDCT() 'IDCT(離散的逆変換)
Dim C0 As Double: Dim C As Double
C0 = 1# / Sqr(2#): C = Sqr(2# / Num)
For j = 0 To Num - 1
Z(j) = C0 * Y(0)
For K = 1 To Num - 1
Z(j) = Z(j) + Y(K) * Cos((2 * j + 1) * K * PI / (2 * Num))
Next
Z(j) = C * Z(j)
Next
Z(Num) = Z(0)
End Sub
DCTの結果
色々なDCTの結果(1)
色々なDCTの結果(2)
(5)高速DCT(Chenのアルゴリズム)
FFTを使ってDCTを効率よく実行することも可能。
ここでは,Chenのアルゴリズムを示す。
DCTはN=4のとき次のように行列式で表現できる。
 X 0 
12
12
12
1 2   x0

 X 1 



x
1
cos(

/
8
)
cos(
3

/
8
)
cos(
5

/
8
)
cos(
7

/
8
)




 X 2 cos(2 / 8) cos(6 / 8) cos(10 / 8) cos(14 / 8)   x2


 





X
3
x
3

  cos(3 / 8) cos(9 / 8) cos(15 / 8) cos(21 / 8) 

これを小行列に分解し,因数分解することで計算量を減らす。
計算の手順
JPEG,MPEGで使われているN=8の場合
C / 4
x0
x1
x2
x3
x4
x5
x6
x7
C / 4
C / 4
 C / 4
1
S / 8
 C / 8
C / 8
S / 8
1
X 0
X 1
X 2
X 3
Cn  cos(n)
Sn  sin(n)
S / 16
 C / 4
1
1
1
1
 C / 16
C / 4
C / 4
C / 4
1
1
C 3 / 16
 S 3 / 16
C / 16
S 3 / 16
C 3 / 16
S / 16
X 4
X 5
X 6
X 7
VBAでの記述 ①データ宣言とパルス信号の設定
Private Const Num = 8
Private Const PI = 3.12159265358979
Private X(Num) As Double '入力データ
Private Y(Num) As Double '変換結果
Private Z(Num) As Double '逆変換結果
Private Sub パルス()
For K = 0 To Num - 1
X(K) = -1
If K >= 3 And K <= 5 Then X(K) = 1
Next
X(Num) = X(0)
End Sub
VBAでの記述 ②結果設定とボタンのClickイベントハンドラ
Private Sub 結果設定()
With Worksheets("Sheet2")
.Cells(1, 1) = "No.": .Cells(1, 2) = "X"
.Cells(1, 3) = "Y":
.Cells(1, 4) = "Z"
For K = 0 To Num
.Cells(K + 2, 1) = K:
.Cells(K + 2, 2) = X(K)
.Cells(K + 2, 3) = Y(K): .Cells(K + 2, 4) = Z(K)
Next
End With
End Sub
Sub Sheet2_ボタン1_Click()
パルス
FDCT
IDCT
結果設定
End Sub
VBAでの記述 ③Chenのアルゴリズム(その1)
Private Sub FDCT() 'FDCT(Chenのアルゴリズム)
'(既に入力XがYに複写されているものとする)
Cos4 = Cos(PI / 4):
Cos8 = Cos(PI / 8)
Cos16 = Cos(PI / 16): Cos163 = Cos(3 * PI /
Sin8 = Sin(PI / 8):
Sin16 = Sin(PI / 16)
Sin163 = Sin(3 * PI / 16)
For J = 0 To Num
Y(J) = X(J)
Next
For J = 0 To 3
tmp = Y(J) + Y(7 - J): Y(7 - J) = Y(J) Next
tmp = Y(0) + Y(3): Y(3) = Y(0) - Y(3): Y(0)
tmp = Y(1) + Y(2): Y(2) = Y(1) - Y(2): Y(1)
tmp = Cos4 * (-Y(5) + Y(6))
Y(6) = Cos4 * (Y(5) + Y(6))
Y(5) = tmp
16)
Y(7 - J): Y(J) = tmp
= tmp
= tmp
VBAでの記述 ④Chenのアルゴリズム(その2)
tmp = Cos4 * (Y(0) + Y(1))
Y(1) = Cos4 * (Y(0) - Y(1))
Y(0) = tmp
tmp = Sin8 * Y(2) + Cos8 * Y(3)
Y(3) = -Cos8 * Y(2) + Sin8 * Y(3)
Y(2) = tmp
tmp = Y(4) + Y(5): Y(5) = Y(4) - Y(5): Y(4) = tmp
tmp = -Y(6) + Y(7)
Y(7) = Y(6) + Y(7)
Y(6) = tmp
tmp = Sin16 * Y(4) + Cos16 * Y(7)
Y(7) = -Cos16 * Y(4) + Sin16 * Y(7)
Y(4) = tmp
VBAでの記述 ⑤Chenのアルゴリズム(その3)
tmp = Cos163 * Y(5) + Sin163 * Y(6)
Y(6) = -Sin163 * Y(5) + Cos163 * Y(6)
Y(5) = tmp
tmp = Y(1): Y(1) = Y(4): Y(4) = tmp
tmp = Y(3): Y(3) = Y(6): Y(6) = tmp
For J = 0 To Num - 1
Y(J) = 0.5 * Y(J)
Next
Y(Num) = Y(0)
End Sub
VBAでの記述 ⑥確認用逆変換
Private Sub IDCT() 'IDT(離散的逆変換)
Dim C0 As Double: Dim C As Double
C0 = 1# / Sqr(2#): C = Sqr(2# / Num)
For J = 0 To Num - 1
Z(J) = C0 * Y(0)
For K = 1 To Num - 1
Z(J) = Z(J) + Y(K) * Cos((2 * J + 1) * K * PI / (2 * Num))
Next
Z(J) = C * Z(J)
Next
Z(Num) = Z(0)
End Sub
FDCTの結果
色々なFDCTの結果(1)
色々なFDCTの結果(2)