1.1 变换编码

视频编码中最重要的编码工具之一是变换编码,变换编码是指把视频内容从一个域变换到另外一个域,从而实现能量的集中。变换后,同样的内容往往可以用更少的比特来表示。

在视频编码中,变换一般是放在最前面的,后面接着量化和熵编码,它们的关系如图13所示。

13分块、变换、量化、熵编码关系图

先把图像分成n×n的小块,一般是8×8的小块,对每个小块做离散余弦变换(Discrete Cosine Transform,简称DCT),然后对DCT后的值做量化,最后编码这些量化后的值。

什么是从一个域变换到另外一个域呢?可以这样来理解,举个简单的例子:在图14中,平面中有2个向量

14 域变换示意图1

如果把坐标轴旋转90度变成(1,1)和(-1,1)方向,那么这两个向量的值就变成了(1,0)和(0,1),如图15所示。

15 域变换示意图2

可见,针对内容,找到合适的坐标轴(也可以叫坐标基向量,简称坐标基),可以大大节省表示内容所需要的比特。这种坐标基的改变,就可以理解为从一个域变换到另一个域。

学过数字信号处理的读者都知道,离散傅里叶变换可以把时域上的离散信号变换到频域,用各个频率的分量的和来表示,如公式(1.1)所示:

同样,在视频编码中,用2维离散余弦变换,可以把一个视频空间信号用各个频域的分量和来表示。DCT的本质可以理解为坐标基的改变,把原来的(1,0,0,..,0),(0,1,0,...,0) . . . (0,0,...,0,1)坐标基向量表示的内容用DCT坐标基向量来表示。可以用以下代码生成DCT基向量和图像:

def makeDCT(N):

    C = np.zeros((N,N))

    C[0,:]=1*np.sqrt(1/N)

    for i in range(1,N):

        for j in range(N):

            C[i,j]=np.sqrt(2/N)*np.cos(np.pi*i*(2*j+1)/(2*N))

    for i in range(N):

        plt.subplot(N//4,N//(N//4),i+1)

        plt.plot(range(N),C[i,:])

    plt.show()

    return C

N=8时,DCT的8个坐标基向量的图像如图16所示。

16 DCT坐标基向量图像

为什么可以称这8个向量为基向量呢?因为它们都是单位向量,并且互相正交。

图17是2维DCT向量的示意图,所谓“2维”,一般是先对每一行做一次DCT,再对每一列做一次DCT。

17 2维DCT向量的示意图

对8×8的块做二维DCT,可以理解为用这个块与图17中的每一个块做内积。计算出的值越大,说明当前块与此基向量的相似度越大。

所以,对图像做DCT的过程,一般被称为从空间域到频率域(或者DCT域)的变换。这种变换有三个好处:

  1. 对于自然图像,DCT后的频域值,靠近左上角的值较大(低频系数),靠近右下角的值较小(高频系数)。能量主要集中在低频区域。
  2. 由于人眼对高频区域信号不敏感,所以高频信号可以使用更低的精度保存。
  3. DCT后的频域值,通过使用DCT的逆运算IDCT,可以复原出原始的空间域的图像。

有兴趣的读者可以从K-L变换(Karhunen-Loeve Transform)的角度研究DCT的适用性。

图18和图19展示了对一幅灰度图像做DCT的过程,变换后的频域图像见图110。

图18 原始灰度图像

把图像分成8×8的小块,见图19。

图19 分块后的灰度图像

对每个小块分别做DCT,然后把每个块的值归一化到区间[0,255],用灰度图的方式显示,结果如图110所示。

图110 DCT域图像

图110中,值越大就越白,值越小就越黑。所有的8×8的小块的左上角都是最白的,在大部分块中,白色区域在第一行,第一列或左上角。很多块除了左上角,其他地方几乎是全黑的。

这种把图像分成8×8的块,每块做DCT的方式,被早期的图像编码标准JPEGJoint Photographic Experts Group)和视频编码标准H263、MPEG2、MPEG4所使用。

除了DCT,随着视频编码技术的发展,其他的变换方法也被引入。例如:H265中引入了离散正弦变换(Discrete Sine Transform,DST)。DST变换系数的公式如(1.2)所示:

以下代码可以生成N=4的DST基向量(简称DST4)和图像:

def makeDST(N):

    C = np.zeros((N,N))

    for i in range(N):

        for j in range(N):

            C[i,j]=np.sqrt(4/(2*N+1))*np.sin(np.pi*(2*i+1)*(j+1)/(2*N+1))

    if True:

        for i in range(N):

            plt.subplot(N//4,N//(N//4),i+1)

            plt.plot(range(N),C[i,:])

        plt.show()

    return C

输出图像如图111所示。

图111 DST4基向量示意图

用DST变换矩阵乘自己的转置矩阵可以得到单位矩阵,因此, DST和DCT一样,行向量都是单位向量并相互正交。在H265中,当帧内块预测使用水平或垂直预测模式时,对预测残差使用DST变换。

H265中使用的这个DST变换有一个小的问题,就是它不能像DCT一样做蝶形分解。因为它的变换系数公式中的分母为2N+1,无法分解,也就不能做快速算法。对4×4的小块,因为有单指令多数据(Single Instruction Multiple DataSIMD)的加持,蝶形分解的快速运算的优势没有那么明显,但是对8×8或16×16甚至更大的块,直接运算的劣势就非常明显了。

于是,在AV1标准中,在DST的基础上,引入了非对称离散正弦变换( Asymmetric Discrete Sine TransformADST)和翻转非对称离散正弦变换(FLIPADST)。ADST的变换系数公式如(1.3)所示:

N=8时,ADST的基向量(简称ADST8)图像如图112所示。

图112 ASDT8基向量示意图

ADST的优点就是它可以做蝶形分解快速运算,因此,可以应用在较大的块上。

另外,AV1除了有DCTADST和FLIPADST外,还有一种变换:恒等变换(Identity TransformIDTX),也就是不做任何变换。因为在实际编码中,有的块在空间上并不平稳,做了变换还不如不做变换。

基于块的变换编码对局域相关性很大的平稳区域,有很好的压缩性能,对自然图像具有编解码速度快,压缩性能高的特点。在近50年的视频编码的发展过程中,基于块的变换编码一直占据着主流位置。JPEG2000是一个很少的例外,它使用小波变换,不再使用固定的分块,彻底摒弃了基于块的离散傅里叶(Discrete Fourier TransformDFT)家族的变换。而且天生地支持分层编码,渐进传输,但该编码到现在也没有普及。

DFT家族的变换在音频编码中也同样重要,音乐压缩格式MP3,使用了时域重叠的DCT(MP3标准中称为MDCT)。具有更高压缩效率的AAC格式,使用了DFT。因为对声音,DFT变换同样有着集中能量的作用,再加上人耳在频率上的掩蔽效应,时频转换的意义就更大了。

DCT可以把能量聚集起来,但也有不适用DCT的情况,如图113所示。

图113 DCT不适用的情况

图113中,左图右上角黑色、左下角白色的像素块在进行DCT后,却变得更加复杂,能量也更加分散。因为自然图像大多是渐变的,没有这种锋利的边缘,所以对于自然图像来说,DCT大多是适用的。对左边这种像素块,有方向的帧内预测是很好的解决办法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值