DCT变换编码及C语言实现

离散余弦变换(Discrete Cosine Transform,简称DCT变换)是一种与傅立叶变换紧密相关的数学运算。在傅立叶级数展开式中,如果被展开的函数是实偶函数,那么其傅立叶级数中只包含余弦项,再将其离散化可导出余弦变换,因此称之为离散余弦变换。

      离散余弦变换(DCT)是N.Ahmed等人在1974年提出的正交变换方法。它常被认为是对语音和图像信号进行变换的最佳方法。为了工程上实现的需要,国内外许多学者花费了很大精力去寻找或改进离散余弦变换的快速算法。由于近年来数字信号处理芯片(DSP)的发展,加上专用集成电路设计上的优势,这就牢固地确立离散余弦变换(DCT)在目前图像编码中的重要地位,成为H.261、JPEG、MPEG 等国际上公用的编码标准的重要环节。在视频压缩中,最常用的变换方法是DCT,DCT被认为是性能接近K-L变换的准最佳变换,变换编码的主要特点有:

  (1)在变换域里视频图像要比空间域里简单。

  (2)视频图像的相关性明显下降,信号的能量主要集中在少数几个变换系数上,采用量化和熵编码可有效地压缩其数据。

  (3)具有较强的抗干扰能力,传输过程中的误码对图像质量的影响远小于预测编码。通常,对高质量的图像,DMCP要求信道误码率,而变换编码仅要求信道误码率。

    DCT等变换有快速算法,能实现实时视频压缩。针对目前采用的帧内编码加运动补偿的视频压缩方法的不足, 我们在Westwater 等人提出三维视频编码的基础上, 将三维变换的结构应用于视频图像压缩, 进一步实现了新的视频图像序列的编码方法。

#include <memory.h>

#include <stdio.h>

#include <math.h>

#include <time.h>

#define PI 3.1415926

#define CLK_TCK CLOCKS_PER_SEC

int N;

void DCT(double *f,double *F)

{

 

 int n,m,x;

 double *dTemp=new double[N*N];//中间矩阵

 double *coff=new double[N*N];//变换系数

 coff[0]=(double)1/sqrt((double)N);

 for(m=1;m<N;m++)

  coff[m]=sqrt((double)2)/sqrt((double)N);

 memset(dTemp,0,sizeof(double)*N*N);

 memset(F,0,sizeof(double)*N*N);

 //一维变换

 for(n=0;n<N;n++)

  for(m=0;m<N;m++)

   for(x=0;x<N;x++)

    dTemp[m*N+n]+=coff[m]*f[x*N+n]*cos((2*x+1)*PI*m/(2*N));

 //第二次一维变换

 for(m=0;m<N;m++)

  for(n=0;n<N;n++)

   for(x=0;x<N;x++)

    F[m*N+n]+=coff[n]*dTemp[m*N+x]*cos((2*x+1)*PI*n/(2*N));

 delete []dTemp;

 delete []coff;

}

void iDCT(double *f,double *F)

{

 int m,y,x;

 double *dTemp=new double[N*N];//中间矩阵

 double *coff=new double[N*N];//变换系数

 coff[0]=1/sqrt((double)N);

 for(m=1;m<N;m++)

  coff[m]= sqrt((double)2) /  sqrt((double)N);

 memset(dTemp,0,sizeof(double)*N*N);

 memset(F,0,sizeof(double)*N*N);

 //一维变换

 for(x=0;x<N;x++)

  for(y=0;y<N;y++)

   for(m=0;m<N;m++)

    dTemp[x*N+y]+=coff[m]*F[x*N+m]*cos((2*y+1)*PI*m/(2*N));

 //第二次一维变换

 for(y=0;y<N;y++)

  for(x=0;x<N;x++)

   for(m=0;m<N;m++)

    F[x*N+y]+=coff[m]*dTemp[m*N+y]*cos((2*x+1)*PI*m/(2*N));

 delete []dTemp;

 delete []coff;

}

int main()

{

 

 clock_t start,end;

 start=clock();

 int i;

 long L;

 

 printf("变换维数:");

 scanf("%d",&N);

 

 double *f=new double[N*N];//初始矩阵

 double *F=new double[N*N];//变换后输出矩阵

 memset(F,0,sizeof(double)*N*N);//初始化为0

 for(i=0;i<N*N;i++)

 

 {

  printf("f[%d][%d]:",i/N,i%N);

  scanf("%lf",&f[i]);

 }

 printf("循环次数:");

 scanf("%d",&L);

//输出初始矩阵

 printf("变换前:\n");

 for(i=1;i<=N*N;i++)

 {

  printf("%f\t",f[i-1]);

  if(i%N==0)

   printf("\n");

 

 }

 for(i=0;i<L;i++)

  DCT(f,F);//变换

//输出变换后矩阵

 printf("变换后:\n");

 for(i=1;i<=N*N;i++)

 {

 

  printf("%f\t",F[i-1]);

  if(i%N==0)

   printf("\n");

 }

for(i=0;i<L;i++)

 iDCT(f,F);

 //输出反变换后矩阵

 printf("反变换后:\n");

 for(i=1;i<=N*N;i++)

 {

  printf("%f\t",f[i-1]);

  if(i%N==0)

   printf("\n");

 

 }

 //printf("\n");

 delete []f;

 delete []F;

 end=clock();

 printf("耗时:%f\n",(double)(end-start)/CLK_TCK);

 return 0;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值