突然发现自己还有个博客,虽然万年不更。。。
自己搞的是图像处理,然后啥都不会,倒是在研究生课程里面接触到了第一个需要自己时间的图像的压缩算法,是JPEG图像压缩的一个主要算法吧,课件里讲这玩意叫离散余弦变换又称之为DCT好像吧,然后M里面已经封装好了这玩意了,可以直接调,但是作业要求要把离散余弦变换,反变换,量化,反量化的过程都写一遍,就懒得用M来搞了,用C定义了一堆二维数组磕磕绊绊,抱大腿才实现了。
上图为正常变换的公式,不难发现是个四重循环搞搞就能O,然后C是个类似于狄利克雷函数的东西,U或V等于0时,其值对应1/√2 反之皆取1就好。然后得到的这个F就称之为DCT变换系数。
至于量化的过程呢,就是拿F当中的每一个值去除以色差量化矩阵或亮度量化矩阵中的所对应的元素,然后取整,就可以得到量化的具体值,再接着很思博的拿量化后的值重新乘上色差量化矩阵或者亮度量化矩阵得到反量化系数。这玩意是用来恢复原图像用的。
上公式就是反变换用的公式了,得到的f跟原图像去比较,就可以评估好坏了。
代码分4块,一块一块写好就好了。主体代码如下:
const double pi=acos(-1.0);
const int maxn=8;
const int ldlh[maxn][maxn] = {
16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55,
14, 13, 16, 24, 40, 57, 69, 56,
14, 17, 22, 29, 51, 87, 80, 62,
18, 22, 37, 56, 68, 109, 103, 77,
24, 35, 55, 64, 81, 104, 113, 92,
49, 64, 78, 87, 103, 121, 120, 101,
72, 92, 95, 98, 112, 100, 103, 99};
const int sclh[maxn][maxn] = {
17, 18, 24, 47, 99, 99, 99, 99,
18, 21, 26, 66, 99, 99, 99, 99,
24, 26, 56, 99, 99, 99, 99, 99,
47, 66, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99,
99, 99, 99, 99, 99, 99, 99, 99};
int lh[maxn][maxn];
int flh[maxn][maxn];
int input[maxn][maxn];
double fdct[maxn][maxn];
int idct[maxn][maxn];
char s[1005]="ans1.txt";
double C(int x)
{
if(x!=0) return 1.0;
return 1.0/(sqrt(2.0));
}
void FDCT()
{
for(int u=0;u<maxn;u++)
{
for(int v=0;v<maxn;v++)
{
double sum=0.0;
for(int i=0;i<maxn;i++)
{
for(int j=0;j<maxn;j++)
{
sum+=input[i][j]*cos((2.0*i+1.0)*u*pi/(2.0*maxn))*cos((2.0*j+1.0)*v*pi/(2.0*maxn));
}
}
fdct[u][v]=2.0*C(u)*C(v)*sum/maxn;
}
}
}
void Quantization()
{
for(int i=0;i<maxn;i++)
{
for(int j=0;j<maxn;j++)
{
lh[i][j]=round(fdct[i][j]/ldlh[i][j]);
}
}
}
void Inv_Quantization()
{
for(int i=0;i<maxn;i++)
{
for(int j=0;j<maxn;j++)
{
flh[i][j]=lh[i][j]*ldlh[i][j];
}
}
}
void IDCT()
{
for(int i=0;i<maxn;i++)
{
for(int j=0;j<maxn;j++)
{
double sum=0.0;
for(int u=0;u<maxn;u++)
{
for(int v=0;v<maxn;v++)
{
sum+=C(u)*C(v)*flh[u][v]*cos((2.0*i+1.0)*u*pi/(2.0*maxn))*cos((2.0*j+1.0)*v*pi/(2.0*maxn));
// cout<<flh[u][v]<<"!!!"<<sum<<"~~~~~~"<<endl;
}
}
idct[i][j]=round(2.0*sum/maxn);
// cout<<"i:"<<i<<" "<<"j:"<<j<<" "<<idct[i][j]<<endl;
}
}
}