动态规划之图像压缩

【图像压缩】

实质:保留相同或绝大部分数据的前提下减小文件大小的过程。
原理:消除不必要的数据,以更高效的格式重新组织数据。
方法:有损压缩、无损压缩
有损压缩:会永久性地擦除掉一些数据;
无损压缩:保证持有全部的数据。

【问题描述】

在计算机中常用像素点灰度值序列{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;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值