[Dynamic Programming] Image Compression Problem

[Dynamic Programming] Image Compression Problem

    1. Problem description:

     In the computer, the gray value sequence {p1, p1, ... pn} of common pixel points represents the image. The integer pi,1<=i<=n, represents the gray value of pixel i. Usually the gray value range is 0~255. So a maximum of 8 bits are required to represent a pixel.

      The principle of compression is to set breakpoints in the sequence {p1,p1,...pn} and divide it into sections. The process of segmentation is to find breakpoints, so that the maximum gray value of the pixels in a segment is relatively small, then this segment of pixels (original need 8 bits) can be represented by fewer bits (such as 7 bits), thus Reduce storage space .

     b represents bits, l represents length, segment is, b[i] represents the minimum storage space required for a pixel in each segment (less than 8 bits only makes sense), l[i] represents how many pixels there are in each segment , s[i] indicates how much storage space it takes to compress from 0 to i.

     If the limit l[i]<=255, 8 bits are required to represent l[i]. And b[i]<=8, requires 3 bits to represent b[i]. So the storage space required for each segment is l[i]*b[i]+11 bits. Assuming that the original image is divided into m segments, the storage space of bits is required.

      The problem of image compression is to determine the optimal segmentation of the pixel sequence {p1, p1, ... pn}, so that the storage space required for this segmentation is the smallest .

     2. Optimal substructure properties

      Let l[i],b[i],1<=i<=m be an optimal segment of {p1,p1,...pn}, then l[1],b[1] is {p1,... ...,pl[1]} is an optimal segment, and l[i],b[i],2<=i<=m is an optimal segment of {pl[1]+1,...,pn} segment. That is, the image compression problem satisfies the optimal substructure property.

     3. Recursive relationship

      Let s[i], 1<=i<=n be the storage bits required for the optimal segmentation of the pixel sequence {p1,p1,...pi}, then s[i] is the storage bits of the first ik Plus the storage space of the last k. From the optimal substructure properties, we can get:

, where

         4. Construct the optimal solution

     The arrays l[i], b[i] record the information required for the optimal segment. The segment length and pixel bits of the last segment of the optimal segment are stored in l[n] and b[n], respectively. The segment length and pixel bits of a segment are stored in l[nl[n]] and b[nl[n]], and so on, to construct the optimal solution in O(n) time.

     The specific implementation code of the algorithm is as follows:

// 3d7 dynamic programming image compression problem   
#include " stdafx.h "   
#include <iostream>   
 using  namespace std;   
  
const int N = 7;  
  
int length(int i);  
void Compress(int n,int p[],int s[],int l[],int b[]);  
void Tracebace(int n,int& i,int s[],int l[]);  
void Output(int s[],int l[],int b[],int n);  
  
intmain ()  
{  
    int p[] = { 0 , 10 , 12 , 15 , 255 , 1 , 2 }; // The subscript of the image grayscale array starts counting from 1   
    int s[N],l[N],b[N];  
  
    cout << " The grayscale sequence of the image is: " << endl;  
  
    for(int i=1;i<N;i++)  
    {  
        cout<<p[i]<<" ";  
    }  
    cout<<endl;  
  
    Compress(N-1,p,s,l,b);  
    Output(s,l,b,N-1);  
    return 0;  
}  
  
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]); // The number of storage bits required to calculate pixel p   
        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 ++]=nl[n]; // Reassign the s[] array to store the segment position   
}  
  
void Output(int s[],int l[],int b[],int n)  
{  
    // After outputting the s[n] storage bits, the s[] array is reassigned, and the location used to store the segment   
    cout<< " The minimum space after image compression is: " <<s[n]<< endl;  
     int m = 0 ;  
    Traceback(n,m,s,l);  
    s[m] = n;  
    cout << " divide the original grayscale sequence into " <<m<< " segment sequence segment " << endl;  
     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 << " Segment length: " <<l[j]<< " , required storage bits: " <<b[j]<< endl;  
    }  
}  

 

     The algorithm Compress requires only O(n) space. Since the number of cycles of j in the algorithm Compress is not more than 256, each determined i can be completed in O(1) time. So the time complexity of the whole algorithm is O(n). The execution process of the algorithm Compress can be represented as follows:

      In the method Output, after outputting the minimum storage space of s[n], the s[] array is reassigned to store the position of the segment, while backtracking to construct the optimal solution. The result of running the program is as follows:

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324583351&siteId=291194637