DCT變換、DCT反變換、分塊DCT變換

1、引言

       DCT變換的全稱是離散餘弦變換(Discrete Cosine Transform),主要用於將數據或圖像的壓縮,可以將空域的信號轉換到頻域上,具備良好的去相關性的性能。DCT變換自己是無損的,可是在圖像編碼等領域給接下來的量化、哈弗曼編碼等創造了很好的條件,同時,因爲DCT變換時對稱的,因此,咱們能夠在量化編碼後利用DCT反變換,在接收端恢復原始的圖像信息。DCT變換在當前的圖像分析已經壓縮領域有着極爲廣大的用途,咱們常見的JPEG靜態圖像編碼以及MJPEG、MPEG動態編碼等標準中都使用了DCT變換。html

 


2、一維DCT變換

      一維DCT變換時二維DCT變換的基礎,因此咱們先來討論下一維DCT變換。一維DCT變換共有8種形式,其中最經常使用的是第二種形式,因爲其運算簡單、適用範圍廣。咱們在這裏只討論這種形式,其表達式以下:算法

      

       其中,f(i)爲原始的信號,F(u)是DCT變換後的係數,N爲原始信號的點數,c(u)能夠認爲是一個補償係數,可使DCT變換矩陣爲正交矩陣。函數

 


3、二維DCT變換

       二維DCT變換實際上是在一維DCT變換的基礎上在作了一次DCT變換,其公式以下:性能

    

       由公式咱們能夠看出,上面只討論了二維圖像數據爲方陣的狀況,在實際應用中,若是不是方陣的數據通常都是補齊以後再作變換的,重構以後能夠去掉補齊的部分,獲得原始的圖像信息,這個嘗試一下,應該比較容易理解。ui

      另外,因爲DCT變換高度的對稱性,在使用Matlab進行相關的運算時,咱們可使用更簡單的矩陣處理方式:編碼

   

      接下來利用Matlab對這個過程進行仿真處理:spa

複製代碼
 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 else 10 a=sqrt(2/4); 11  end 12 A(i+1,j+1)=a*cos(pi*(j+0.5)*i/4); 13  end 14 end 15 Y=A*X*A' %DCT變換 16 YY=dct2(X) %Matlab自帶的dct變換
複製代碼

       運行結果爲:3d

複製代碼
 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.5052 12 -12.6428 -54.0659 7.4278 22.7950 13 -6.2500 10.7158 -19.7500 -38.8046 14 40.6852 -38.7050 -11.4653 -45.9341 15 16 17 YY = 18 19 242.7500 48.4317 -9.7500 23.5052 20 -12.6428 -54.0659 7.4278 22.7950 21 -6.2500 10.7158 -19.7500 -38.8046 22 40.6852 -38.7050 -11.4653 -45.9341
複製代碼

      由上面的結果咱們能夠看出,咱們採用的公式的方法和Matlab自帶的dct變化方法結果是一致的,因此驗證了咱們方法的正確性。code

      若是原始信號是圖像等相關性較大的數據的時候,咱們能夠發如今變換以後,係數較大的集中在左上角,而右下角的幾乎都是0,其中左上角的是低頻份量,右下角的是高頻份量,低頻係數體現的是圖像中目標的輪廓和灰度分佈特性,高頻係數體現的是目標形狀的細節信息。DCT變換以後,能量主要集中在低頻份量處,這也是DCT變換去相關性的一個體現。orm

      以後在量化和編碼階段,咱們能夠採用「Z」字形編碼,這樣就能夠獲得大量的連續的0,這大大簡化了編碼的過程。

 


4、二維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:3 10 for j=0:3 11 if i==0 12 a=sqrt(1/4); 13 else 14 a=sqrt(2/4); 15  end 16 A(i+1,j+1)=a*cos(pi*(j+0.5)*i/4); %生成變換矩陣 17  end 18 end 19 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.2212 12 -61.8263 7.9246 -10.7344 30.6881 13 -16.5000 -14.7549 22.5000 -6.8770 14 8.8322 16.6881 -35.0610 -6.9246 15 16 17 X1 = 18 19 61.0000 19.0000 50.0000 20.0000 20 82.0000 26.0000 61.0000 45.0000 21 89.0000 90.0000 82.0000 43.0000 22 93.0000 59.0000 53.0000 97.0000
複製代碼

      咱們能夠看到反變換後無損的恢復了原始信息,因此證實了方法的正確性。可是在實際過程當中,須要量化編碼或者直接捨棄高頻份量等處理,因此會出現必定程度的偏差,這個是不可避免的。

 


5、分塊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 figure 11 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 figure 27 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變換在使用時的區別。


6、小結

        DCT、DWT等是圖像處理的基礎知識,以前一直有用到,可是沒怎麼好好整理下,今天在作稀疏編碼的時候正好有用到,就順便整了下,但願可以給後來者一些提示。

 

 

 

轉自:https://www.cnblogs.com/lzhen/p/3947600.html

相關文章
相關標籤/搜索