你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:技术专栏 / Linux开发
比特平面编码用于图像压缩的程序设计
 

    本文介绍了如何把比特平面编码用于图像压缩,并编写了具体程序实现读取图片,生成压缩文件,解压缩,重建图像等功能。

关键词  无损压缩,比特平面编码,嵌入特性,格雷码,图像压缩

一、 概述

人类所获取的外界知识中约有80%以上的信息来自于视觉,很多情况下图像所承载的信息比任何其它形式的信息都更真切,更丰富,获取也更便捷。一幅实用的数字图像的数据量是巨大的,这给图像的传输和存储带来相当大的困难。在保证一定的图像质量和满足任务要求条件下,减少原始图像数据量的处理过程也就是图像压缩是非常关键的一个步骤。

在无损压缩算法中,一种有效的减少像素间冗余的技术就是单独处理图像的位平面,这种技术被称为位平面编码。它是以将一幅多级图像分解为一系列二值图像并对每幅二值图像进行压缩的原理为基础的。该算法应用也比较广泛,在JPEG2000中,把量化后的系数组织成二进制位平面,从最高有效位平面开始,依次对每个位平面上的小波系数位进行编码。该编码算法的输出是按数据对重建图像质量的重要性排列的,因此可以按一定的压缩比在任意时刻截断输出码流,而获得当时条件下可能获得的最好质量,具有良好的灵活性和可分级性,这就是所说的嵌入特性,可用于渐进图像传输。以lena图像为例,保留第7位比特平面重建后的图像,和保留第76位比特平面重建后的图像分别如图1,图2所示。

二、 算法简介

灰度图像的每个像素值为8比特,可以表示为以2为基底的多项式,即

   (1)

基于这一性质,将多值图像分解为一个二值图像序列的简单方法是将式(1)中多项式8个系数分成8个一比特的平面。因此,一幅灰度图像可以如此变换成8幅二值图像,每幅二值图像成为一个比特平面。第i个比特平面由所有像素的第i个比特组成(i=0,1,7)。由多值图像分解成一组比特平面,这种变换是可逆的,即由这组比特平面可以完全重建原始的多值图像。

每一比特平面可以分成若干个p×q个像素大小的块。比特平面经过划分,出现三种不同结构的块,即全0块,全1块,以及01混合的块。统计表明,前两种结构的块最常出现。一种编码做法是比较全0块和全1块出现的概率,对出现概率高的分配一比特码字0,对另一个分配二比特码字11,对混合块分配10作前缀码,其后跟pq比特,表示该块的具体图案。

若以p(0)表示全0块出现的概率,以p(1)表示全1块出现的概率,则混合块出现的概率为1-p(0)-p(1),这个编码方案的压缩比为

    (2)

图像相邻的灰度值具有很强的相关性,所以高比特位具有大量的全0块和全1块。相邻像素间的较小差别主要体现在低比特位上,混合块出现的概率较高,对编码效率有一定的影响。

但是,有时像素值的一个微小改变会对比特平面的复杂程度造成重大影响。当像素值127(01111111)128(10000000)相邻,全部8个比特平面都会出现从01的转变,从而在所有比特平面都破坏了全0块或全1块的出现,降低了编码效率。为了解决这一问题,我们引进格雷码,其突出特点为代表相邻两个数值的码字只有1位发生转变。比如127128的格雷码分别为1100000001000000,只有第七比特平面含有从01的转变,增大了全0块全1块出现的概率,有利于编码效率的提高。

本文将通过一个“图像比特平面编码程序的具体实例讨论如何利用VC++实现图像读取、比特平面编码、生成压缩文件、解码和重建图像的功能。具体开发环境:Windows XP, Microsoft Visual C++ 6.0

二、 程序实现与分析

 1.打开图像,将灰度值存入图像数组,并显示(本文中代码省略)。

 2.将图像各个像素灰度值转换为格雷码,并存入代表8个比特平面的数组。

相应于(1)中的多项式,8比特的格雷码可由下式得到。

  (3)

for(i=0;i<lx*ly;i++)

{

   //ip中存储各像素灰度值

   a=(int)ip[i];

   b=a/2;

   //当前像素对应的格雷码

   GrayCode=a^b;

   //把格雷码存入8个比特平面对应的数组

   for(j=0;j<8;j++)

   {

   iip[j][i]=GrayCode%2;

   GrayCode/=2;

   }

}

3.对各个比特平面进行扫描,取p=q=4,各比特平面中p*q小块如果为全0块,开头一位放2,如果为全1块,开头一位放3,而混合块开头一位是01,编码时可以相区别。同时统计全0块和全1块出现的次数,返回01,编码时可以区别处理。下面为进行扫描的函数。

int scan()

{

   int zero,one,i,j,z,k,binary,sign;

   zero=one=0;

   for(i=0;i<(ly/p);i++)

   {

   for(j=0;j<(lx/q);j++)

      {

        binary=iip[I][i*p*lx+j*q]; sign=0;

        //判断是否为混合块,一旦有不相等的数值,跳出循环

        for(z=0;z<p;z++)

        {

           for(k=0;k<q;k++)

              {

                  if(binary!=iip[I][(i*p+z)*lx+(j*q+k)])

                  {

                    sign=1;break;

                  }

              }

              if(sign==1) break;

          }

          //是全0块或全1

          if((z==p)&&(k==q))

          {

            if(binary==0)

            {

              zero++;//0计数加1

              iip[I][i*p*lx+j*q]=2;//0块标志

            }

            else

            {

              one++;//1计数加1

              iip[I][i*p*lx+j*q]=3;//1块标志

            }

          }

      }

  }

  if(one>zero) return 1;

  else return 0;

}

4.开始编码并写入文件。

编码从高位比特平面到低位比特平面进行。对于全0块或全1块,如果出现概率高,分配1比特码字0;如果出现概率低,分配2比特码字11。如果是混合块,先写入前缀码10,再写入该块具体图案。由于读写文件的最小单位是字节,而编码是不定长的,所以我们把每32位编码对应为一个unsigned int 型数据,依次把各个unsigned int 型数据写入文件。最后几位编码如果不够32位,我们把这几位编码的右端补0,凑够32位后写入文件。解码时,当所有位平面解码完成后,我们就不再继续向下读数据文件,所以上面右端补0的做法不影响解码的正确性。以下为编码并写入文件的程序。

//创建压缩文件

CFile MyFile1("D:\\test.dat",CFile::modeCreate|CFile::modeWrite);

nCode=nN=0;

//编码从高位比特平面到低位比特平面

for(i1=7;i1>=0;i1--)

{

  for(i=0;i<(ly/p);i++)

    {

      for(j=0;j<(lx/q);j++)

      {

        bi=iip[i1][i*p*lx+j*q];

        //该块为全0或全1块且出现的概率高,分配1比特码字0

        if(((bi==2)&&(c[i1]==0))||((bi==3)&&(c[i1]==1)))

        {

          nCode+=0;nN++;

          if(nN==32)

          {

            MyFile1.Write((void*)(&nCode),4);

            nN=0;nCode=0;

          }

          else

            nCode<<=1;

        }

        //该块为全0或全1块且出现的概率低,分配2比特码字11

        else if(((bi==2)&&(c[i1]==1))||((bi==3)&&(c[i1]==0)))

        {

          for(l=0;l<2;l++)

            {

              nCode+=1;

              nN++;

              if(nN==32)

              {

                MyFile1.Write((void*)(&nCode),4);

                nN=0;

                nCode=0;

              }

              else

                nCode<<=1;

          }

        }

        //混合块先写入前缀码10,再写入该块具体图案

        else

        {

          //写入10

          for(l=0;l<2;l++)

          {

            nCode+=(1-l);nN++;

            if(nN==32)

            {

              MyFile1.Write((void*)(&nCode),4);

              nN=0;nCode=0;

            }

            else

            nCode<<=1;

          }

          //写入该块具体图案

          for(z=0;z<p;z++)

          {

            for(k=0;k<q;k++)

            {

              nCode+=iip[i1][(i*p+z)*lx+j*q+k];nN++;

              if(nN==32)

              {

                MyFile1.Write((void*)(&nCode),4);

                nN=0;nCode=0;

              }

              else

              nCode<<=1;

            }//k

          }//z

        }//else

      }//j

    }//i

}//i1

MyFile1.Close();

5.由压缩文件解码,重建图像。

解码为编码的逆过程,以下为解码的程序。

CFile MyFile2("D:\\test.dat",CFile::modeRead);

while(1)

{

 MyFile2.Read((void*)(&nCode1),4);

 n1=31;

 //把编码拆入数组

  while(n1>=0)

  {

    st[n1--]=nCode1%2;nCode1/=2;

  }

  for(i=0;i<32;i++)

  {

    if(read==1)

    {

     oop[num][n++]=st[i];

      if(n==p*q)

      {

        n=0;num++;read=0;

        if(num==((lx/q)*(ly/p)))

        {

         trans();//一个比特平面解码完成,存入数组相应位置

         if(nu==-1)

         {

            sig=1;break;

         }

         else

         {

            num=0;s1=c[nu];s2=1-s1;

         }

        }

      }

    }

    else if(con==1)

    {

      if(st[i]==1)

        {

          oop[num++][0]=s2+2;

          if(num==((lx/q)*(ly/p)))

          {

            trans();//一个比特平面解码完成,存入数组相应位置

            if(nu==-1)

            {

             sig=1;break;

            }

            else

            {

             num=0;s1=c[nu];s2=1-s1;

            }

          }

        }

        else

        {

         read=1;

        }

        con=0;

    }

    else

    {

     if(st[i]==0)

     {

        oop[num++][0]=s1+2;

        if(num==((lx/q)*(ly/p)))

        {

         trans();//一个比特平面解码完成,存入数组相应位置

         if(nu==-1)

         {

            sig=1; break;

         }

         else

         {

            num=0;s1=c[nu];s2=1-s1;

         }

        }

    }

    else

     con=1;

    }

  }//i

  if(sig==1) break;

}

MyFile2.Close();

以下为解码过程中用到的一个转换函数,作用为把各个比特平面的数组全0块,全1块全部填入01,混合块填入具体图案。

void trans()

{

  int d1,d2,i,j,z,k;

  for(i=0;i<(ly/p);i++)

  {

   for(j=0;j<(lx/q);j++)

    {

     d1=oop[i*(lx/q)+j][0];

     //0块填入01

     if((d1==2)||(d1==3))

     {

       for(z=0;z<p;z++)

       {

         for(k=0;k<q;k++)

         {

            op[nu][(i*p+z)*lx+j*q+k]=d1-2;

         }

       }

     }

     //混合块填入具体图案

     else

     {

       for(z=0;z<p;z++)

       {

         for(k=0;k<q;k++)

         {

            d2=oop[i*(lx/q)+j][z*q+k];

            op[nu][(i*p+z)*lx+j*q+k]=d2;

         }

       }

     }

   }//j

  }//i

 nu--;

}

6.将格雷码转为二进制码,并存入图像数组。

相应于(1)中的多项式,8比特的二进制码可由下式得到。

       (4)

对应的程序如下。

for(i=0;i<lx*ly;i++)

{

  //转换为二进制

  nValue=nValue1=op[7][i];

  for(j=6;j>=0;j--)

  {

    nValue1=(op[j][i])^nValue1;

    nValue<<=1;

    nValue+=nValue1;

  }

  //存入图像数组

  op1[i]=nValue;

}

6.显示解码后图像(本文中代码省略)。

三、 结语

   256*256像素(64K)的几幅灰度图像进行测试,结果如下。

sun

tree

baboon

lena

cat

34.8K

53.4K

61.4K

50.4K

52.3K

  

512*512像素(256K)的几幅灰度图像进行测试,结果如下。

goldhill

lena

barbara

boat

baboon

207K

189K

212K

208K

243K

 

对于上述结果可以进一步处理。如果一个编码块中比特数值大部分为0,只有很少的1,利用人的视觉心理特性,可将该块视为全0块处理。此时视觉上可能感觉不到明显的失真而

予以接受。反之也可将1很多而0很少的块视为全1块处理。这种利用视觉心理特性的编码,尤其在低位的比特平面上使用,不会引起明显的可察觉失真(因其产生的客观失真量小),可收到较好效果。上述处理使全0块全1块出现的概率p(0)p(1)上升,从而提高压缩效率。

 

 



四、参考文献

[1]冈萨雷斯. 数字图像处理. 北京:电子工业出版社,2003

    [2]张春田,苏育挺,张静. 数字图像压缩编码. 北京:清华大学出版社,2006






 

  推荐精品文章

·2024年12月目录 
·2024年11月目录 
·2024年10月目录 
·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089