DCT是仅次与K-L变换的信息集中能力优秀的算法,K-L算法需要对每个子图象求变换矩阵,所以DCT是替代它的实用算法。
1. 8*8 2D DCT 直接变换
for (u = 0; u < 8; u++)
for (v = 0; v < 8; v++)
for (x = 0; x < 8; x++)
for (y = 0; y < 8; y++)
MAT(F,u,v)) += MAT(f,x,y)*c*cos((2*x+1)*u*pi/(2*nrow))*cos((2*y+1)*v*pi/(2*ncol));
x,y是像素坐标, x,y = 0,1,2,...,7;
u,v是像素坐标对应的DCT坐标;
MAT(m,i,j)表示8*8点矩阵m中第i行第j列的元素,一维算法计算量大,不实用,算法忽略。
C(0) = 1/sqrt(2), C(i) = 1 i = 1,2,...,7。
c = 1/4*C(u)*C(v)
2. 8*8 2D DCT 分解为一维形式
for (v = 0; v < 8; v++)
for (u = 0; u < 8; u++)
for (x = 0; x < 8; x++)
MAT(tmpF,u,v) += MAT(f,x,v)*coff*cos((2*x+1)*pi*u/(2*nrow)):
for (u = 0; u < 8; u++)
for (v = 0; v < 8; v++)
for (y = 0; y < 8; y++)
MAT(F,u,v) += coff*MAT(tmpF,u,y)*cos((2*y+1)*pi*v/(2*ncol)):
coff[0] = 1/sqrt(8);
coff[i] = sqrt(2)/sqrt(8); i = 1,2,...,7;
算法实现:
#define PI 3.14159265358979323846
void DCT(double *f, double *F, int r)
{
// 离散余弦变换点数
int count;
count = 1<<r; // r = 3 8*8变换 r = 4 16*16变换
// 循环变量
int m,n,x;
// 中间变量
double *dTemp = new double[count*count];
double *coff = new double[count];
// 设定系数coff
coff[0]=1/sqrt(count);
for (m = 1;m < count;m++)
{
coff[m]=sqrt(2)/sqrt(count);
}
//dTemp赋初值
memset(dTemp, 0, sizeof(double) * count * count);
memset(F, 0, sizeof(double) * count * count);
// 求F[m,n]
for (n = 0; n < count; n++)
{
for (m = 0; m < count; m++)
{
for (x = 0; x < count; x++)
{
dTemp[m*count+n] += f[x*count+n]*coff[m]*cos((2*x+1)*PI*m/(2*count));
}
}
}
for (m=0; m< count; m++)
{
for (n = 0; n < count; n++)
{
for (x = 0; x < count; x++)
{
F[m*count+n] += dTemp[m*count+x]*coff[n]*cos((2*x+1)*PI*n/(2*count));
}
}
}
// 释放内存
delete dTemp;
delete coff;
}