写点什么

veImageX 演进之路:HEIF 图片编码压缩与优化

  • 2022-11-08
    北京
  • 本文字数:4764 字

    阅读完需:约 16 分钟

veImageX演进之路:HEIF图片编码压缩与优化

字节跳动在公司成立之初就建设了图像处理平台,起初主要服务于今日头条 APP 的图文资源。随着业务扩展,逐步开始服务抖音图集、短视频封面、图虫等几乎用户能看到的所有图片展示场景。火山引擎视频云团队将字节跳动图像处理的实践,整理为《veImageX 演进之路》系列,将从产品应用、后端技术、前端技术、算法、客户端 SDK,详细解读字节跳动背后的图像技术。


veImageX 是火山引擎基于字节跳动内部服务实践,推出的图像一站式解决方案 ,覆盖上传、存储、处理、分发、展示、质量监控全链路应用。

前言

压缩技术对于图像、视频应用十分重要。在保证同样主观质量的前提下,如何将图像压缩到更小体积便于互联网信息传输,火山引擎视频云团队便在不断突破压缩技术“天花板”。


目前互联网任何应用、网站网页都离不开加载图像。HEIF 是一种图像处理领域高效编码压缩的图片格式,在节省成本和画质平衡角度,一直备受广大用户青睐。图片格式从最早期的 JPEG、无损压缩 PNG、压缩效率较高的 WEBP,到追求更高压缩效率的 HEIF、AVIF,都在各个场景有着广泛的应用。相比其他几种图片格式,HEIF 格式提供了较多的灵活性,可以支持更多的图片特性,比如透明通道、深度图、缩略图等辅助图像信息,也可以在不破坏原有图像的情况下进行图像编辑、裁剪、旋转、图形叠加。除此之外,HEIF 容器支持封装多张图片序列动画,结合不同的编码压缩方式可以达到很高的压缩效率。高压缩率能够有效节省传输成本,提高加速速度,提升用户体验。

HEIF 图片

HEIF 是基于公开的国际标准 ISO standard 定义的图片文件格式,它是一种封装容器,文件中除了必要的文件信息,还可以添加各种图像编辑信息。因为和编码方式相互独立,所以在编码器的选择上更加灵活,可以根据实际需求适配。字节跳动使用的自研 BVC 编码器,在压缩效率和编码速度上优势明显。目前已经覆盖了超过 50% 的业务场景,取得了不错的业务收益。

HEIF 封装格式

HEIF 图片格式组成如下图,它由若干个 box 组成,文件属性和数据都存储在 box 结构中,对于静态图来说,必须包含的主要 box 类型有 ftyp、meta、mdat:

● ftyp(file type)描述了文件封装的类型,比如 heic、heix、hevc 等

● meta box 是媒体信息的描述,指明文件中子 box 的相互关联关系、编码流在文件中的相对位置、色彩信息和其他图像属性信息,其中包括但不限于以下几种,可以根据业务需要添加自定义信息。

○ 图像基础信息:宽高、相对比例、解码器配置等;

○ 色彩信息(colr):包括 ICC profile、NCLX 等类型的色彩信息,使得图像在显示设备上正确的渲染;

○ 裁剪区域(crop):自定义显示区域,在解封装后可根据区域裁剪最终显示的图像;

○ 图像旋转(irot):0、90、180 或 270 度;

○ 图像镜像(imir):自定义图像是否镜像显示。

● mdat box 中存储了各种类型的编码压缩数据,主流的编码器有 H.264、H.265、AV1 等,字节采用的是内部自研的 BVC CPU+FPGA 方案。输出的码流主要包含:

○ master image:完整可显示的主体图像;

○ thumbnails:缩略图,一般用于快速预览,渐进式加载等场景;

○ Auxillary:辅助图,例如透明通道或者深度信息等;

○ Derived:最终导出的图,可自定义显示效果 ;

○ Equivalent:可选图,可用作最终显示的素材。


HEIF 封装格式

veImageX 基于 HEIF 特性和算法优化

HEIF 因其灵活高效的封装和编码方式,使得特性支持上更加便利。目前字节 HEIF 中已支持的功能有:



HEIF 缩略图的应用

HEIF 特性在业务场景中的应用 以缩略图为例说明。HEIF 缩略图是在原图的基础上封装了一个较小尺寸的图像以用作快速预览等场景。目前字节已经用 HEIF 缩略图实现了图片渐进加载的功能。该功能主要体现在用户可感知耗时的优化,提升用户体验。例如:在用户网络状况不佳时,加载完缩略图后,及时显示缩略图,图片加载完成后再显示原图。预览的渐进式效果如下,用户先看到图片整体轮廓的模糊效果,直到图片完全加载出来。


HEIF 分块编码

HEIF 文件可以封装图片序列,考虑到大图的并行处理,内存消耗、裁剪等方面的性能,使用 Tile 编码可以有效优化以上问题。另外业务中也存在一些超长大图,分辨率超过手机厂商支持范围,导致系统接口解码显示异常等情况,可以使用 Tile 编码解决此类问题。


Tile 编码是将一张较大的原图按照一定的尺寸分成若干个小块,分别对小块进行独立编码,再对编码数据进行一定规则的封装,在解码端解码后按照原规则拼接成大图,将冗余数据裁剪到原图分辨率进行显示。

● 编码:把大图分成若干个 Tile,宽高设置相同,一般移动端设备编码的 Tile 大小设置为 512x512;每个 Tile 单独编码,输出 Tile 压缩后数据进行后续封装。

● 封装:封装层需要增加 grid infe 和每个 Tile 单独对应一个 infe; 增加 iref->dimg 索引; 增加 idat 存放 grid 信息; iloc 记录 Tile 文件的偏移信息; grid 的 ispe 存放实际宽高。



Tile 示意图

自适应调整 Tile 尺寸

Tile 编码方案解决上述问题的同时也带来了文件体积的增长,主要由于:

● Tile 编码区域大于原图宽高,一般固定 Tile 尺寸后,最后一行或一列不足 512 的会 Padding,存在一部分冗余数据;

● 分块编码效率问题 ;

● 封装格式中需要记录的信息增多,导致文件大小增长。


经过测试,固定 512x512 的 Tile 尺寸 Grid 编码后比正常编码文件大小平均增加 22.40%,文件大小增长主要是冗余数据编码引入。


为了优化这部分体积,设计了自适应的 Tile 尺寸方案,根据原图分辨率自适应划分 Tile 大小。自适应方案测试后,相比正常编码的文件体积平均增加 1.91%,避免冗余浪费。



HEIF 图片 ROI 编码

在图片实际应用中,人眼对于一张图片每个区域的关注程度不同。比如人脸、文字、图像中心区域等等往往是人眼关注的重点,而对天空、草地、图像背景区域的画质要求次之。针对人眼视觉特性,HEIF 图片增加了显著性检测和基于检测区域的编码压缩,结合显著性检测对用户感兴趣区域进行画质提升,保证码率平稳的情况下提升用户感官体验。


ROI(Region Of Interest)编码是基于显著性区域进行优化的编码压缩方式,即对于图像中识别到的感兴趣区域和非感兴趣区域在编码算法上进行优化,提高 ROI 区域质量,降低量化参数程度,增加比特数分配;对于非 ROI 区域,在保证主观画质的情况下,减少比特数分配。


一张图片需要 ROI 编码时,先经过 ROI 检测算法,识别到图片中的显著性区域(一般不超过 10 个区域),将 ROI 坐标区域按照一定的规则封装后传到编码器内部。编码器根据区域重新分配各个区域的比特数,在保证主观画质的基础上,提升 ROI 区域画质。算法最终经过专家测评和盲测,画质满足需求,已经应用到实际业务中。


ROI 编码部分流程图

HEIF 编码压缩技术

目前图像处理为了满足低存储成本,同时满足多种分辨率、样式等适配问题。一般情况下需要实时或者准实时处理,HEIF 格式使用字节自研的 BVC 编码器,初期 CPU 计算方案成本较高,同时在体验层面图像压缩编码耗时也相对较高。为了减少链路的耗时,火山引擎推出了节省计算成本的 FPGA 异构方案。结合 FPGA 和 CPU 编码的优势,ImageX 在 HEIF 编码方案上设计了 FPGA+CPU 方案,FPGA 方案提供了高速的压缩编码体验。由于 FPGA 的硬件方面限制,需要 CPU 方案兼容和适配其他限制外使用场景。CPU 提供了高效的编码压缩体验,可以选择不同的画质档位,根据业务需求选择合适的编码参数。编码器正在持续的升级优化,希望提供更好的压缩性能和编码速度。


FPGA&CPU 编码调用流程


FPGA-based HEIF 编码方案

HEIF 编码在提升压缩率的同时,因其复杂度高,也需要消耗更多 CPU 计算资源。为了降低 HEIF 格式的编码计算成本,ImageX 采用了 FPGA 异构架构,整体成本约为 CPU 方案的 10%。

● 在性能方面,单台 FPGA server 的处理能力是 CPU server 的 15+倍,编码延时方面,FPGA 方案不到 CPU 的十分之一。由于 FPGA 方案的延时大大降低,在所有分辨率的图片上都可以使用同步处理,避免了 CPU 方案对大分辨异步处理而降级的情况,从而节省回源带宽和用户感知延时

● 在编码效率上,FPGA 编码效率和 CPU 方案的常用档位基本持平,可以在高速编码的同时,得到高效的编码质量。


HEIF 压缩性能对比

HEIF vs. WEBP

选取一定数量的图片针对 WEBP 和 HEIF 图片测试,在相同画质下 HEIF 动静图相比 WEBP 码率节省约 50%。HEIF 能够在对齐主客观画质的情况下,可以节省更多的文件体积。整体对比效果如下所示:




图片内容简单、平坦区域较多的场景,WEBP 有较多的块效应、色带等失真,HEIF 图片可以保持更好的画质、压缩失真较少、清晰度更高。


WEBP 12k vs. HEIF 7k

对于复杂图像,HEIF 图片纹理细节保留较多,边缘清晰,无明显毛刺;原图色彩还原度好,无明显色偏。


WEBP 60k vs. HEIF 39k


src vs. WEBP 67k vs. HEIF 38k

HEIF vs. AVIF

经过测试对比得出如下数据,在客观指标相同或稍高时,HEIF 相比 AVIF 快速档位有约 10%的体积节省。



HEIF 自适应

为了满足用户图片清晰度需求,图片的体积也随之提升,消耗的带宽也越来越大。如何在有限的网络带宽下,兼顾画质和体积对于提升用户的画质体验就显得尤为重要。基于以上考虑,团队设计了图片自适应算法策略,在主观画质保持不变的基础上,节省了带宽成本。

算法介绍

互联网中图片内容丰富多样,固定的编码参数并不能灵活的对不同种类内容提供适合的画质体验。自适应算法基于图片内容的统计特性,针对不同类型图片制定参数自适应调整策略。


首先,选择合适数量的测试图片数据集,分析图片的基本信息,文件格式、宽高、文件大小、有参/无参画质、指标用户模版配置等,统计线上图片目前的画质情况,制定合适的基准作为后续调整策略的参照;其次,由于线上图片格式种类较多,自适应算法选择统一的预编码方式,获取预编码后的特征作为模型输入,针对图片编码难易程度、分辨率等对图片进行统计分类,得到图片的分类信息;最后,对每个分类的图片进行 RD 曲线预测,根据当前用户配置期望确定质量阈值,该阈值根据预编码阶段的特征自适应调整。


在调整过程中,质量较低的图片需要提升质量参数,质量达标并高于预期时,则在主观画质不变的基础上,减小文件体积。从效果上看,自适应算法调整后,图片画质有提升,质量相对稳定,失真严重的图片减少,用户画质体验提升的同时,可以节省带宽成本。



码率节省

随机选取 5000 张图片,测试自适应的码率节省,相比固定编码参数的图片大小,自适应约节省 10%的体积,当然在火山引擎的 veImageX 设计中 JPEG、WEBP 等其他格式也可以应用该算法。



主观效果



HEIF 234k vs. Adaptive HEIF 174k


HEIF 30k vs. Adaptive HEIF 22k



HEIF 42k vs. Adaptive HEIF 29k

HEIF 解码

HEIF 格式因其高效的压缩效率,优质的画质体验和丰富灵活的图像内容备受关注,之所以没有普及使用主要是终端的兼容性问题。近年来越来越多的设备厂商支持了系统 HEIF 解码,推动 HEIF 生态的完善,但还是有较多场景不支持 HEIF 的解码渲染。因此,火山引擎设计了客户端的 HEIF 解码方案,采用自研的 BVC 解码器,解码速度较开源方案有较大程度的优化,解决了各端系统兼容问题。图片 SDK 根据机型做了系统和自研解码的适配,保证机型性能的同时提升用户流畅的观看体验。此外,图片 SDK 还提供了图片访问指标上报能力,可以在 veImageX 控制台方便查看相关图片业务指标,对业务实验、问题定位等提供了便利的手段。



小结

HEIF 图片在高效的编码压缩算法基础上叠加了一系列算法优化策略,以更低的成本得到优质的图片质量。火山引擎希望通过不断的探索和持续优化算法策略,为用户带来更惊喜的图片画质体验。同时,火山引擎也期望通过图像压缩技术降低企业用户的互联网传输带宽,提升用户加载体验,加快互联网传输速度,协同对整个社会产生价值。


目前以上编解码算法的优化已经集成到火山引擎 veImageX 产品中,点击阅读原文了解更多。

https://www.volcengine.com/products/imagex/?utm_source=wechat&utm_medium=article&utm_term=wx_readmore&utm_campaign=20221027&utm_content=imagex


作者简介:

李蒙蒙, 火山引擎视频云 veImageX 核心图像算法工程师。

张锡平,火山引擎视频云 veImageX 产品负责人。

2022-11-08 13:4710233

评论

发布
暂无评论
发现更多内容

Flutter开发中的一些Tips(二)

android 程序员 移动开发

Fragment的使用

android 程序员 移动开发

git 补丁 - diff 和 patch 使用详解(1)

android 程序员 移动开发

Google Pay支付遇到的问题

android 程序员 移动开发

Flutter集成高德定位和地图功能

android 程序员 移动开发

GridLayoutManager这么用,你可能还真没尝试过

android 程序员 移动开发

Gson用户指南

android 程序员 移动开发

HashMap及HashTable源码解析

android 程序员 移动开发

Flutter动画:用Flutter来实现一个拍手动画

android 程序员 移动开发

Flutter填坑全面总结(包括Flutter1

android 程序员 移动开发

HashMap源码分析 —— 一篇文章搞定HashMap面试

android 程序员 移动开发

Flutter开发之——运行卡在gradle assembleDebug

android 程序员 移动开发

Fragment add与replace的区别(1)(1)

android 程序员 移动开发

GC 回收机制与分代回收策略

android 程序员 移动开发

Flutter与Dart-入门

android 程序员 移动开发

Flutter:基于video_player实现视频相关手势控制、全屏播放

android 程序员 移动开发

google vr 入门之制作简易的VR播放器(二)

android 程序员 移动开发

Fragment极度懒加载-+-Layout子线程预加载,奇妙的APP启动速度优化思路

android 程序员 移动开发

Github TOP100 Android开源

android 程序员 移动开发

Github标星3-2K-2020BATJ数据结构与算法笔试题及其答案吐血整理!

android 程序员 移动开发

Glide的简单封装GlideUtils

android 程序员 移动开发

Flutter的原理及美团的实践(中)

android 程序员 移动开发

Flutter如何实现下拉刷新和上拉加载更多

android 程序员 移动开发

Flutter实战1 --- 写一个天气查询的APP

android 程序员 移动开发

Flutter开发之——Menu

android 程序员 移动开发

Flutter开发之——事件监听

android 程序员 移动开发

Flutter教程(二) 了解Dart语言

android 程序员 移动开发

Flutter如何实现下拉刷新和上拉加载更多(1)

android 程序员 移动开发

Flutter版-WanAndroid-App

android 程序员 移动开发

Flutter状态管理--Getx学习2

android 程序员 移动开发

Flutter绘制-11-旋转小人儿造成的视觉错效

android 程序员 移动开发

veImageX演进之路:HEIF图片编码压缩与优化_产品_张锡平_InfoQ精选文章