离散余弦变换DCT

时间:2021-08-28 21:31:43

DFT:离散傅里叶变换
实变换的DFT有共轭对称性,有一半的数据冗余。
因此,提出DCT。

DCT:在频域是实信号,减少一半以上的计算,实数域变换,变换核为实数,余弦函数。

用处:大多数自然信号的能量集中在低频部分(可用于数据压缩)

二维DCT变换定义
离散余弦变换DCT

因此我们获得DCT和TDCT系数矩阵,就可以得到最终的DCT变换矩阵。

result = DCT(h_h) * Image(h_w) * TDCT(w_w)’

离散余弦变换DCT

下面是DCT变换的代码:

//DCT变换子程序:已知192*48的图像矩阵f_short,获得 HM_W_H_H*HM_W_H_W(16*16)的汉明矩阵F
int MyDCT2(short f_short[N][M],short F[HM_W_H_H][HM_W_H_W])
{
    int i,j,k;
    int sum;
    short temp[HM_W_H_H][N];
    short DCT[M][M];    //48*48
    short TDCT[N][N];   //192*192
    FILE *fp_DCT,*fp_TDCT;

    /////*********************得到DCT变化系数,乘以个1024******************///////
    //float DCT1[M][M],TDCT1[N][N];
    //int ChangeInt;
    //float Ck;

    //for(i=0;i<M;i++)
    //{
    // if(i==0) 
    // Ck=1.000000/sqrt(2);
    // else Ck=1;
    // for(j=0;j<M;j++)
    // DCT1[i][j]=sqrt(2.000000/M)*Ck*cos((2*j+1)*i*PI/(2*M)); //DCT系数
    //}
    //for(i=0;i<N;i++)
    //{
    // if(i==0) 
    // Ck=1.000000/sqrt(2);
    // else Ck=1;
    // for(j=0;j<N;j++)
    // TDCT1[i][j]=sqrt(2.000000/N)*Ck*cos((2*j+1)*i*PI/(2*N)); //TDCT系数
    //}

    //for(i=0;i<M;i++)
    //{
    // for(j=0;j<M;j++)
    // {
    // DCT[i][j] = (short)(DCT1[i][j]*1024);
    // }
    //}
    //for(i=0;i<N;i++)
    //{
    // for(j=0;j<N;j++)
    // {
    // TDCT[i][j] = (short)(TDCT1[i][j]*1024);
    // }
    //}

    fp_DCT = fopen("DCT.txt","rb");
    fp_TDCT = fopen("TDCT.txt","rb");
    fread(DCT,sizeof(DCT),1,fp_DCT);
    fread(TDCT,sizeof(TDCT),1,fp_TDCT);

    //注意排流水 DCT和f_short的存储空间不应该有CACHE冲突 最好这些存储空间放在L2SRAM//
    //DCT变换:res = DCTPara(HM_W_H_H*h) * image(h*w) * TDCTPara(HM_W_H_H*w)' ;
    //最终得到一个 HM_W_H_H * HM_W_H_H 的矩阵,即取左上角16*16的矩阵
    //DCT * Image(M*N) * TDCT' , 只保留左上角的16*16
    for(i=0;i<HM_W_H_H;i++) //i的取值可以为0~48
    {
        for(j=0;j<N;j++) //0~192
        {
            sum=0;
            for(k=0;k<M;k++)
                sum+=(DCT[i][k]*f_short[j][k])>>10;
            temp[i][j]=sum; // temp(i,j) = DCT(i,:)*Image(:,j) 即DCT的第i行*图像的第j列(此处认为Image为M*N)
        }
    }   // 最终temp大小为HM_W_H_H*N(16*192)(可以为48*192)
    for(i=0;i<HM_W_H_H;i++) //0~48
    {
        for(j=0;j<HM_W_H_H;j++) //0~192 //此处应为HM_W_H_W??????
        {
            sum=0;
            for(k=0;k<N;k++)
                sum+=(temp[i][k]*TDCT[j][k])>>10;
            F[i][j]=sum; // F(i,j) = temp(i,:)*[TDCT(j,:)]' 即temp的第i行*TDCT的第j行的转置
        }
    }

    fclose(fp_DCT);
    fclose(fp_TDCT);

    return 0;
}