JPEG解碼——(6)IDCT逆離散余弦變換


  本篇是該系列的第六篇,承接上篇IZigZag變換,介紹接下來的一個步驟——逆離散余弦變換,即逆零偏置前的一個步驟。

  該步驟比較偏理論,其業務是對IZigZag變換后的數據,再進一步的處理,使其恢復DCT變換前的數據。

  需要補充一點說明的是,上面的DCT其實是DCT2,因為jpeg編碼下都是對8x8的像素塊進行處理。

1. 理論

  1.1. 背景

    DCT,即離散余弦變換,常用圖像壓縮算法,步驟如下

    1)分割,首先將圖像分割成8x8或16x16的小塊;
    2)DCT變換,對每個小塊進行DCT變換;
    3)舍棄高頻系數(AC系數),保留低頻信息(DC系數)。高頻系數一般保存的是圖像的邊界、紋理信息,低頻信息主要是保存的圖像中平坦區域信息。
    4)圖像的低頻和高頻,高頻區域指的是空域圖像中突變程度大的區域(比如目標邊界區域),通常的紋理豐富區域。

  1.2.算法

    二維DCT變換就是將二維圖像從空間域轉換到頻率域。形象的說,就是計算出圖像由哪些二維余弦波構成。其算法如下:

    

     其中,F就是變換得到的系數,f是圖像的像素值,A是轉換矩陣,其中i為二維波的水平方向頻率,j為二維波的垂直方向頻率,取值范圍都是0-(N-1),N是圖像塊的大小,其中:

    

    即進行如下步驟的處理可以得到DCT變換后的系數矩陣:

    1)求出轉換矩陣A;
    2)利用轉換矩陣A,轉換到頻域,即由圖像 f 得到系數矩陣F。

2. 實踐

  2.1. 圖像上運用實現

    DCT用圖像上的處理,都是對8x8的像素數據塊進行處理,因此,DCT2變換的轉換矩陣A為:

    

     其中,

     

    那么轉換矩陣A為:

    

     計算如這個鏈接

 1 void InitTransMat()  2 {  3     int i,j;  4     float a;  5 
 6     for(i=0;i<MAT_SIZE;i++)  7  {  8         for(j=0;j<MAT_SIZE;j++)  9  { 10             a = 0; 11             if(i==0) 12  { 13                 a=sqrt((float)1/MAT_SIZE); 14  } 15             else
16  { 17                 a=sqrt((float)2/MAT_SIZE); 18  } 19             DCT_Mat[i][j]= a*cos((j+0.5)*PI*i/MAT_SIZE); //變換矩陣
20  } 21  } 22     /* only for 8x8 */
23     //float Tmp[100][100] = { 24     // {0.3536, 0.3536, 0.3536, 0.3536, 0.3536, 0.3536, 0.3536, 0.3536,}, 25     // {0.4904, 0.4157, 0.2778, 0.0975, -0.0975, -0.2778, -0.4157, -0.4904,}, 26     // {0.4619, 0.1913, -0.1913, -0.4619, -0.4619, -0.1913, 0.1913, 0.4619,}, 27     // {0.4157, -0.0975, -0.4904, -0.2778, 0.2778, 0.4904, 0.0975, -0.4157,}, 28     // {0.3536, -0.3536, -0.3536, 0.3536, 0.3536, -0.3536, -0.3536, 0.3536,}, 29     // {0.2778, -0.4904, 0.0975, 0.4157, -0.4157, -0.0975, 0.4904, -0.2778,}, 30     // {0.1913, -0.4619, 0.4619, -0.1913, -0.1913, 0.4619, -0.4619, 0.1913,}, 31     // {0.0975, -0.2778, 0.4157, -0.4904, 0.4904, -0.4157, 0.2778, -0.0975,}, 32     //}; 33     //for (int i=0; i<8; i++) 34     // for (int j=0; j<8; j++) 35     // DCT_Mat[i][j] = Tmp[i][j];
36 }

  2.2. IDCT2—— 由F求f的過程

     前篇文章已介紹了由IZigZag變換后得到的系數矩陣F,那么要恢復原數據,就要進行如下變換:

    

    算法的C語言描述如下:

 1 int IDCT2(float (*dst)[8], int (*block)[8], bool dump)  2 {  3     float trans_matrix[8][8] = {  4         {0.3536,    0.3536,    0.3536,    0.3536,    0.3536,    0.3536,    0.3536,    0.3536,},  5         {0.4904,    0.4157,    0.2778,    0.0975,   -0.0975,   -0.2778,   -0.4157,   -0.4904,},  6         {0.4619,    0.1913,   -0.1913,   -0.4619,   -0.4619,   -0.1913,    0.1913,    0.4619,},  7         {0.4157,   -0.0975,   -0.4904,   -0.2778,    0.2778,    0.4904,    0.0975,   -0.4157,},  8         {0.3536,   -0.3536,   -0.3536,    0.3536,    0.3536,   -0.3536,   -0.3536,    0.3536,},  9         {0.2778,   -0.4904,    0.0975,    0.4157,   -0.4157,   -0.0975,    0.4904,   -0.2778,}, 10         {0.1913,   -0.4619,    0.4619,   -0.1913,   -0.1913,    0.4619,   -0.4619,    0.1913,}, 11         {0.0975,   -0.2778,    0.4157,   -0.4904,    0.4904,   -0.4157,    0.2778,   -0.0975,}, 12  }; 13 
14     float tmp[8][8]; 15 
16     float t=0; 17     int i,j,k; 18     for(i=0;i<8;i++)  //same as A'*I
19  { 20         for(j=0;j<8;j++) 21  { 22             t = 0; 23             for(k=0; k<8; k++) 24  { 25                 t += trans_matrix[k][i] * block[k][j]; //trans_matrix's ith column * block's jth column
26  } 27             tmp[i][j] = t; 28  } 29  } 30 
31     for(i=0; i<8; i++)  //same as tmp*A
32  { 33         for(j=0; j<8; j++) 34  { 35             t=0; 36             for(k=0; k<8; k++) 37  { 38                 t += tmp[i][k] * trans_matrix[k][j]; 39  } 40             dst[i][j] = t; 41  } 42  } 43 
44     if (dump) { 45         puts("----after idct2----"); 46         for (i=0; i<8; i++) { 47             for (j=0; j<8; j++) { 48                 printf("%3.4f ", dst[i][j]); 49  } 50             puts(""); 51  } 52         puts(""); 53  } 54 
55     return 0; 56 }

  2.3. 例子實踐

    根據前篇文章的IZigZag結果恢復數據,如下:

    有沒有注意到許多值是近似相等的?這是因為圖像在時域的連續性導致,可以利用其進行數據壓縮。

3. 篇外補充

  正是圖像上這種特性,才有了圖像壓縮的這種方法——空間去冗余。

  但是,需要說明一點的是,DCT2/IDCT2不是有損失壓縮(壓縮是數據量降低的概念,有損/無損是轉換前后信息是否丟失的概念),因為它可以完全恢復數據,只是這種變換將圖像在空間域/頻率域之間轉換。另外因為本人用的是浮點運算,因此會降低運算速度。一種優化可以把變換矩陣表每個元素都擴大10000倍,進行整形運算。

  從DCT正變換角度來說,時域的非0數據量很多,但是經DCT2轉換后,頻域(非0數據)數據量變得非常少,值都普遍縮小,很多較大的非零值轉換為了0,后續可以用其他算子來表示一連串連續的零數據。

  在這里,要特別感謝傅里葉這位法國數學家,正是因為他的出色工作,才使得如今的最常見的圖像壓縮技術變成了現實。

  正可謂,前人栽樹后人乘涼。前人的理論成果,后人在應用上開花結果。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM