播放器视频后处理实践(一)
1. 前言
在播放器架构不断演进的今天,视频后处理技术正在成为提升用户体验的关键环节。相比传统的解码即播,现代播放器越来越多地引入后处理链路,通过增强画质、渲染氛围等手段,为用户提供更具沉浸感的视听体验。
本系列文章将系统介绍我们在播放器视频后处理模块中的技术方案与工程实现,涵盖从效果设计、算法选型,到性能优化和跨平台兼容的全链路细节。第一期内容聚焦在两类核心能力:
-
视频增强:提升画面清晰度、对比度与色彩表现,尤其针对暗场、低码率等场景进行针对性优化;
-
氛围模式:基于视频内容实时生成边缘延展光效,打造更强沉浸感,适配大屏与移动端场景。
本文将着重介绍我们如何在性能受限的设备上实现视频增强效果,如何结合 GPU/OpenGL、Shader 编程以及平台图像处理 API 构建高效可控的处理链路。后续我们将陆续推出如氛围模式等视频后处理文章,敬请期待。
2. 视频增强(亮度和色彩)
丨2.1 什么是视频增强技术
视频增强技术是指一系列用于改善视频质量的技术手段,其目的是在不改变原始内容的情况下提升视频的视觉效果。技术的应用场景包括视频播放、编辑、传输、存储等领域,常用于提高图像清晰度、对比度、色彩饱和度等,使观看者获得更好的视觉体验。
丨2.2 常见视频增强技术
移动端实践:亮度与色彩增强。针对Android/iOS平台的视频播放场景,我们重点实现了亮度增强与色彩增强两项关键技术。本文将分享技术落地中的核心方案与优化经验。
丨2.3 亮度增强
亮度增强效果示意图(左:原图 右:增强后)
2.3.1 技术选型
亮度增强是图像/视频处理中非常基础且常见的操作,常见的亮度增强原理可以分为以下几类,每种方式背后的核心思想略有不同。下面是详细的分类和解释:
- 线性亮度增强(线性增益)
原理:RGB整体直接乘以一个大于 1 的系数(或加一个偏移量)。
公式:
color.rgb = color.rgb * gain; // 乘法增强color.rgb = color.rgb + offset; // 加法增强
-
简而言之,这种做法就是简单粗暴的在原本的RGB上进行提升,从这里,可以想到RGB颜色调整后容易出现色偏。
-
那么我们可能会想到,如果先将RGB转换为YUV,调节Y 分量,再反变换为 RGB。
公式:
Y = 0.299*R + 0.587*G + 0.114*B;
Y_new = Y * gain;
-
这确实是视频增强中一种常用且理论上“更稳”的方式,因为它分离了亮度(Y)和色彩(UV / IQ / CbCr)信息。
-
但这种处理方式有一个严重的问题,不处理图像的对比度或中间的关系,且不能保留高光细节(Clipping),也就是调整后,超过范围[0.0,1.0]的值会被截断(clamp),造成高光过曝。
- 直方图均衡(Histogram Equalization)
原理:通过调整像素分布,让亮度值均匀分布在整个区间,从而整体提升视觉亮度。
特点:增强暗部和亮部的对比,对低对比度图像尤其有效。
实现相对复杂,不常用于实时shader,考虑到其运算复杂性,我们也pass了这种方式。
- Gamma 变换(幂律调整)
原理:使用幂函数对像素进行非线性拉伸。
公式:
color.rgb = pow(color.rgb, vec3(gamma));
特点:γ < 1:图像变亮,主要拉升暗部;γ > 1:图像变暗,压缩亮部。
具有两个优点:
-
调整方式具有非线性特点,能更细腻地控制中间调亮度,避免简单加法可能引起的局部过曝或暗部细节丢失。
-
模拟现实中显示设备的响应曲线,效果较为自然。
这也是我们最后选择的方式,他的运算量简单,适合端上视频播放的实时处理。
2.3.2 背后的原理
我们引申一下,这种方式的优点是怎么得出来的呢。
- 为何能避免简单加法可能引起的局部过曝或暗部细节丢失
从公式看,原本亮度较低的像素会被相对“提亮”更多,而原本亮度较高的像素提升幅度较小。暗部像素相对于原值会获得更大的“提拉”,而亮部像素则变化较小,从而既能提升整体曝光,又能保留高光细节。
- 为什么说模拟现实中显示设备的响应曲线,更为自然呢?
因为显示器、人眼视觉和视频编码,都是非线性系统,不是简单线性变化。
-
真实世界的光亮度是线性的,比如两支灯加起来就是两倍亮。
-
但人眼感知亮度是对数感知的(小亮度变化很敏感,大亮度变化不敏感)。
-
视频和图像在存储时通常经过一个 Gamma编码,原本线性光 → 压缩(比如取 1/2.2 次方) → 存成文件。这种光和电的转换过程,就是OETF/EOTF响应曲线。
所以这种pow(color, gamma)的调整方式,实际就是在模拟显示端的响应曲线。
总结一句话:
编码有 Gamma,所以显示端或后处理也必须按照 Gamma空间规则来调节,才能保持自然感知。
丨2.4 色彩增强
色彩增强效果示意图(左:原图 右:增强后)
从上图可以看到山体、草地上的花,饱和度增强。
2.4.1 调节的目标
1. 增强色彩感知
提高图像的“鲜艳度”或“视觉吸引力”,让图像更生动。
特别是在图像颜色偏灰、曝光不佳或图像压缩后颜色损失的情况下。
2. 突出主体
通过饱和度调节,增强主体与背景之间的色彩对比,提高视觉聚焦度。
3. 修复/还原真实色彩
对摄像头采集后色彩不足的图像进行还原,尤其是肤色、植物、天空等自然色彩。
针对上述目标,我们主要依赖主观评测感受,同时需要避免以下问题:
主观评估(人眼视觉)
-
色彩鲜明但不刺眼:增强后色彩更加明显但不过饱和。
-
肤色自然:人脸或皮肤色调不过红或黄(肤色是视觉最敏感区域)。
-
色彩分布均衡:图像中颜色种类丰富但不过分集中某一色调。
-
无色彩断层:调节后颜色过渡应平滑,不能有色阶突变。
2.4.2 技术选型
目前业界对色彩增强主要有以下2种方向的研究:
-
传统SDR色彩增强。
-
SDR2HDR,模拟HDR效果,达到增强目的。
从实现方式上,主要也有2种主流方式:
1. 非神经网络(传统算法 or 结合lut查找表)
2. 基于神经网络(模型)
模型需要较高的技术储备,且在移动端运行耗时大,所以目前我们没有选择这种方式,而是寻找效果较好且可控的算法。
2.4.2.1 色彩三要素
我们先了解下“色彩三要素”。他们是色彩学中用于描述颜色感知的三个基本维度,分别是:色相、饱和度、明度。这三者共同定义了一个颜色的完整视觉特性。
色相
饱和度
明度
在色彩增强中,一般主要调节的是饱和度(Saturation),其次可能会适当调整明度(Brightness / Value) ,而色相(Hue)通常不会主动改变。原因如下:
常调节的要素及原因:
1. 饱和度(Saturation)
- 最常调节的要素,增强后画面显得更鲜艳、更有吸引力,尤其适用于风景、商品、动漫类画面。可提升视觉冲击力和色彩表现力。
- 明度 / 亮度(Brightness / Value)
- 有时作为辅助增强项,提高整体图像的通透感。与 Gamma 调节、曝光补偿常一起使用,即配合使用上一章节的亮度调整即可。
- 色相(Hue)
- 一般不调整,因为改变色相会改变物体本身颜色,可能导致不真实(如人脸偏色、草地变蓝等)。只在需要艺术化或特殊滤镜(如复古风格、红外效果)时才会使用。
2.4.2.2 颜色空间的选择
选择好色彩增强的调节方向为『饱和度』后,第二步,我们需要选择好颜色空间。
当视频一帧画面作为GL纹理输入到后处理链路时,为RGB颜色模型,我们想要调节饱和度,则需要将其转换为其他颜色空间进行调节,那么面临的第一个问题是如何选择合适的颜色模型去进行算法设计?
-
RGB
-
HSV
-
LCH/LAB
2.4.2.3 基于RGB空间
- 基于RGB颜色直接调节
们可以理解,饱和度是色彩的纯度,即色彩相对于灰度(无色)的程度。那么我们可以基于RGB颜色模型,并根据灰度进行差值混合即可。
如GPUImage的GPUImageSaturationFilter提供了类似例子,它对饱和度调节,是基于RGB颜色,然后取出灰度值通过在原始颜色和灰度之间插值,mix(vec3(luma), color.rgb, saturation) 实现了饱和度的变化:
-
插值因子 saturation 越接近 0,图像越趋向于灰度;
-
saturation 越高,图像越接近原始颜色或超出原始饱和度,色彩更鲜艳。
这种简单的算法存在一个问题:原本局部饱和度已经比较高,如果依然提高饱和度,则局部细节消失。
过饱和,细节丢失
2. 为了解决上述问题,我们基于自然饱和度的调整。
自然饱和度(Vibrance)的概念最先由photoshop提出,重点在于适应性,自然饱和度调整后一般比饱和度调整要自然。其核心特点:
进行自适应饱和度调节的流程:
-
计算亮度(Luma):使用加权平均公式从 RGB 获取亮度:luma = 0.2126 * r + 0.7152 * g + 0.0722 * b
-
计算饱和度(Saturation):使用 RGB 最大值和最小值之差估算色彩纯度:saturation = max(r, g, b) - min(r, g, b)
-
计算调节因子 k:根据当前饱和度和用户设置的 Vibrance 强度进行非线性调节:k = 1.0 + Vibrance * (1.0 - saturation / 255.0)(Vibrance 取值范围通常为 0.0 ~ 1.0)
-
应用颜色调整:将颜色向亮度方向插值,使低饱和度颜色更鲜艳,同时高饱和区域变化较小:color.rgb = mix(vec3(luma), color.rgb, k)
其调整倾向于将RGB值往同一个luma值进行靠近,也是无法保证颜色保持稳定,容易会发生偏色的情况。
色彩增强效果示意图(左:原图 右:自然饱和度增强后)
于是,我们继续探索其他的颜色模型。
2.4.2.4 基于HSV颜色模型的饱和度调整
基于HSV饱和度的调整方法是将RGB颜色模型转换为HSV颜色模型,其中HSV分别表示色相(Hue)、饱和度(Saturation)、明度(Value)。只调整饱和度可以在不影响明暗和色相的情况下增强色彩的鲜艳程度。
将常见的调整方法有整体抬升,按比例增加,或者曲线调整,达到将整体饱和度提高的目的。但是饱和度调整同时提升所有颜色的强度,比较粗暴。
有可能导致:
-
本来局部饱和度已经比较高,调节后过饱和,局部细节的消失。(和上一章节例子一样)。
-
本来局部饱和度较低,接近白色,加大饱和度后,容易出现色块。
普通调节
如何优化:
-
对此引入对源的饱和度的检测,设定上下限制,平滑调节。
-
在HSV颜色模型上,引入了类似自适应饱和度调整的方式。
-
目的:在低饱和度区域,避免突然增加饱和度。低饱和度的颜色(例如接近灰色的颜色)通常对饱和度调整非常敏感,因此需要一种平滑的方式。
-
目的:在高饱和度区域减少权重,避免过度增强饱和度。高饱和度的区域本身已经很饱和,进一步增加饱和度会导致过饱和,视觉上显得不自然。
加入自适应后
2.4.2.5 肤色保护
采用HSV空间调整后,我们还需要考虑一个核心问题:
在图像色彩增强(如饱和度调整、色调映射)时,肤色区域容易因过度调整而失真(如过红、过黄或惨白)。需通过肤色识别技术,对检测到的肤色区域进行保护,限制增强幅度,保持自然观感。
在此引入了基于HSV色彩模型的肤色识别,HSV色彩模型也同样将亮度与颜色进行了分离,因此对于光照变化也有很强的抗干扰能力,可以较好的识别出肤色。
结合HSV色彩模型和高斯概率模型实现肤色保护,具体步骤如下:参考GPUImageSkinToneFilter的肤色识别方法。
(1) RGB转HSV空间
-
将图像从RGB转换到HSV空间,分离色调(H)、饱和度(S)、亮度(V)。
-
优势:HSV的色调通道(H)对光照变化鲁棒,更适合肤色识别。
(2) 肤色概率计算
-
肤色色调模型:
统计肤色色调的均值 skinHue = 0.05(典型值,对应黄红色调)。
方差相关参数 skinHueThreshold = 40(控制肤色范围宽度)。
-
距离计算:
计算当前像素色调 h 与 skinHue 的归一化距离。
dist = abs(h - skinHue) / 0.5高斯权重(概率)。
-
通过高斯函数计算肤色概率:
skinProb = exp(-dist * dist * skinHueThreshold)结果范围 [0, 1],越接近1表示越可能是肤色。
(3) 肤色区域保护
-
阈值分割:
设定阈值(如 skinProb > 0.95),二值化得到肤色掩膜(Mask)。
-
动态衰减增强强度:
对检测到的肤色区域,按 skinProb 权重衰减色彩增强效果。例如:enhanced_pixel = original_pixel * (1 - skinProb) + adjusted_pixel * skinProb * alphaalpha 为衰减系数(如0.2),控制保护力度。
增加肤色保护后,可以看到效果明显更好,人脸不会有过于突兀的颜色变化。
左:增强(无保护)中:原图 右:增强(肤色保护)
2.4.3 效果对比
-
HSV空间的调节后色彩更加自然。
-
RGB空间调节则更加绚丽。但容易色偏。
-
基于综合考虑,我们采用HSV空间调节,以适应更多的源,避免色偏。
三. 总结与展望
本研究聚焦于移动端视频增强技术的工程化落地,重点验证了亮度增强与色彩增强两种核心算法的实际应用效果。从主观评测效果看,在部分视频上,两项技术均能显著提升视频观感质量,有效改善用户体验。
目前,亮度增强功能已在「好看 App」成功上线,且收获了良好的应用效果。现阶段,我们正着力研发亮度增强与色彩增强相叠加的综合优化方案,计划通过这一方案对更多视频内容进行品质升级,从而为用户带来更优质的观看体验。以下为您呈现亮度增强结合色彩增强的部分应用案例:
例子1:后层次感更好(右)
例子2:色彩更鲜明(右)
例子3:画面更清晰明亮(右)
未来研究将围绕以下方向展开:
-
场景化优化:建立典型场景特征库,针对性优化算法参数配置。
-
实时性提升:通过模型轻量化与硬件加速技术,更加快速的视频实时处理。