DCT变换、DCT反变换
matlab实现详细过程不使用函数实现
二维DCT变换其实是在一维DCT变换的基础上在做了一次DCT变换,其公式如下
由公式我们可以看出,上面只讨论了二维图像数据为方阵的情况,在实际应用中,如果不是方阵的数据一般都是补齐之后再做变换的,重构之后可以去掉补齐的部分,得到原始的图像信息,这个尝试一下,应该比较容易理解。
另外,由于DCT变换高度的对称性,在使用Matlab进行相关的运算时,我们可以使用更简单的矩阵处理方式
public double [][] apllyDCT(int blocksize, int block[][]) {
double c = 0.0;
double[][] A1 = new double[blocksize][blocksize];//A1代表变换矩阵
double sizedouble=blocksize;
for (int i=-1;i<blocksize-1;i++)
{ if (i==-1)
c=Math.sqrt(1/sizedouble);
else
c=Math.sqrt(2/sizedouble);
for (int j=-1;j<blocksize-1;j++)
A1[i+1][j+1]=c*Math.cos(Math.PI*(j+1+0.5)*(i+1)/sizedouble);
}
// for (int i=0;i<8;i++)
// {
// for (int j=0;j<8;j++)
// System.out.println(A1[i][j]);
// System.out.println('\n');
// }
double[][] A2 = new double[blocksize][blocksize];
//二维数组转置
for (int i=0;i<blocksize;i++)
{
for (int j=0;j<blocksize;j++)
A2[j][i]=A1[i][j];
}
// 计算两个矩阵相乘
double[][] AX = new double[blocksize][blocksize];
for (int i = 0; i < blocksize; i++) {
for (int j = 0; j < blocksize; j++) {
for (int k = 0; k < blocksize; k++) {
AX[i][j] += A1[i][k] * block[k][j];
}
}
}
// 计算两个矩阵相乘
double[][] AXA = new double[blocksize][blocksize];
for (int i = 0; i < blocksize; i++) {
for (int j = 0; j < blocksize; j++) {
for (int k = 0; k < blocksize; k++) {
AXA[i][j] += AX[i][k] * A2[k][j];
}
}
}
return AXA;
}
在图像的接收端,根据DCT变化的可逆性,我们可以通过DCT反变换恢复出原始的图像信息,其公式如下:
同样的道理,我们利用之前的矩阵运算公司可以推导出DCT反变换相应的矩阵形式:
public int [][] apllyIDCT(int blocksize, double block[][]) {
double c = 0.0;
double[][] A1 = new double[blocksize][blocksize];//A1代表变换矩阵
double sizedouble=blocksize;
for (int i=-1;i<blocksize-1;i++)
{ if (i==-1)
c=Math.sqrt(1/sizedouble);
else
c=Math.sqrt(2/sizedouble);
for (int j=-1;j<blocksize-1;j++)
A1[i+1][j+1]=c*Math.cos(Math.PI*(j+1+0.5)*(i+1)/sizedouble);
}
// for (int i=0;i<8;i++)
// {
// for (int j=0;j<8;j++)
// System.out.println(A1[i][j]);
// System.out.println('\n');
// }
double[][] A2 = new double[blocksize][blocksize];
//二维数组转置
for (int i=0;i<blocksize;i++)
{
for (int j=0;j<blocksize;j++)
A2[j][i]=A1[i][j];
}
// 计算两个矩阵相乘
double[][] AX = new double[blocksize][blocksize];
for (int i = 0; i < blocksize; i++) {
for (int j = 0; j < blocksize; j++) {
for (int k = 0; k < blocksize; k++) {
AX[i][j] += A2[i][k] * block[k][j];
}
}
}
// 计算两个矩阵相乘
double[][] AXA = new double[blocksize][blocksize];
int[][] AXA1 = new int[blocksize][blocksize];
for (int i = 0; i < blocksize; i++) {
for (int j = 0; j < blocksize; j++) {
for (int k = 0; k < blocksize; k++) {
AXA[i][j] += AX[i][k] * A1[k][j];
}
}
}
for (int i = 0; i < blocksize; i++) {
for (int j = 0; j < blocksize; j++) {
AXA[i][j]=Math.round(AXA[i][j]);
AXA1[i][j]=(new Double(AXA[i][j])).intValue();
}
}
return AXA1;
}