離散餘弦變換的改進

離散餘弦變換的改進fficeffice" />[/B]
鄧景仁(sgdjr2003)
2004年11月12日星期五
摘要:[/B]
關鍵詞:[/B]



1 前言[/B]
由於我還是高一新丁,文學底子很薄弱,對於一些技術方面的知識,我是有口說不出,無法用文字表達出來,因此這裏提供的知識只是我 所知道的1/4左右,還有3/4我不知該如何表達,特別是第三節“ 深入研究DCT”,我個人認爲簡直是淺入!
此文適合於那些對DCT或對Haar小波的Mallat算法有一定了解的人。
如果你只是菜鳥,不但想看懂此文,而且還要看懂其他的類似文章,那麼我教你一個最快的學習方法:
設 X={10,20}
分解的方法:低頻=10+20=30,高頻=10-20=-10,
即 Y={30,-10}
合併的方法:X(0)=(低頻+高頻)/2=(30+(-10))/2=10,X(1)=X(0)-高頻=10-(-10)=20
即 X={10,20}
只要搞清楚低頻和高頻是怎麼來的和如何合併的即可。
2 [/B]DCT[/B]簡介[/B]
DCT全名爲Discrete Cosine Transform,中文名爲離散餘弦變換。在衆人皆知的JPEG編碼中,就是使用了DCT來壓縮圖像的。爲什麼DCT可以壓縮圖像?我想這個問題有很多人都想知道,但其實這是錯誤的說法!因爲DCT在圖像壓縮中僅僅起到扶助的作用,給它n個數據,經變換後仍然會得出n個數據,DCT只不過消除了這n個數據的冗餘性和相關性。
即,用很少的數據就能大致還原出這n個數據,其他的一些DCT係數只起到修正的作用,可有可無。
DCT有一個缺點,就是計算量很大!因爲如果按照DCT的標準變換公式(二維)來實現8x8點陣的變換需要將近上萬次計算!後來提出了一種優化方法,即將二維的DCT分解爲兩個一維的DCT,這樣一來計算量就可以減少爲原來的1/4。但是計算量依然巨大,不具有使用價值,後來在1988年有人提出了一種快速算法叫AAN,它也是將二維的DCT分解成一維的形式,但是二維計算量已減少到只有600來次了,JPG和MPEG編碼中的DCT就是使用AAN算法實現的。
DCT還有一個缺點,就是不能無損變換,因爲DCT係數都是一些無理數,目前爲止,依然無法解決。
3 [/B]深入研究[/B]DCT[/B]
首先讓我們來看看AAN算法的第一階級變換代碼:
For I = 0 To 3
J = 7 - I
Y(I) = X(I) + X(J)
Y(J) = X(I) - X(J)
Next I
設X={10,20,30,40,50,60,70,80}
那麼Y={90,90,90,90,-10,-30,-50,-70}
可以看出,這一階級的低頻部分(相加得出的數據)全部相等,而高頻部分則呈線性或者是有規律的。DCT 之所以能以較少的數據大致還原圖像,就是因爲通過預測高頻部分而達到的。那麼爲何高頻部分可以預測呢?請仔細看上面的代碼,可以 看出DCT 是由外到內來進行處理的,由於像素與像素間有一定的關聯性,所以靠的越近的像素之間的差就應該越小,越遠就因該越大,但也並不是 說所有的數據都具有這種規律,因此DCT 預測出來的高頻數據就會和原高頻數據不大相同,它們之間的差便是第二節提出的修正數據。第二階級變換則是在第一階級變換的基礎上 再次分解出低、高頻,和預測高頻,得出修正值。第三階級……。最後,再將DCT係數按照重要程度由大到小,由左到右,重排列即可。
例:X={10, 20, 30, 40, 50, 60, 70, 80}
經過FDCT後:Y={127,-64,0,-7,-0,-2,0,-1}
其中127是最最重要的,而-64次之,以此類推。可以發現,-7,-2,-1的能量都很小,說明這三個修正值可以忽略,當忽略後,
得Y={127,-64,0,0,0,0,0,0}
經過IDCT後:X={ 14, 18, 27, 39, 51, 63, 72,76}
這與原始數據:X={10, 20, 30, 40, 50, 60, 70, 80}
是非常接近的,肉眼很難發覺。
4 [/B]爲何[/B]JPEG2000[/B]放棄[/B]DCT[/B]
[/B]在JPEG2000裏,放棄了基於塊的DCT,而改爲了小波變換。爲何要放棄DCT呢?我認爲最根本的原因還是跟DCT的計算量有關,第二節已經指出,爲了減少計算量,我們不得不使用只能處理8X8點陣的AAN快速算法(目前,也只有基於8X8點陣的),對於一幅圖像,必須將其分割成無數個8X8大小的“塊”,對塊進行變換。在低碼率下,就會產生方塊效應,要解決這個問題,唯有不使用基於區塊的AAN 快速算法,而是使用直接變換法,但計算量驚人!由於小波變換計算量很少,便於直接處理圖像數據,因此就不會產生塊效應,但假如用 小波也進行基於8X8點陣的塊變換,在低碼率下,同樣也會有塊效應!只要是基於塊變換的,那麼在低碼率下就會出現塊效應,無論是DCT還是小波。因此,如果忽略DCT直接處理的計算量問題的話,我認爲壓縮效率會比JPEG2000更好!(具體原因暫不討論)
5 DCT[/B]的改進[/B][/B]
下面的代碼是我對DCT變換的改進,它具有以下特性
l 無損變換
l 計算量少
l 原位計算
經改進後,它已不再叫作DCT了,可以認爲是一種新的算法,只不過是在DCT的基礎上修改而來。
以下是正變換:X爲輸入端,Y爲輸出端
設X={10,20,30,40,50,60,70,80}
那麼Y={45,40,0,0,0,0,0,0}
'----------------------------------第一階級
For I = 0 To 3
J = 7 - I
Y(J) = X(J) - X(I)
Y(I) = X(I) + Fix(Y(J) / 2)
Next I
'-----------------------------------第二階級
For H = 0 To 4 Step 4
For I = 0 To 1
J = 3 - I
X(J + H) = Y(J + H) - Y(I + H)
X(I + H) = Y(I + H) + Fix(X(J + H) / 2)
Next I
Next H
'-----------------------------------第三階級
For I = 0 To 6 Step 2
Y(I + 1) = X(I + 1) - X(I)
Y(I) = X(I) + Fix(Y(I + 1) / 2)
Next I
'-----------------------------------預測
Y(3) = Y(3) - Y(2)
Y(6) = Y(6) - Y(7)
Y(7) = Y(7) - Y(4)
'重要性排序與AAN一樣,皆爲{0,4,2,6,1,5,7,3},此略

爲何能無損?爲何能原位?和具體實現原理暫時略,以後我會補上
6 [/B]參考[/B][/B]
[1]丁貴廣,計文平,郭寶龍 Visual C++6.0數字圖像編碼 p44,p57,p170
 
我又寫了一個改進算法,可以無損或有損變換


詳見:host.bluexp.net/vbgood/forum/forum_posts.asp?TID=20672&PN=1&20672.html


我最近由圖像編碼改爲視頻編碼 但在這方面我還是新手,急需高手指點。。。

還有就是我想自己制訂編碼算法(即自創算法)。。

在此附上我在圖像處理上,設計的仿DCT一維變換的算法。原理很簡單,就是基於數據的相關性。。。,如果稍加改動,是可以無損變 換的,即不存在小數的精度問題。反變換就是本代碼的逆代碼。

Sub FT(Dat() As Integer, K As Integer, L As Integer)
Dim X(7) As Single, Y(7) As Single
Dim Pos As Integer, I As Integer, J As Integer
'0.125, 0.25, 0.5, 0.75, 0.875 比例係數
'1 / 8, 2 / 8, 4 / 8, 6 / 8, 7 / 8 比例係數的分數表達
' = Array(0, 4, 2, 6, 1, 5, 7, 3)
Pos = L
For I = 0 To 7
X(I) = Dat(Pos + K * I)
Next I

For I = 0 To 3
J = 7 - I
Y(I) = X(I) + X(J)
Y(J) = X(J) - X(I)
Next I

X(0) = Y(0) + Y(3)
X(1) = Y(1) + Y(2)
X(2) = Y(2) - Y(1)
X(3) = Y(3) - Y(0)
X(4) = Y(4)
X(5) = (Y(6) - Y(5)) * 0.5
X(6) = (Y(6) + Y(5)) * 0.875
X(7) = Y(7)

Y(0) = X(0) + X(1)
Y(1) = X(1) - Y(0) * 0.5
Y(2) = X(2) * 0.25 + X(3) * 0.75
Y(3) = X(3) * 0.25 - X(2) * 0.75

X(4) = X(5) + X(4): X(5) = X(5) - X(4) * 0.5
X(6) = X(7) + X(6): X(7) = X(7) - X(6) * 0.5

Y(4) = X(4) * 0.125 + X(6) * 0.875
Y(5) = X(6) * 0.125 - X(4) * 0.875
Y(6) = X(5) * 0.25 + X(7) * 0.75
Y(7) = X(7) * 0.25 - X(5) * 0.75

For I = 0 To 7
Dat(Pos + K * I) = Y(P(I))
Next I
End Sub


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章