【动态规划】图像压缩问题

来源:互联网 发布:lnmp环境yum搭建博客 编辑:程序博客网 时间:2024/05/16 19:16

    1、问题描述:

     在计算机中,常用像素点的灰度值序列{p1,p1,……pn}表示图像。其中整数pi,1<=i<=n,表示像素点i的灰度值。通常灰度值的范围是0~255。因此最多需要8位表示一个像素。

      压缩的原理就是把序列{p1,p1,……pn}进行设断点,将其分割成一段一段的。分段的过程就是要找出断点,让一段里面的像素的最大灰度值比较小,那么这一段像素(本来需要8位)就可以用较少的位(比如7位)来表示,从而减少存储空间

     b代表bits,l代表length,分段是,b[i]表示每段一个像素点需要的最少存储空间(少于8位才有意义),l[i]表示每段里面有多少个像素点,s[i]表示从0到i压缩为一共占多少存储空间。

     如果限制l[i]<=255,则需要8位来表示l[i]。而b[i]<=8,需要3位表示b[i]。所以每段所需的存储空间为l[i]*b[i]+11位。假设将原图像分成m段,那么需要位的存储空间。

      图像压缩问题就是要确定像素序列{p1,p1,……pn}的最优分段,使得依此分段所需的存储空间最小

     3、递推关系

      设s[i],1<=i<=n是像素序列{p1,p1,……pi}的最优分段所需的存储位数,则s[i]为前i-k个的存储位数加上后k个的存储空间。由最优子结构性质可得:

,式中

         4、构造最优解

     数组l[i],b[i]记录了最优分段所需的信息最优分段的最后一段的段长度和像素位数分别存储在l[n]和b[n]中,其前一段的段长度和像素位数存储于l[n-l[n]]和b[n-l[n]]中,依此类推,可在O(n)时间内构造最优解。

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>


#define MAX 20


int max_bit(int p[],int start,int end);
void compress(int s[],int p[],int b[],int l[],int n);
void back_tack(int s[],int b[],int l[],int n);


int seg;


int main()
{
    int i,l[MAX],b[MAX],s[MAX];
    int p[] = {10,12,15,255,1,2};


    for (i = 0; i < MAX; i++)
        s[i] = 999;


    compress(s,p,b,l,6);


    printf("最小空间为:%d\n",s[6]);
    seg = 0;
    back_tack(s,b,l,6);
    printf("总共分为%d段\n",seg);


    return 0;
}


int max_bit(int p[],int start,int end)
{
    int i,bit_max,max_value;
    
    max_value = 0;


    for (i = start; i < end; i++)        //求出最大值
        max_value = max_value > p[i] ? max_value : p[i];


    bit_max = 1;            //最大值至少要多少的存储位
    i = max_value / 2;
    while(i > 0)
    {
        bit_max++;
        i = i / 2;
    }


    return bit_max;
}


void compress(int s[],int p[],int b[],int l[],int n)
{
    int i,k,tmp;
    int bit_max;
    
    s[0] = 0;
    s[1] = max_bit(p,0,1) + 11;
    l[1] = 0;


    for (i = 2; i <= n; i++){                //控制s[i] 
        for (k = 0; k < i; k++){            // 分割点
            bit_max = max_bit(p,k,i);
            tmp = s[k] + (i-k)*bit_max + 11;
            //s[i] = s[i] < tmp ? s[i] : tmp;
            if (s[i] > tmp){
                s[i] = tmp;
                l[i] = i-k;
                b[i] = bit_max;
            }
        }
    }
}


void back_tack(int s[],int b[],int l[],int n)
{
    if (n == 0){
        return;
    } else {
        seg += 1;
        back_tack(s,b,l,n-l[n]);
        printf("段长度:%d,所需存储位数:%d\n",
            l[n],b[n]);
    }
}




0 0
原创粉丝点击