离散余弦变换(DCT)的C++实现
程序员文章站
2022-07-14 22:18:54
...
DCT变换具体概念性质参考博客https://blog.csdn.net/BigDream123/article/details/101426393
这里仅仅描述DCT-2变换的C++实现。
DCT-2正变换的公式如下:
DCT-2反变换公式如下:
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
using namespace std;
#define NUM 8
#define PI 3.1415926
int around(double a)
{
if(a >= 0)
{
return int(a+0.5);
}
else
{
return int(a-0.5);
}
}
// DCT - Discrete Cosine Transform
void DCT(int data[NUM][NUM])
{
int output[NUM][NUM];
double alpha,beta;//C(k) C(l)
int m=0,n=0,k=0,l=0;
for(k = 0;k < NUM;k++)
{
for(l = 0;l < NUM;l++)
{
if(k == 0)
{
alpha = sqrt(1.0/NUM);
}
else
{
alpha = sqrt(2.0/NUM);
}
if(l == 0)
{
beta = sqrt(1.0/NUM);
}
else
{
beta = sqrt(2.0/NUM);
}
double temp = 0.0;
for(m = 0;m < NUM;m++)
{
for(n = 0;n < NUM;n++)
{
temp += data[m][n] * cos((2*m+1)*k*PI/(2.0*NUM)) * cos((2*n+1)*l*PI/(2.0*NUM));
}
}
output[k][l] = around(alpha * beta *temp);
}
}
memset(data,0,sizeof(int)*NUM*NUM);
memcpy(data,output,sizeof(int)*NUM*NUM);
}
//Inverse DCT
void IDCT(int data[NUM][NUM])
{
int output[NUM][NUM];
double alpha,beta;
int m=0,n=0,k=0,l=0;
for(m = 0;m < NUM;m++)
{
for(n = 0;n < NUM;n++)
{
double temp = 0.0;
for(k = 0;k < NUM;k++)
{
for(l = 0;l < NUM;l++)
{
if(k == 0)
{
alpha = sqrt(1.0/NUM);
}
else
{
alpha = sqrt(2.0/NUM);
}
if(l == 0)
{
beta = sqrt(1.0/NUM);
}
else
{
beta = sqrt(2.0/NUM);
}
temp += alpha * beta * data[k][l] * cos((2*m+1)*k*PI/(2*NUM)) * cos((2*n+1)*l*PI/(2*NUM));
}
}
output[m][n] = around(temp);
}
}
memset(data,0,sizeof(int)*NUM*NUM);
memcpy(data,output,sizeof(int)*NUM*NUM);
}
int main()
{
int input[NUM][NUM] =
{
{89, 101, 114, 125, 126, 115, 105, 96},
{97, 115, 131, 147, 149, 135, 123, 113},
{114, 134, 159, 178, 175, 164, 149, 137},
{121, 143, 177, 196, 201, 189, 165, 150},
{119, 141, 175, 201, 207, 186, 162, 144},
{107, 130, 165, 189, 192, 171, 144, 125},
{97, 119, 149, 171, 172, 145, 117, 96},
{88, 107, 136, 156, 155, 129, 97, 75}
};
DCT(input);
cout << "The result of DCT is:\n";
for(int i = 0;i < NUM;i++)
{
for(int j = 0;j < NUM;j++)
{
cout << input[i][j] << '\t';
}
cout << endl;
}
IDCT(input);
cout << "The result of IDCT is:\n";
for(int i = 0;i < NUM;i++)
{
for(int j = 0;j < NUM;j++)
{
cout << input[i][j] << '\t';
}
cout << endl;
}
return 0;
}
由于DCT变换的可分离性,可以将二维DCT变换分解为两个一维DCT变换,如下
代码实现如下:
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
using namespace std;
#define NUM 8
#define PI 3.1415926
int around(double a)
{
if(a >= 0)
{
return int(a+0.5);
}
else
{
return int(a-0.5);
}
}
//两次一维DCT变换
void DCT_1D_1D(int data[NUM][NUM])
{
int temp[NUM][NUM],output[NUM][NUM];
double alpha,beta;
int m=0,n=0,k=0,l=0;
//一维DCT水平变换
for(m = 0;m < NUM;m++)
{
for(l = 0;l < NUM;l++)
{
if(l == 0)
{
alpha = sqrt(1.0/NUM);
}
else
{
alpha = sqrt(2.0/NUM);
}
double tmp = 0.0;
for(n = 0;n < NUM;n++)
{
tmp += data[m][n] * cos((2*n+1)*l*PI/(2*NUM));
}
temp[m][l] = around(alpha * tmp);
}
}
//一维DCT垂直变换
for(l = 0;l < NUM;l++)
{
for(k = 0;k < NUM;k++)
{
if(k == 0)
{
beta = sqrt(1.0/NUM);
}
else
{
beta = sqrt(2.0/NUM);
}
double tmp = 0;
for(m = 0;m < NUM;m++)
{
tmp += temp[m][l] * cos((2*m+1)*k*PI/(2*NUM));
}
output[k][l] = around(beta * tmp);
}
}
memset(data,0,sizeof(int)*NUM*NUM);
memcpy(data,output,sizeof(int)*NUM*NUM);
}
//Inverse DCT
void IDCT(int data[NUM][NUM])
{
int output[NUM][NUM];
double alpha,beta;
int m=0,n=0,k=0,l=0;
for(m = 0;m < NUM;m++)
{
for(n = 0;n < NUM;n++)
{
double temp = 0.0;
for(k = 0;k < NUM;k++)
{
for(l = 0;l < NUM;l++)
{
if(k == 0)
{
alpha = sqrt(1.0/NUM);
}
else
{
alpha = sqrt(2.0/NUM);
}
if(l == 0)
{
beta = sqrt(1.0/NUM);
}
else
{
beta = sqrt(2.0/NUM);
}
temp += alpha * beta * data[k][l] * cos((2*m+1)*k*PI/(2*NUM)) * cos((2*n+1)*l*PI/(2*NUM));
}
}
output[m][n] = around(temp);
}
}
memset(data,0,sizeof(int)*NUM*NUM);
memcpy(data,output,sizeof(int)*NUM*NUM);
}
int main()
{
int input[NUM][NUM] =
{
{89, 101, 114, 125, 126, 115, 105, 96},
{97, 115, 131, 147, 149, 135, 123, 113},
{114, 134, 159, 178, 175, 164, 149, 137},
{121, 143, 177, 196, 201, 189, 165, 150},
{119, 141, 175, 201, 207, 186, 162, 144},
{107, 130, 165, 189, 192, 171, 144, 125},
{97, 119, 149, 171, 172, 145, 117, 96},
{88, 107, 136, 156, 155, 129, 97, 75}
};
DCT_1D_1D(input);
cout << "The result of 1D-DCT and 1D-DCT is:\n";
for(int i = 0;i < NUM;i++)
{
for(int j = 0;j < NUM;j++)
{
cout << input[i][j] << '\t';
}
cout << endl;
}
IDCT(input);
cout << "The result of IDCT is:\n";
for(int i = 0;i < NUM;i++)
{
for(int j = 0;j < NUM;j++)
{
cout << input[i][j] << '\t';
}
cout << endl;
}
return 0;
}
上一篇: 移动端h5自适应布局,mark点
下一篇: 离散余弦变换(含源码)