標籤:style blog http color os 使用 strong ar for
DCT變換、DCT反變換、分塊DCT變換
歡迎轉載,但請註明出處!
一、引言
DCT變換的全稱是離散餘弦變換(Discrete Cosine Transform),主要用於將資料或映像的壓縮,能夠將空域的訊號轉換到頻域上,具有良好的去相關性的效能。DCT變換本身是無損的,但是在映像編碼等領域給接下來的量化、哈弗曼編碼等創造了很好的條件,同時,由於DCT變換時對稱的,所以,我們可以在量化編碼後利用DCT反變換,在接收端恢複原始的映像資訊。DCT變換在當前的映像分析已經壓縮領域有著極為廣大的用途,我們常見的JPEG靜態映像編碼以及MJPEG、MPEG動態編碼等標準中都使用了DCT變換。
二、一維DCT變換
一維DCT變換時二維DCT變換的基礎,所以我們先來討論下一維DCT變換。一維DCT變換共有8種形式,其中最常用的是第二種形式,由於其運算簡單、適用範圍廣。我們在這裡只討論這種形式,其運算式如下:
其中,f(i)為原始的訊號,F(u)是DCT變換後的係數,N為原始訊號的點數,c(u)可以認為是一個補償係數,可以使DCT變換矩陣為正交矩陣。
三、二維DCT變換
二維DCT變換其實是在一維DCT變換的基礎上在做了一次DCT變換,其公式如下:
由公式我們可以看出,上面只討論了二維映像資料為方陣的情況,在實際應用中,如果不是方陣的資料一般都是補齊之後再做變換的,重構之後可以去掉補齊的部分,得到原始的映像資訊,這個嘗試一下,應該比較容易理解。
另外,由於DCT變換高度的對稱性,在使用Matlab進行相關的運算時,我們可以使用更簡單的矩陣處理方式:
接下來利用Matlab對這個過程進行模擬處理:
1 clear; 2 clc; 3 X=round(rand(4)*100) %產生隨機矩陣 4 A=zeros(4); 5 for i=0:3 6 for j=0:3 7 if i==0 8 a=sqrt(1/4); 9 else10 a=sqrt(2/4);11 end 12 A(i+1,j+1)=a*cos(pi*(j+0.5)*i/4);13 end14 end15 Y=A*X*A‘ %DCT變換16 YY=dct2(X) %Matlab內建的dct變換
運行結果為:
1 X = 2 3 42 66 68 66 4 92 4 76 17 5 79 85 74 71 6 96 93 39 3 7 8 9 Y =10 11 242.7500 48.4317 -9.7500 23.505212 -12.6428 -54.0659 7.4278 22.795013 -6.2500 10.7158 -19.7500 -38.804614 40.6852 -38.7050 -11.4653 -45.934115 16 17 YY =18 19 242.7500 48.4317 -9.7500 23.505220 -12.6428 -54.0659 7.4278 22.795021 -6.2500 10.7158 -19.7500 -38.804622 40.6852 -38.7050 -11.4653 -45.9341
由上面的結果我們可以看出,我們採用的公式的方法和Matlab內建的dct變化方法結果是一致的,所以驗證了我們方法的正確性。
如果原始訊號是映像等相關性較大的資料的時候,我們可以發現在變換之後,係數較大的集中在左上方,而右下角的幾乎都是0,其中左上方的是低頻分量,右下角的是高頻分量,低頻係數體現的是映像中目標的輪廓和灰階分布特性,高頻係數體現的是目標形狀的細節資訊。DCT變換之後,能量主要集中在低頻分量處,這也是DCT變換去相關性的一個體現。
之後在量化和編碼階段,我們可以採用“Z”字形編碼,這樣就可以得到大量的連續的0,這大大簡化了編碼的過程。
四、二維DCT反變換
在映像的接收端,根據DCT變化的可逆性,我們可以通過DCT反變換恢複出原始的映像資訊,其公式如下:
同樣的道理,我們利用之前的矩陣運算公司可以推匯出DCT反變換相應的矩陣形式:
下面我們用Matlab對這個過程進行模擬:
1 clear; 2 clc; 3 X=[ 4 61 19 50 20 5 82 26 61 45 6 89 90 82 43 7 93 59 53 97] %原始的資料 8 A=zeros(4); 9 for i=0:310 for j=0:311 if i==012 a=sqrt(1/4);13 else14 a=sqrt(2/4);15 end 16 A(i+1,j+1)=a*cos(pi*(j+0.5)*i/4); %產生變換矩陣17 end18 end19 Y=A*X*A‘ %DCT變換後的矩陣20 X1=A‘*Y*A %DCT反變換恢複的矩陣
運行結果為:
1 X = 2 3 61 19 50 20 4 82 26 61 45 5 89 90 82 43 6 93 59 53 97 7 8 9 Y =10 11 242.5000 32.1613 22.5000 33.221212 -61.8263 7.9246 -10.7344 30.688113 -16.5000 -14.7549 22.5000 -6.877014 8.8322 16.6881 -35.0610 -6.924615 16 17 X1 =18 19 61.0000 19.0000 50.0000 20.000020 82.0000 26.0000 61.0000 45.000021 89.0000 90.0000 82.0000 43.000022 93.0000 59.0000 53.0000 97.0000
我們可以看到反變換後無損的恢複了原始資訊,所以證明了方法的正確性。但是在實際過程中,需要量化編碼或者直接捨棄高頻分量等處理,所以會出現一定程度的誤差,這個是不可避免的。
五、分塊DCT變換
在實際的影像處理中,DCT變換的複雜度其實是比較高的,所以通常的做法是,將映像進行分塊,然後在每一塊中對映像進行DCT變換和反變換,在合并分塊,從而提升變換的效率。具體的分塊過程中,隨著子塊的變大,演算法複雜度急速上升,但是採用較大的分塊會明顯減少映像分塊效應,所以,這裡面需要做一個折中,在通常使用時,大都採用的是8*8的分塊。
Matlab的 blkproc 函數可以幫我們很方便的進行分塊處理,下面給出我們的處理過程:
1 clear; 2 clc; 3 4 X=imread(‘pepper.bmp‘); 5 X=double(X); 6 [a,b]=size(X); 7 Y=blkproc(X,[8 8],‘dct2‘); 8 X1=blkproc(Y,[8 8],‘idct2‘); 9 10 figure11 subplot(1,3,1);12 imshow(uint8(X));13 title(‘原始圖‘);14 15 subplot(1,3,2);16 imshow(uint8(Y));17 title(‘分塊DCT變換圖‘);18 19 subplot(1,3,3);20 imshow(uint8(X1));21 title(‘分塊DCT恢複圖‘);22 23 Y1=dct2(X);24 X10=idct2(Y1);25 26 figure27 subplot(1,3,1);28 imshow(uint8(X));29 title(‘原始圖‘);30 31 subplot(1,3,2);32 imshow(uint8(Y1));33 title(‘DCT變換圖‘);34 35 subplot(1,3,3);36 imshow(uint8(X10));37 title(‘DCT反變換恢複圖‘);
運行結果為:
,我們可以明顯看出DCT變換與分塊DCT變換在使用時的區別。
六、小結
DCT、DWT等是影像處理的基礎知識,之前一直有用到,但是沒怎麼好好整理下,今天在做稀疏編碼的時候正好有用到,就順便整了下,希望能夠給後來者一些提示。
我的新浪微博:http://weibo.com/3109428257/profile?rightmod=1&wvr=5&mod=personinfo
Reference:http://wuyuans.com/2012/11/dct2/
【DCT筆記】DCT變換、DCT反變換、分塊DCT變換