Hadamard變換

原地址:http://blog.sina.com.cn/s/blog_6dcd52870100yl2v.html

        http://zh.wikipedia.org/wiki/%E9%98%BF%E8%BE%BE%E9%A9%AC%E5%8F%98%E6%8D%A2

哈達瑪(Hadamard)矩陣是由+1和-1元素構成的正交方陣。所謂正交方陣,指它的任意兩行(或兩列)都是正交的。把行(或列)看作一個函數,任意兩行(或兩列)都是正交的 H2n=[Hn Hn;Hn -Hn].在現在的視頻編碼標準中,阿達馬變換多被用來計算SATD(一種視頻殘差信號大小的衡量)。

變換矩陣

H.264中使用了4階和8階的阿達馬變換來計算SATD,其變換矩陣爲:

H_4 = \begin{bmatrix} 1 &  1 &  1 &  1 \\ 1 & -1 &  1 & -1 \\ 1 &  1 & -1 & -1 \\ 1 & -1 & -1 &  1 \end{bmatrix}
H_8 = \begin{bmatrix}  1 &  1 &  1 &  1 &  1 &  1 &  1 &  1 \\ 1 & -1 &  1 & -1 &  1 & -1 &  1 & -1 \\ 1 &  1 & -1 & -1 &  1 &  1 & -1 & -1 \\ 1 & -1 & -1 &  1 &  1 & -1 & -1 &  1 \\ 1 &  1 &  1 &  1 & -1 & -1 & -1 & -1 \\ 1 & -1 &  1 & -1 & -1 &  1 & -1 &  1 \\ 1 &  1 & -1 & -1 & -1 & -1 &  1 &  1 \\ 1 & -1 & -1 &  1 & -1 &  1 &  1 & -1 \end{bmatrix}

SATD計算方法

當計算4x4塊\begin{bmatrix}L_4\end{bmatrix}的SATD時,先使用下面的方法進行二維的阿達馬變換:

\begin{bmatrix}    L_4'  \end{bmatrix}=  \begin{bmatrix}    H_4  \end{bmatrix}\times  \begin{bmatrix}    L_4  \end{bmatrix}\times  \begin{bmatrix}    H_4  \end{bmatrix}

然後計算\begin{bmatrix}L_4'\end{bmatrix}所有係數絕對值之和並歸一化

類似的,當計算8x8塊\begin{bmatrix}L_8\end{bmatrix}的SATD時,先使用下面的方法進行二維的Hadamard變換:

\begin{bmatrix}    L_8'  \end{bmatrix}=  \begin{bmatrix}    H_8  \end{bmatrix}\times  \begin{bmatrix}    L_8  \end{bmatrix}\times  \begin{bmatrix}    H_8  \end{bmatrix}

然後計算\begin{bmatrix}L_8'\end{bmatrix}所有係數絕對值之和並歸一化

構建阿達馬變換

阿達馬變換轉換主要型式爲 \boldsymbol{2^k} 點的轉換矩陣,其最小單位矩陣爲 2x2 的阿達馬變換矩陣,以下分別爲二點、四點與如何產生 \boldsymbol{2^k} 點的阿達馬變換轉換步驟。

  • 二點阿達馬變換轉換:

\boldsymbol{W_2} = \begin{bmatrix} 1 & 1 \\ 1 & -1 \end{bmatrix}

  • 四點阿達馬變換轉換:

\boldsymbol{W_4} = \begin{bmatrix} 1 & 1 & 1 & 1 \\ 1 & 1 & -1 & -1 \\ 1 & -1 & -1 & 1 \\ 1 & -1 & 1 & -1 \end{bmatrix}

  • 產生 \boldsymbol{2^k} 點阿達馬變換的步驟:

步驟一: \boldsymbol{V_{2^{k+1}}} = \begin{bmatrix} \boldsymbol{W_{2^k}} & \boldsymbol{W_{2^k}} \\ \boldsymbol{W_{2^k}} & \boldsymbol{-W_{2^k}} \end{bmatrix}

步驟二: 根據正負號次序 (Sign change,正負號改變次數) 將矩陣 (Matrix) 內的列向量座順序上的重新排列。

\boldsymbol{V_{2^{k+1}}} \longrightarrow  \boldsymbol{W_{2^{k+1}}}

範例

\boldsymbol{V_4} = \begin{bmatrix} \boldsymbol{W_2} & \boldsymbol{W_2} \\ \boldsymbol{W_2} & \boldsymbol{-W_2} \end{bmatrix} = \begin{bmatrix} 1 & 1 & 1 & 1 \\ 1 & -1 & 1 & -1 \\ 1 & 1 & -1 & -1 \\ 1 & -1 & -1 & 1 \end{bmatrix} ,\quad \boldsymbol{W_4} = \begin{bmatrix} 1 & 1 & 1 & 1 \\ 1 & 1 & -1 & -1 \\ 1 & -1 & -1 & 1 \\ 1 & -1 & 1 & -1 \end{bmatrix}.

\boldsymbol{V_8} = \begin{bmatrix} 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & -1 & -1 & 1 & 1 & -1 & -1 \\ 1 & -1 & -1 & 1 & 1 & -1 & -1 & 1 \\ 1 & -1 & 1 & -1 & 1 & -1 & 1 & -1 \\ 1 & 1 & 1 & 1 & -1 & -1 & -1 & -1 \\ 1 & 1 & -1 & -1 & -1 & -1 & 1 & 1 \\ 1 & -1 & -1 & 1 & -1 & 1 & 1 & -1 \\ 1 & -1 & 1 & -1 & -1 & 1 & -1 & 1 \end{bmatrix}, \quad \boldsymbol{W_8} = \begin{bmatrix} 1 & 1 & 1 & 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & -1 & -1 & -1 & -1 \\ 1 & 1 & -1 & -1 & -1 & -1 & 1 & 1 \\ 1 & 1 & -1 & -1 & 1 & 1 & -1 & -1 \\ 1 & -1 & -1 & 1 & 1 & -1 & -1 & 1 \\ 1 & -1 & -1 & 1 & -1 & 1 & 1 & -1 \\ 1 & -1 & 1 & -1 & -1 & 1 & -1 & 1 \\ 1 & -1 & 1 & -1 & 1 & -1 & 1 & -1 \end{bmatrix}.

優缺點比較

優點

  • 僅需實數運算 (Real operation) 。
  • 不需乘法運算 (No multiplication) ,僅有加減法運算。
  • 有部分性質類似於離散傅立葉變換 (Discrete fourier transform) 。
  • 順向轉換 (Forward transform) 與反向轉換 (Inverse transform ) 型式爲相似式。

\begin{cases} \begin{matrix} F\left[ m \right] &=& \sum_{n=0}^{N-1} W\left[ {m, n} \right] f\left[ n \right] & & (\mbox{Forward Type}) \\ f\left[ n \right] &=& \left( \frac{1}{N} \right) \sum_{n=0}^{N-1} W\left[ {m, n} \right]F\left[ m \right] & &(\mbox{Inverse Type}) \end{matrix} \end{cases},

其中 F\left[ n \right] 與 f\left[ n \right] 分別都爲行向量 (Column vector) 。

缺點


Hadamard變換

   for (j=0;j<16;j)
   {
       for (i=0;i<16;i)
       {
          M1[ i ][j]=imgY_org[img->opix_y+j][img->opix_x+i]-img->mprr_2[k][j][ i ];       

          //計算當前宏塊殘差塊
          M0[i%4][i/4][j%4][j/4]=M1[ i ][j];
       }
   }
   current_intra_sad_2=0;              // noSADstart handicap here
   for (jj=0;jj<4;jj)
   {
     for (ii=0;ii<4;ii)
     {
      for (j=0;j<4;j)                                                      第一次一維Hadamard變換
      {                               
         M3[0]=M0[0][ii][j][jj]+M0[3][ii][j][jj];
         M3[1]=M0[1][ii][j][jj]+M0[2][ii][j][jj];
         M3[2]=M0[1][ii][j][jj]-M0[2][ii][j][jj];
         M3[3]=M0[0][ii][j][jj]-M0[3][ii][j][jj];
         M0[0][ii][j][jj]=M3[0]+M3[1];                     
         M0[2][ii][j][jj]=M3[0]-M3[1];                     
         M0[1][ii][j][jj]=M3[2]+M3[3];                     
         M0[3][ii][j][jj]=M3[3]-M3[2];                     
      }                                                                                    
      for (i=0;i<4;i)                                                       
      {                                                                                    
         M3[0]=M0[ i ][ii][0][jj]+M0[ i ][ii][3][jj];
         M3[1]=M0[ i ][ii][1][jj]+M0[ i ][ii][2][jj];
         M3[2]=M0[ i ][ii][1][jj]-M0[ i ][ii][2][jj];
         M3[3]=M0[ i ][ii][0][jj]-M0[ i ][ii][3][jj];
         第二次一維Hadamard變換
         M0[ i ][ii][0][jj]=M3[0]+M3[1];                     
         M0[ i ][ii][2][jj]=M3[0]-M3[1];                     
         M0[ i ][ii][1][jj]=M3[2]+M3[3];                     
         M0[ i ][ii][3][jj]=M3[3]-M3[2];                     
         for (j=0;j<4;j)                                             
         if ((i+j)!=0)                                                       
         current_intra_sad_2 += abs(M0[ i ][ii][j][jj]);      變換後的AC殘差值取絕對值求和作爲代價
      }                                                                                    
     }
   }
   for (j=0;j<4;j)
   for (i=0;i<4;i)
   M4[ i ][j]=M0[0][ i ][0][j]/4;
   // Hadamard of DC koeff
   for (j=0;j<4;j)     後面兩個for循環對當前宏塊的DC殘差進行Hadamard變換並將變換後的值取絕對值求和作爲代價
   {
      M3[0]=M4[0][j]+M4[3][j];
      M3[1]=M4[1][j]+M4[2][j];
      M3[2]=M4[1][j]-M4[2][j];
      M3[3]=M4[0][j]-M4[3][j];
      M4[0][j]=M3[0]+M3[1];
      M4[2][j]=M3[0]-M3[1];
      M4[1][j]=M3[2]+M3[3];
      M4[3][j]=M3[3]-M3[2];
   }
   for (i=0;i<4;i)
   {
      M3[0]=M4[ i ][0]+M4[ i ][3];
      M3[1]=M4[ i ][1]+M4[ i ][2];
      M3[2]=M4[ i ][1]-M4[ i ][2];
      M3[3]=M4[ i ][0]-M4[ i ][3];
      M4[ i ][0]=M3[0]+M3[1];
      M4[ i ][2]=M3[0]-M3[1];
      M4[ i ][1]=M3[2]+M3[3];
      M4[ i ][3]=M3[3]-M3[2];
      for (j=0;j<4;j)
      current_intra_sad_2 += abs(M4[ i ][j]);
    }
    if(current_intra_sad_2 < best_intra_sad2)
    {
      best_intra_sad2=current_intra_sad_2;
      *intra_mode = k; // update best intra mode
     }
    }
  }
   best_intra_sad2 = best_intra_sad2/2;
   return best_intra_sad2;
}
以上是源程序裏的一段,intra_16*16並不是計算SAD值,而是計算SATD。
其中M1中放的是宏塊的殘差,M0也是,不過爲了下面計算HADAMARD變換方便,他表示成M0[4][4][4][4]的形式,前2個[4][4]表示8X8塊座標,後2個[4][4]表示一個8X8裏的4X4塊座標。
程序先對殘差進行HADAMARD變換,然後把所有的DC分量提出來,再對DC分量做HADAMARD變換,
最後得到的是SATD。
有兩點不明白,誰知道的解釋一下:
1 在提取DC分量時爲什麼要除以4?
2 最後的best_intra_sad2 爲什麼要除以2?

這主要是由於SATD變換不是歸一化矩陣,變換後的係數值幅值增加,因此要相應的/2和/4

hadamard 變換本身就有一個 /2 的操作,因此每次變換都要對所有係數進行 /2。而 find_sad_16x16 函數執行了兩次 hadamard 變換:首先對 256 個係數進行一次,其次對所有 DC 係數再做一次,因此對 DC 係數應該 /4,而對 AC 係數應該 /2。find_sad_16x16 函數中的:M4[ i ][j]=M0[0][ i ][0][j]/4;就是對 DC 係數 /4,而最後的:best_intra_sad2 = best_intra_sad2/2;可以認爲是對 AC 係數的變相 /2。但這裏相當於是對所有係數 /2,所以 DC 係數多了一次 /2。這個多的一次就不知道原因了。

264樂園羣裏探討過這個問題。對於hadamard變換的/2已經有了結論。但是對DC係數多除的那一次2,目前尚未找到根據。
4階hadamard變換的定義式本身就是包含了這個/2的。可以見http://en.wikipedia.org/wiki/Hadamard_transform。這裏再多解釋一點
假設hadamard變換沒有/2, 變換矩陣爲:
1  1   1  1
1 -1   1 -1
1  1  -1 -1
1 -1  -1  1
這時對一個列向量v = (1, 1, 1, 1)'做變換,即用變換矩陣左乘列向量v,得到的變換後向量v' = (4, 0, 0, 0)'。
現在觀察v和v',在歐氏空間中,對一個向量的“大小”的衡量就是其長度,通過計算內積得到。那麼
len(v)   = sqrt( 1^2 + 1^2 + 1^2 + 1^2) = 2
len(v') = sqrt( 4^2 + 0^2 + 0^2 + 0^2) = 4
由此可見如果沒有那個/2,變換前後,該向量的長度發生了變化。這樣的變換是違背正交變換的定義的。

所以,作爲正交變換的hadamard變換,必須要有這個/2的歸一化。

A:推而廣之,整數 DCT 變換在變換前後向量的長度也發生了變化,爲什麼沒有除以 2 呢?

DCT變換(非整數)也是歸一化的整數變換也是正交變換,所以也一定會滿足歸一化的。firstime是不是忘記把scaling matrix考慮進來了啊。

按照畢厚傑書上 113 頁,變換矩陣爲公式 6.15(這個時候 scaling matrix 還沒分離出來吧?):
a   a   a   a
b   c -c -b
a -a -a   a
c -b   b -c
其中 a = 1/2,b = (2/5)^0.5。這個矩陣對列向量v = (1, 1, 1, 1)'做變換前後的向量長度並不相等啊。

才發現畢厚傑書上的DCT變換矩陣是錯的。。。。第二行第四列應該是-b
應該是
a  a  a  a
b  c -c  -b
a -a -a  a
c -b  b -c

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