性质
- 矩阵元素都为1/-1
- 正交矩阵、对称矩阵。hadamard变换为正交变换
- 奇数行/列偶对称,偶数行/列奇对称
- 满足Paserval定理
优点
- 仅含有加减运算,可用递归快速实现。(比余弦变换简单了太多了)
- 正变换和反变换具有相同形式,算法实现起来简单(变换是HXH)
- 具有递推公式,算法实现简单(体验一下实际代码就能发现,真的很简单易计算,而且不用浮点数运算)
- hadamard变换后求SATD和余弦变换后求SATD,结果差距不大,但是如果直接残差不变换求SAD,就和余弦变换后求SATD差距很大。所以,他和余弦变换有相似效果,但是算的快又简单
// 函数功能是计算8×8块的哈达玛变换,并计算其SAD值,m2[8][8]存放最终的变换结果
Int xCalcHADs8x8_ISlice(Pel *piOrg, Int iStrideOrg)
{
Int k, i, j, jj;
Int diff[64], m1[8][8], m2[8][8], m3[8][8], iSumHad = 0;
for( k = 0; k < 64; k += 8 )
{
diff[k+0] = piOrg[0] ;
diff[k+1] = piOrg[1] ;
diff[k+2] = piOrg[2] ;
diff[k+3] = piOrg[3] ;
diff[k+4] = piOrg[4] ;
diff[k+5] = piOrg[5] ;
diff[k+6] = piOrg[6] ;
diff[k+7] = piOrg[7] ;
piOrg += iStrideOrg;
//piOrg每次增加一行的偏移
}
//horizontal
for (j=0; j < 8; j++)
{
jj = j << 3;//每次+8
m2[j][0] = diff[jj ] + diff[jj+4];
m2[j][1] = diff[jj+1] + diff[jj+5];
m2[j][2] = diff[jj+2] + diff[jj+6];
m2[j][3] = diff[jj+3] + diff[jj+7];
m2[j][4] = diff[jj ] - diff[jj+4];
m2[j][5] = diff[jj+1] - diff[jj+5];
m2[j][6] = diff[jj+2] - diff[jj+6];
m2[j][7] = diff[jj+3] - diff[jj+7];
/*
m2=diff*Backstep_matrix
the derivation of Backstep_matrix
H0=[1]
H1=[1 1
1 -1]
/ 0/ 1/ 2/ 3/ / 0/ 1/ 2/ 3/ / 0/ 1/ 2/ 3/
/0/ 1/ 1/* 1/ 1/ /0/ 1/ 0/* 1/ 0/ /0/ H1 /* 0 /
/1/ 1/-1/* 1/-1/ /1/ 0/ 1/* 0/ 1/ /1/ /* /
* * * * * * * * = * * * * * * * * * * * * * * * * *
/2/ 1/ 1/*-1/-1/ /2/ 1/ 0/*-1/ 0/ /2/ 0 /* H1 /
/3/ 1/-1/*-1/ 1/ /3/ 0/ 1/* 0/-1/ /3/ /* /
所以这个结果就是,diff分别乘以Backstep_matrix[2->3]、Backstep_matrix[1->2]、Backstep_matrix[H1->1]
**/
m1[j][0] = m2[j][0] + m2[j][2];
m1[j][1] = m2[j][1] + m2[j][3];
m1[j][2] = m2[j][0] - m2[j][2];
m1[j][3] = m2[j][1] - m2[j][3];
m1[j][4] = m2[j][4] + m2[j][6];
m1[j][5] = m2[j][5] + m2[j][7];
m1[j][6] = m2[j][4] - m2[j][6];
m1[j][7] = m2[j][5] - m2[j][7];
m2[j][0] = m1[j][0] + m1[j][1];
m2[j][1] = m1[j][0] - m1[j][1];
m2[j][2] = m1[j][2] + m1[j][3];
m2[j][3] = m1[j][2] - m1[j][3];
m2[j][4] = m1[j][4] + m1[j][5];
m2[j][5] = m1[j][4] - m1[j][5];
m2[j][6] = m1[j][6] + m1[j][7];
m2[j][7] = m1[j][6] - m1[j][7];
}
//vertical
for (i=0; i < 8; i++)
{
m3[0][i] = m2[0][i] + m2[4][i];
m3[1][i] = m2[1][i] + m2[5][i];
m3[2][i] = m2[2][i] + m2[6][i];
m3[3][i] = m2[3][i] + m2[7][i];
m3[4][i] = m2[0][i] - m2[4][i];
m3[5][i] = m2[1][i] - m2[5][i];
m3[6][i] = m2[2][i] - m2[6][i];
m3[7][i] = m2[3][i] - m2[7][i];
m1[0][i] = m3[0][i] + m3[2][i];
m1[1][i] = m3[1][i] + m3[3][i];
m1[2][i] = m3[0][i] - m3[2][i];
m1[3][i] = m3[1][i] - m3[3][i];
m1[4][i] = m3[4][i] + m3[6][i];
m1[5][i] = m3[5][i] + m3[7][i];
m1[6][i] = m3[4][i] - m3[6][i];
m1[7][i] = m3[5][i] - m3[7][i];
m2[0][i] = m1[0][i] + m1[1][i];
m2[1][i] = m1[0][i] - m1[1][i];
m2[2][i] = m1[2][i] + m1[3][i];
m2[3][i] = m1[2][i] - m1[3][i];
m2[4][i] = m1[4][i] + m1[5][i];
m2[5][i] = m1[4][i] - m1[5][i];
m2[6][i] = m1[6][i] + m1[7][i];
m2[7][i] = m1[6][i] - m1[7][i];
}
for (i = 0; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
iSumHad += abs(m2[i][j]);
}
}
iSumHad -= abs(m2[0][0]);
//减去直流分量
iSumHad =(iSumHad+2)>>2;
//?????为什么加2除以4
return(iSumHad);
}