JPEG 编码过程:为 GPU 处理开路

图片平台上承接了巨量的图片每天需要针对几十亿的图像进行处理,由于JPEG格式是存储系统中存储最多图像格式,而JPEG格式编解码以及处理中都是大量的数据计算,GPU较于CPU具有更强大的数据并行计算的能力。于是研究利用GPU来加速处理图像编解码以及图像处理, 为此很有必要先了解JPEG的的编解码过程。

文章参考了大量外部资料,引用了相关的图片以及数据,所涉及到的内容或者原理都有相应的链接跳转以供查询。

JPEG的颜色模式

JPEG采用YCrCb的颜色模式,通常叫着YUV,其中Y代表亮度,Cr,cb代表色度和饱和度。而我们通常熟悉的计算机系统采用RGB颜色模式。从RGB颜色模式向YUV模式转换采用以下公式:

Y =  0.299R' + 0.587G' + 0.114B'
U = -0.147R' - 0.289G' + 0.436B'
V = 0.615R'  - 0.515G' - 0.100B'

为何JPEG采用YUV格式编码呢?是因为亮度变换的敏感度要比对色彩变换的敏感度高出很多。因此采用YUV颜色模式能够将图像不太重要的信息进行抽离出来。采用不同的采样比例来达到减少存储数据的目的。

经过上述颜色空间转换后,我们就能得到Y、U、V三个分量上的三张表。

采样

4:1:1采样为例,若在一个2x2的图像中。4:1:1采样即为:

Y:  SHY=2   SVY=2
U:  SHU=1   SVU=1
V:  SHV=1   SVV=1

若2x2的rgb转换为YUV后图像编码表示为:

[Y0 U0 V0] [Y1 U1 V1]
[Y2 U2 V2] [Y3 U3 V3]

那么经过4:1:1采样后

[Y0 U0 V2] [Y1 U0 V2] 
[Y2 U0 V2] [Y3 U0 V2]

数据存放为:

Y0 U0 Y1 Y2 V2 Y3

那么原图共占用12个字节,经过采样后仅需要6个字节。这里通过采样初步减少了图像大小。

分块

数据采样完成后就需要进行下一步操作,进行空间域向频率域转换DCT变换。在空间域里处理图像有困难,就转到频率域来进行处理。为了进行DCT变换需要对图像码流进行分块。从码流中分别提取Y、U、V三个分量构成三张表。

JPEG 进行DCT变换时需要8x8的block为单元。而最小编码单元MCU是水平方向和垂直方向上采样最大值与8x8的乘积。那么4:1:1采样的mcu大小为16x16。

图像边缘在不满8x8时需要进行补齐,采用不同的补齐方式将会产生不同的影响。如采用全黑色进行补齐将产生振铃效应,在边缘较为锐利的文字型图像中较为容易发现。通常采用重复边缘上的数据来进行填充。 其次是图像在进行DCT变换时高频分量的丢失或者精度损失也造成振铃效应。

振铃效应图像对比:

振铃效应影响的图片

IM处理的图像

DCT变换

这里有两张傅里叶变换的经典图像:

鉴于图像在8x8的范围内相对的连续性,DCT变换能够将能量集中于低频部分,而高频部分信息肉眼不敏感,这样就使得后续对DCT变换后的矩阵进行量化减少高频信息成为可能。

DCT变换的强大威力示例:

经过DCT变换后得到的8x8矩阵,其中(0,0)位置称为直流分量,其他63个元素称为交流分量。

量化

数据量化是针对DCT变换后得到的系数矩阵进行精度处理,使用DCT系数矩阵中的每一项分别于对应的量化矩阵位置处的值相除所得到的新矩阵为量化后的结果。JPEG分别针对Y亮度、UV色度和饱和度提供两张不同的量化表。因为人眼对亮度相对于色度更加敏感,所以亮度量化表精度较色度量化表更加精细。

亮度量化表

色度量化表

而通常我们在进行JPEG质量调整时就是在量化表乘一个系数得到新的量化表。量化过程对于原图来说是一个有损的过程。这也就是JPEG实际图像质量无法超越原始图像的原因。

经过量化后的数据进一步缩小了数值范围,在右下角高频部分由于量化表系数较大很多图像在此部分形成了较多的0。而左上角低频部分保留了较多的肉眼敏感的数据。

一个8x8DCT变化后数据量化的示例:

针对量化后的数据需要从二维矩阵降维到一维的数组,方便进行数据编码。而由于矩阵呈现右下角数据更小更集中的趋势,在降维时采用了zigzag扫描算法。这样右下角的数据在一维空间中连续存放,有利于产生更多的0。对减少编码后图像大小提高压缩率有很好的帮助。

zigzag扫描过程:

上面数据经过zigzag扫描后行程这样的序列

数据编码

经过zigzag扫描后的数据进行横向排布后得到这样的序列:

-26,-3,0,-3,-2,-6,2,-4,1,-3,1,0,5,1,2,-1,1,-1,2,0,0,0,0,0,-1,-1,0,0,0...,0

数据分为两部分,第一个数值为DC直流分量,对直流分量采用DPCM编码,因为该值通常较大,而相邻的8x8图像数据之间的差值变化不大。

针对AC系数序列进行RLE游程编码。是因为经过zigzag扫描后产生许多连续的0,RLE编码能够大幅减少0数据的空间占位。

再使用标准的huffman表对DC和AC编码后的数据进行huffman编码得到二进制序列。而使用huffman表编码时,针对DC直流分量和AC交流分量分别采用不同的huffman表。对YUV各个通道的编码也将采用不同的编码表。

欲了解上述数据如何进行RLE编码,再进行huffman编码可参考这篇文章JPEG算法解密(四),该文章详细的描述了游程编码过程以及从游程编码的结果进行huffman编码得到相应的存储二进制数据流。

数据编码完成后把用到的DHT表,huffman表以及其他一些数据信息,按规定格式写入到数据的头部。和编码后的数据合并起来就产生了一个JPEG文件。jpeg头部写入的huffman表。写入的是码字数量和编码内容,在解码时需要根据各个长度的码字数量结合编码内容来建立huffman树对数据进行解码。

GPU并行性考量

上述过程中DCT变换过程,数据量化过程以及后续的huffman数据编码过程都是以MCU为单位,这些过程应该都能够进行并行化处理。来获取一定的处理加速。

后续将分析图像缩放以及解码过程,考虑通过并行化以获取加速的可能。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏AI启蒙研究院

【通俗理解】协方差

822
来自专栏一心无二用,本人只专注于基础图像算法的实现与优化。

图像纹理合成及纹理传输算法学习(附源码)。

    有2到3年没有逛CodeProject了,上班一时无聊,就翻翻这个比较有名的国外网站,在其Articles » Multimedia » General...

3048
来自专栏Petrichor的专栏

论文阅读: Soft-NMS

传统的NMS (Non-Maximum Supression)去重过程如下:

1772
来自专栏用户3246163的专栏

2.4 估值和模拟

Exponentially weighted moving average(指数加权移动平均)

1243
来自专栏ATYUN订阅号

使用TensorFlow和DLTK进行生物医学图像分析的介绍

DLTK是用于医学图像的深度学习工具包,它扩展了TensorFlow, 以实现生物医学图像的深度学习。它为经典的应用程序提供特殊的操作和功能、模型的实现、教程(...

1754
来自专栏机器学习算法与Python学习

GitHub最受欢迎深度学习应用项目 Top 5

1 Neural Style Star:12122 Github:https://github.com/jcjohnson/neural-style 这个项目是...

43212
来自专栏云时之间

什么是LSTM

哈喽,大家好,上一次我们了解了什么是卷积神经网络RNN,然后我又加上了我翻译的那一篇文章来简述了一下RNN和LSTM,今天,让我们来详细的了解下什么是LSTM。...

3236
来自专栏AI研习社

决策树:一种像人脑一样工作的算法

决策树是用于机器学习最流行的算法之一,尤其对于分类和回归问题。我们每次做决策时大脑都像决策树一样工作。

1123
来自专栏AI研习社

基于 Tensorflow eager 的文本生成,注意力,图像注释的完整代码

我总是发现生成和序列模型令人着迷:他们提出的问题与我们刚开始学习机器学习时常遇到的问题不同。当我第一次开始学习ML时,我学了分类和回归(和大多数人一样)。这些帮...

1182
来自专栏小小挖掘机

windows下使用word2vec训练维基百科中文语料全攻略!(三)

训练一个聊天机器人的很重要的一步是词向量训练,无论是生成式聊天机器人还是检索式聊天机器人,都需要将文字转化为词向量,时下最火的词向量训练模型是word2vec,...

3515

扫码关注云+社区