图像处理解决方案 veImageX 技术演进之路

图像处理

近日,第五届深度学习图像压缩挑战赛(以下将简称“ CLIC 大赛”)比赛结果公布,首次参赛的火山引擎视频云多媒体实验室夺得视频压缩赛道第一名。压缩技术对于图像、视频应用十分重要。在保证同样的质量前提下,如何将图像压缩到更小的体积便于互联网信息传输,火山引擎视频云团队不断突破压缩技术“天花板”。当前字节跳动高峰期每秒需处理近百万张图片,基于今日头条、抖音等亿级 DAU 的实践打磨,与国际领先的压缩技术,火山引擎视频云打造图像一站式解决方案 veImageX ,覆盖上传、存储、处理、分发、展示、质量监控全链路,涵盖图像生产、图像消费、云平台三大应用场景。

图像生产

图像生产场景主要将业务产生的图像写入图像存储中,来源包括用户端的图像上传、在镜像站或三方云的存储(按需拉取或全量迁移)、在火山引擎的独立存储桶、业务自主合成的图片等。

picture.image

图像消费

图像消费环节提供了图片 URL 打包、图片实时处理链路、端数据上报等能力。

picture.image

业务 URL 签发: 签发过程中会调用 veImageX 的签发服务,然后下发图片 URL 到业务客户端。经过签发的图片 URL ,携带了有效期和签名信息,可以有效防止 URL 盗链、 URL 篡改、域名盗用等。

客户端 消费:业务图片加载 SDK ,完成图片下载、解码、展示、访问数据上报一系列操作。客户端上报的数据,经数据上报中心清洗后,会存储到数据仓库,供查询、监测图片的访问性能、错误率等指标使用。

网络分发:在图片下载过程中,一般来说会首先访问 CDN 。若 CDN 未缓存,则会触发回源,请求由源站接入层转发到图片静图服务。该服务主要负责访问权限的校验、流量控制、图片资源下载以及静态图片的主体处理流程。请求处理过程中,对于需要应用图片算法、HEIF 静图 FPGA 编码的场景,图片静图服务会通过 RPC 请求 Lambda 计算平台,相应的能力已通过远程可调用函数的方式在平台上部署。对于 FPGA 不能支持的图片(分辨率过大或过小),会发送到 CPU 平台的 HEIF 静图编码服务做处理。对于动图转码处理的请求,图片静图服务会发送到动图服务做处理。由于动图的帧数有多有少,对于帧数多、分辨率高的大动图,当请求处理超过一定时间后,动图服务会将同步处理转为异步方式运行,并临时返回原图作为降级结果,待降级结果在 CDN 上的缓存失效后,相应的请求会再次回源,此时可以拿到异步处理后的图片。当图片静图服务完成图片请求的处理后,请求相应的数据会存入数据仓库,供数据分析、计费推量使用。

云平台

veImageX 控制台作为一站式云平台,为用户提供了租户管理、配置下发、用量查询、质量监控、算法与算子管理等功能。

picture.image

控制台的请求通过网关发往 veImageX 后端服务。

平台管理,相关的 OpenAPI 支撑了平台侧配置管理、用量查询、质量监控等能力。涉及到后两者的场景,需要查询数据仓库获取对应的数据。涉及到域名的场景,需要依赖 veImageX 的域名管理服务,和接入与分发的各个组件交互。

算子仓库,图像算法开发人员借此可以方便地管理、发布、运维图片算法模型。云数据迁移服务则负责了图片生产场景中数据迁移任务的管理。创意魔方服务实现了多图合成的能力,业务可以通过创意魔方附加组件创建样式,然后动态替换文字、图片,批量生产图片,适用于海报制作、商品图片合成等场景。

离线调用,作为图片实时分发链路的补充,这里还提供了图片算法的离线调用,包含了所有图片算法的 OpenAPI 。此外图片离线转码分析平台可以应对批量图片的离线转码、画质分析等场景。

veImageX 的技术演进历程

veImageX 这些能力的形成并非一蹴而就,而是伴随着字节跳动的业务发展一路成长。

基础通用的图片分发能力

互联网时代开展业务离不开图片,在业务开展的早期,图片分发就在考虑之中。对于字节跳动来说,图片分发相关系统的开发工作在公司正式成立之前就已经开始了。

主流的图片传输方案都是基于 HTTP(S) 协议。由于图片的码率相比视频小很多,对于大多数场景,完全可以在一个 HTTP(S) 请求中完成实时处理。然后在用户访问侧接入 CDN ,将自己的图片处理服务作为源站,这样可以缓存绝大部分的图片请求的响应。如此,一个基本的图片分发链路就算搭建完成了。

早期的图片系统主要解决业务的最基础的图片分发诉求,并在此之上做了一定程度的抽象,通过 HTTP 路由来区分不同的分发场景。比如使用 /obj/<store_uri> 表示分发原图,使用 /large/<store_uri> 表示分发大分辨率档位的图片。

当业务场景变多后,个性化的图片展示诉求也随之而来,以 HTTP 路由区分场景这种偏定制化的方式就日益臃肿了。此时,图片系统利用通用做法,将图片处理参数做归类抽象,比如裁剪、缩放、水印等。将图片参数的选择权交给业务,让业务在下发的图片 URL 中自行指定处理参数,达到个性化分发的目的。

在 URL 中直接拼接图片处理参数,可以提供很大的自由度。但业务使用图片更多的是基于场景,而不是参数。不同的图片分发场景,可能都使用了相同的图片处理参数,但图片 URL 都长得一样。这时,业务不仅需要理解参数背后的含义,也无法通过 URL 中的参数来区分使用场景。另外,随着图片处理能力的变多、变复杂,图片处理参数的设计也会成为一个问题。

为了解决这类问题,技术团队首先定义 filter ,一个 filter 可以抽象为一个图像处理模块,输入为 RGBA 像素矩阵和一些自定义参数,输出为 RGBA 像素矩阵。单个 filter 可以是简单的图像缩放,也可以是复杂的图像算法(如超分)。接着将图片处理过程抽象为一个 pipeline ,依次运行下载->解码->应用 filter A->应用 filter B->编码,并将最终的结果返回。有了这些概念,我们可以定义模板:模板为一个配置文件,存放在图片系统服务端,模板内部封装了图片 filter(哪个 filter 什么参数)和编码参数。这样,业务在使用时不用关注内在细节,只需要在交互界面点选,即可创建属于自己的模板。为了提升模板的可扩展性,模板还支持 filter 中的部分参数动态变化,下发时在 URL 中传入。例如支持在 URL 中动态指定缩放宽高、支持传入用户 ID 作为水印文本等。

picture.image

随着模板的推出和业务线变多,一个严峻的事实出现在眼前:业务接入时到哪里创建管理模板,到哪里管理图片资源和图片域名,如何打通客户端和服务端?这时,veImageX 作为一个完整的产品形态应运而生。veImageX 以服务为最小粒度管理业务资源(域名、存储、模板等),通过附加组件的形式提供了诸多图片算法,具备了用量查询、质量监控、配置下发等端联动能力。

HEIF 高效压缩格式的推广

在具备基本的云图片能力后,随着业务体量的增长,veImageX 和业务逐步关注如何降低业务的图片成本。在业务的图片相关成本中,CDN 带宽成本一般占据 80% 以上。因此在不影响下发图片质量的前提下,降低图片码率是有效降低CDN 带宽成本的手段。

常用的图片格式有 JPEG、GIF、WebP、HEIF。JPEG 和 GIF 从推出到现在历经 30 年,JPEG 主打静图,GIF 主打动图。后起之秀 WebP 于 2010 年由 Google 推出,基于 VP8(与 H.264 同代技术),同时支持动静图,同画质下,相比 JPEG 和 GIF 可以节约 70% 的码率。HEIF 格式基于 H265 ,由 MPEG 于 2015 年推出。

火山引擎视频云团队基于 H265 技术,以自研的 BVC1 编解码器为核心,推出了可以兼容 HEIF 格式的高效图片编解码。目前 HEIF 图片格式已经在覆盖了超过 50% 的业务场景,使用 HEIF 压缩后的图片码率可以达到为同画质 WebP 的 55%-70%。

HEIF 格式是一把双刃剑,相比其他格式,在提升压缩率的同时,也需要消耗更多 CPU 计算资源。为了降低 HEIF 格式的编码计算成本,veImageX 采用了 FPGA 异构架构。应用后,整体成本约为 CPU 方案的 10%。但异构的一个难点在于:FPGA 计算集群如何部署。这里有三种方案。方案 A:整体图片处理服务迁移到 FPGA 集群;方案 B:将 HEIF 编码独立一个服务,并部署到 FPGA 集群;方案 C:整个服务划分 CPU 集群+ FPGA 集群,只将需要使用 FPGA HEIF 编码的请求发送到 FPGA 集群。

picture.image

三种方案相比,方案A最简单,但最不经济,因为 FPGA 只会用于 HEIF 编码,不可用于其他计算。而对于不涉及 HEIF 编码的请求,只消耗 CPU 资源。由于机器上 FPGA 和 CPU 配比是固定的,而 FPGA 吞吐量相比 CPU 高很多,如此会造成 CPU 资源相对短缺。为了保证 CPU 负载在安全水位内,此时 FPGA 负载必然过低,导致资源的浪费。另外,FPGA 资源有交付周期,而 CPU 资源相对更容易获取,方案 A 也提升整体运维成本。

方案 B 的优势在于足够灵活,图片处理服务通过 RPC 的方式和 HEIF 编码服务通信,而不用关注 HEIF 编码的计算架构。对于 HEIF 编码服务,可以先通过 CPU 计算架构实现。待 FPGA 方案完备后,只要改变 RPC 的目的服务,即可实现无缝迁移。另外独立的 HEIF 编码服务用到 CPU 的计算场景相比整个图片处理服务会少很多,这样 FPGA 的吞吐量不会受限于 CPU 资源的配比,可以发挥到最大。当然,劣势在于,RPC 调用引入了额外的编解码过程,用于发送处理完成后待编码的图像,而且会引入少量的压缩噪声。另外,RPC 附带网络通信开销,链路时延变长,如此会抵消 FPGA 的编码性能优势。

方案 C 对图片处理服务及其上游有一定要求,需要他们对流量有掌控能力,能将需要 FPGA HEIF 编码的请求按需发送到 FPGA 集群。另外方案对 FPGA 集群的 CPU 配比也有一定的要求,此时计算瓶颈可能卡在 CPU 资源上,导致 FPGA 的吞吐量受限。方案的优势在于能够发挥 FPGA 的计算性能,降低源站图片处理延迟。当然,从另外一层面来说,由于 CDN 的存在,当请求量达到一定体量时,源站处理延迟只会影响到图片的首刷体验,对端上整体图片加载时长的影响微乎其微。

当前 veImageX 于方案 B 和方案 C,按场景的不同,都有采用:对于静图场景,用到方案 B ,因为 FPGA 对于图片的分辨率有限制范围,CPU 和 FPGA 两套计算架构需要共存,而且静图请求量较大,独立服务维护可以使 CPU 不至于成为瓶颈,能够挖掘 FPGA 的最大潜力;对于动图场景,因为动图帧数多,编码为中间格式再通过 RPC 发送代价较高,方案 C 更合适。

当然,图片格式的发展很快,与 HEIF 压缩性能不相上下的 AVIF 格式 veImageX 也已支持。基于新一代 H.266 的 BVC2 格式也已经在路上

智能图像算法的应用

图片分发场景使用到的算法,按用途一般包括画质提升、码率节省、定向优化;定向优化主要是指盲水印、抠图、背景自动擦除、智能裁剪等。画质提升类的算法以超分和增强为主。超分能够提供 2-8 倍的分辨率提升,以此提升图片的展示效果,当然此时图片的码率也会相应变大。增强算法以优化图片内容为目的,按场景可以细分为低质增强、人像增强等。

    • 低质增强算法能够对多种模糊、噪声、压缩损伤等低质类型的图像自适应处理。经过算法处理后,图片在清晰度、对比度、噪声和伪像消除等多方面都有较大的提升。

picture.image 左图为原图,图片内噪声比较明显,画质较差;右图为低质增强后结果,整体画质提升明显

    • 人像增强算法对图片中关键的人脸区域进行消除模糊、细节恢复、重建清晰的人脸五官,进一步提升人脸的质量。

picture.image 左图为原图,人像较为模糊;右图为人像增强后,人像整体更为清晰

码率节省类算法的代表是集智瘦身。该算法可以在保持原图画质的基础上,降低图片码率。根据业务的线上应用效果,整体码率节省比例可以达到 10%-15% 。

这些智能算法一般都需要依赖 GPU 计算资源来加速,由此引入了异构计算资源。在实践中,veImageX 依赖 Lambda 计算平台来管理 GPU 资源。开发人员将算法模型封装为 Lambda 平台上的函数,图片处理服务通过 RPC 来应用图片处理算法。如此,实现了图片处理服务和算法迭代间的解耦。为了提升算法发布的效率,veImageX 建设了算子平台。算子平台作为 veImageX 和算法开发人员之间的桥梁,实现了算法模型的自动化上架、算法函数的可视化运维、算法版本的迭代管理等功能。

图片算法处理耗时一般是百毫秒的量级,再加上 RPC 中作为中间结果的图片文件的编解码和网络传输,整体处理耗时可能是普通图片请求的数倍。对于首次回源的请求,如果使用了图片算法,访问的延迟会不可控。为了提升图片的首刷体验,veImageX 针对效果提升类算法引入了降级的方式。首次访问时,直接返回原图作为降级结果,并异步调用图片算法,再将算法处理后的图片持久化存储。

picture.image

以上讨论的都是在图片分发的场景下,应用图片算法并实时返回。另外一种看似合理的思路是,在图片完成上传后,立即触发图片算法,并将算法处理后的图片存下来。待到分发时,直接下发处理后的图片。这种做法有一些弊端:

首先生产侧应用图片算法是一个全量的过程,需要对所有已上传的图片做相应处理,随着时间积累,这部分图片数据占用的存储资源将逐步膨胀。尽管里面很多图片可能不会再被访问到,但仍然要支付这部分存储开销。

另外,算法模型会有版本迭代,可能会修复一些问题、或有能力提升,此时存量已处理过的图片就十分“尴尬”:如果存量全部替换使用新算法,量级太大,未必能都处理完;如果不替换,新的算法生效慢,已有的问题图片也可能都无法修复。

相比而言,在分发侧实时处理的优势就体现出来了。分发时按需处理,算法模型更新后,只需要灰度替换为新的图片模板,存量和新增可以一并解决。

图像画质的把控

上文提到的算法,有些是提升画质,有些是保证画质的前提下降码率。这里面都围绕了一个概念:画质。veImageX 提供了 OpenAPI,可以对输入的图片做画质评估,从清晰度、噪声、美学等维度对图片做综合打分。但我们发现用户更关注的是访问的图片所在的巨大集合所呈现的画质,而不是单张或若干张图片的画质分数。因此还需要一个大盘来展示用户访问视角下,图片的整体画质情况。此外,当开启新的算法 AB 实验后,也可以根据画质指标来验证算法的效果,这样整体实验的结果更为置信。

在客户端直接对展示的图片做画质评估肯定不是一个好办法,一方面画质评估会消耗较多计算资源,另一方面,客户端访问到的图片大部分都是缓存在 CDN 上的,是一样的,这样重复计算很是浪费资源。因此服务端进行画质评估更合理,而画质评估的结果可以随图片内容一起缓存在 CDN。veImageX 在图片模板中新增了画质评估选项。若选项打开,则源站处理完成图片请求后,在返回图片数据之前加入一个步骤——画质评估。由于画质评估非必要步骤,评估超时或者失败都不应当影响图片数据的返回。

但天下没有免费的午餐,画质评估也涉及到了远程算法调用,整体耗时约占原图片请求处理的 30%-50% ,所以请求首次回源的延迟必然会相应增加。解决这个问题有两个方案:

  • 尽量在用户访问频次高的场景使用。一个供参考的数据是:CDN 边缘节点命中率在 30% 的时候,如果引入画质评分,客户端请求图片平均耗时上涨约 20% ;而当 CDN 边缘命中率到 99% 的时候,整体平均耗时上涨不到 2% 。
  • 源站做画质评估时加入抽样选项,默认 50%,意味着只对 50% 的请求做画质评估。由于客户端上报数据原本就是抽样进行的(一般至少百万分之一),所以源站的抽样对最终的结果影响微乎其微。

picture.image

在线画质评估方案主要用于实验中的画质指标分析和用户视角的画质评分。一个问题随之而来,AB 实验一般历时较久,那么在应用新算法实验之前,如何能够评估算法对画质的影响,并相应调整算法参数呢?veImageX 通过离线画质评估平台来解决这个难题。具体做法是,拉取一批线上实际的用户的访问图片,使用包含新算法的图片模板进行处理,处理过程中,对模板中每个 filter 的入口、出口图片做画质分析,最终将所有分析结果汇总成报表。这样根据报表中的中间画质结果,能够清晰地评估新算法的整体效果。业务也能够根据结果调换 filter 顺序、修改算法参数。

分发链路的复用

图片的实时分发链路只是一个载体,稍加拓展,就可以应用到其他场景。例如,原文件为视频,如果下发静图,则对视频文件做实时截帧,从视频文件的固定时间点抽取一帧,并复用图片模板处理;如果下发动图,则对视频文件做实时动态封面截取,从视频文件中截取一个短片段,转换为动态图片,然后复用图片模板处理。当然,受限于「实时」这个前提,原文件为小视频时,则效果最佳。

对于小视频的实时转码,也可复用图片的实时分发链路,但是需要一些定制改造。首先视频处理过程与图片大相径庭,需要独立的服务处理、独立的模板配置;其次图片处理结果码率一般不大,可以单次全量返回,但是视频得考虑观看体验,需要能支持流式返回。当然,这种方案相比视频点播来说,只是胜在轻量接入、简单分发、快速使用,对于视频点播涉及到的诸多视频转码能力、播放端优化、中长视频支持都力所不能及。

一些总结

veImageX 图片系统的演进贯穿在字节跳动发展的过程中,在不同时期以不同的形式解决图片分发的各类问题,最终“生长”成为图片中台。veImageX 从业务需求中走出来,回归到业务中去,紧密联系业务,提供了一套完整的端到端图片解决方案。

229
1
0
0
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论