【图像压缩】
实质:保留相同或绝大部分数据的前提下减小文件大小的过程。
原理:消除不必要的数据,以更高效的格式重新组织数据。
方法:有损压缩、无损压缩
有损压缩:会永久性地擦除掉一些数据;
无损压缩:保证持有全部的数据。
【问题描述】
在计算机中常用像素点灰度值序列{p1,p2,…,pn}表示图像。其中整数 pi,1 ≤ i ≤ n ,表示像素点 i 的灰度值。通常灰度值的范围是0~255。因此,需要用8位表示一个像素。
图像的变位压缩存储格式将所给的像素点序列{p1,p2,…,pn}分割成 m 个连续段是是S1,S2……,Sm。第 i 个像素段Si中(1 ≤ i ≤ m ),有 l[ i ]个像素,且该段中每个像素都只用 b[ i ] 位表示。设 t[i]=,1 ≤ i ≤ m,则第 i 个像素段Si为Si={Pt[i]+1,……,Pt[i]+l[i]},1 ≤ i ≤ m
设hi=log(max Pk+1) ,t[i]+1 ≤ k ≤t[i]+l[i],则hi≤b[i]≤8。因此需要用3 位表示 b[i],1 ≤ i ≤ m。如果限制1 ≤ l[i] ≤ 255,则需要用8表示 l[i],1 ≤ i ≤ m。因此第 i 个像素段所需的存储空间为 l[i] * b[i]+11位。按此格式存储像素序列{p1,p2,…,pn},需要位的存储空间。
图像压缩问题要求确定像素序列{p1,p2,…,pn}的最优分段,使得依此分段所需的存储空间最小。其中,0 ≤ pi ≤ 256,1 ≤ i ≤ n,每个分段的长度不超过 256 位。
【算法分析】
1.最优子结构性质
设 l[i],b[i],1 ≤ i ≤ m 是{p1,p2,…,pn}的一个最优分段。显而易见,l[1],[1]是{p1,…,pl[1]}的一个最优分段,且l[i],b[i],2 ≤ i ≤ m是{pl[1]+1,…,pn}的一个最优分段。即图像压缩问题满足最优子结构性质
2.递归计算最优值
设s[i],1 ≤ i ≤ n是像素序列{p1,p2,…,pi}的最优分段所需的存储位数。由最优子结构性质易知:
s[i]=min{s[i-k]+k*bmax(i-k+1,i)}+11,1 ≤ k ≤ min{ i ,256}
式中,bmax(i,j)= log(max{pk}+1)]。
据此可设计解图像压缩问题的动态规划算法
3.构造最优解
算法Compress中用l[i],b[i]记录了最优分段所需的信息。最优分段的最后一段的段长度和像素位数分别存储在 l[n],b[n] 中。其前一段的段长度和像素位数存储于l[n-l[n]]和b[n-l[n]]中。以此类推,由算法计算出的 l 和 b 可在 O(n)时间内勾造出相应的最优解。
【C++代码实现】
//解图像压缩问题的动态规划算法
void Compress(int n, int p[], int s[], int l[], int b[])
{
int Lmax = 256, header = 11;
s[0] = 0;
for (int i = 1; i <= n; i++) {
b[i] = length(p[i]);
int bmax = b[i];
s[i] = s[i - 1] + bmax;
l[i]= 1;
for (int j = 2; j <= i && j <= Lmax; j++) {
if (bmax < b[i - j + 1])bmax = b[i - j + 1];
if (s[i] > s[i - j] + j * bmax) {
s[i] = s[i - j] + j * bmax;
l[i] = j;
}
}
s[i] += header;
}
}
int length(int i)
{
int k = 1; i = i / 2;
while (i > 0) { k++; i = i / 2; }
return k;
}
//构造最优解
void Traceback(int n, int& i, int s[], int l[])
{
if (n == 0)return;
Traceback(n - l[n], i, s, l);
s[i++] = n - l[n];
}
void Output(int s[], int l[], int b[], int n)
{
cout << "The optimal value is" << s[n] << endl;
int m = 0;
Traceback(n, m, s, l);
s[m] = n;
for (int j = 1; j <= m; j++) {
l[j] = l[s[j]];
b[j] = b[s[j]];
}
for (int j = 1; j <= m; j++){
cout << l[j] << ' ' << b[j] << endl;
}
}