指数哥伦布编码

哥伦布编码前言

在计算机中,一般数字的编码都为二进制,但是由于以相等长度来记录不同数字,因此会出现很多的冗余信息,如下:

十进制

5

4

255

2

1

二进制

00000101

00000100

11111111

00000010

00000001

有效字节

3

3

8

2

1

如数字1,原本只需要1个bit就能表示的数据,如今需要8个bit来表示,那么其余7个bit就可以看做是冗余数据,

在网络传输时,如果以原本等长的编码方式来传输数据,则会出现很大的冗余量,加重网络负担,但是如果只用有效字节来传输上述码流,则会是:10110011111111101,这样根本不能分离出原本的数据,哥伦布编码则是作为一种压缩编码算法,能很有效地对原本的数据进行压缩,并且能很容易地把编码后的码流分离成码字。

哥伦布编码思想

一个码字的信息量,称之为熵,二进制上可用log2[n]来表示,也就是上面表格的有效字节,但是如果只是把有效码字串联起来,得到的只是一串无用的码流,因为这串码流中并没有描述单一码字的信息量,也就是无法对码流进行分离

哥伦布编码就采用了加0前缀,用于表达码字的信息量,在得到m个0前缀后,就能知道该码字在码流中的长度,并从码流中把码字分离出来

哥伦布编码概念

指数哥伦布(Exp-Golomb)编码是一种在音视频编码标准中经常采用的可变长编码方法,它是使用一定规则构造码字的变长编码模式。它将所有数字分为等大小不同的组,符号值较小的组分配的码长较短,同一组内符号长基本相等,并且组的大小呈指数增长。

指数哥伦布码的比特串分为“前缀”(prefix)和“后缀”(suffix)两个部分。它的逻辑结构为:

[Mzero][1][INFO]

编码后码长为2M + 1 + k,M为前缀长度,1为中间的1长度,M+k为后缀长度

 

K阶指数哥伦布码

  在H.264中,使用CABAC需要进行二值化处理,而指数哥伦布编码就是CABAC的一种二值化处理的方法。k阶指数哥伦布编解码具体过程如下:

A、编码过程:假设待编码数字为CodeNum(必须非负整数)

  指数哥伦布编码后的形式为[MZeors][1][Info],MZero表示M个0。

    1、将CodeNum以二进制形式表示(若不足k位,前面补0),去掉后面k位(若刚好是k位,去掉k位后得0),将结果(数值)加1,得到二进制数T1;

    2、M为二进制数T1的二进制位数减一;

    3、然后将第一步中舍去的k位接到T1结尾,就得到[1][Info]。

  设[Info]的二进制位数为I,编码过程也可以如下描述:

    [1 Info]是CodeNum+2^k的二进制表示,MZeros中0的个数M = I - k。

    于是就有总的编码长度CodeLen = M + 1 + I =2M+k+1。 

举例如下:

 对于 k =0时:CodeNum=3。编码如下:

    二进制表示为11,去掉k=0位后加1得100;

    所以M=2

    所以编码后结果为[MZeros][1][Info]= [MZeros][1 Info] = 00100

 

B、解码过程:

  1、读入连续0,连续0的个数就是M;

  2、计算CodeLen = 2M+k+1,得到[1 Info]的位数是 I=CodeLen - M =M+K+1;

  3、读入I位二进制码字,转换成10进制,假设为W。由W = CodeNum + 2^k,得CodeNum = W-2^K。

举例如下: 

  解码00100,读入连续2个0,所以M=2;CodeLen=2M+1+k=5;所以需要再读入3个码流100,[1 Info]就是100,转成十进制结果W为4,所以CodeNum =W-2^K=4-1=3;

  同样对于k=0,CodeNum=6时,编码为:00111;

  同样对于k=3,CodeNum=3时,编码为:1011;

  同样对于k=3,CodeNum=6时,编码为:1110;

  同样对于k=3,CodeNum=10时,编码为:010010;

一般来说,根据码字出现的概率调整哥伦布编码的阶数K,

如果是码字0出现的概率较大,那么应该用K = 0,即0阶指数哥伦布编码

如果码字0与1出现的概率都比较大,那么应该用K= 1,以此类推

在H.264中用的是K = 0

例子2:

下面分别介绍:

u(1) :为一个字节取出前1位

ue(v) 为无符号指数哥伦布熵编码

编码过程如下:

对 4 进行无符号指数哥伦布熵编码
1、将4加1(为5)转换为最小的二进制序列即 101 (此是M=3)
2、此二进制序列前面补充M-1即两个0

3、得出的4的无符号指数哥伦布熵编码的序列为 00101

解码过程如下:

如对 00101进行无符号指数哥伦布熵解码
1、获取开头连续的N个0, 此时N = 2
2、再向后读取N+1位的值,即 101,为5

3、 5 - 1 =4 获取其解码后码值

se(v) 为有符号指数哥伦布熵编码

编码过程如下:

如对4进行有符号指数哥伦布熵编码
1、4的绝对值转为最小二进制序列,即 100 (此时M = 3)
2、后面补充符号位,0 即 1000

3、前面补充M个0, 即 0001000

解码过程如下:

如对二进制序列 0001000 进行有符号指数哥伦布熵解码
1、获取开头连续的N个0, 此时N = 3
2、再获取N为数值,即 100 即为4
3、获取最后的符号位,0,即为正值

4、故此序列解码后的码值为4
示例二:

编码

如对-15进行有符号指数哥伦布熵编码
1、-7的绝对值转为最小二进制序列,即 1111 (此时M = 4)
2、后面补充符号位,1,即 11111

3、前面补充M个0,即 000011111

解码:

如对二进制序列 000011111 进行有符号指数哥伦布熵解码
1、获取开头连续的N个0, 此时N = 4
2、再获取N为数值,即 1111 即为15
3、获取最后的符号位,1,即为负值
4、故此序列解码后的码值为-15
 

解码代码:

UINT Ue(BYTE *pBuff,UINT nLen, UINT&nStartBit)

{

     //计算bit的个数

     UINT nZeroNum =0;

     while (nStartBit<nLen * 8)

     {

         if (pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8)))//&:按位与,%取余

         {

              break;

         }

         nZeroNum++;

         nStartBit++;

     }

     nStartBit++;

     //计算结果

     DWORD dwRet =0;

     for (UINTi=0; i<nZeroNum;i++)

     {

         dwRet <<= 1;

         if (pBuff[nStartBit / 8] & (0x80 >> (nStartBit % 8)))

         {

              dwRet += 1;

         }

         nStartBit++;

     }

     return (1 << nZeroNum)- 1 + dwRet;     //W-2^K

}

 

int Se(BYTE *pBuff,UINT nLen, UINT&nStartBit)

{

     int UeVal=Ue(pBuff,nLen,nStartBit);

     return UeVal&1?(UeVal+1)/2:-(UeVal/2);

}

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值