作者:杨洋,阿里云技术专家,从事直播相关媒体处理引擎开发

背景

图像质量的衡量是个老问题,对此人们提出过很多简单可行的解决方案。例如均方误差(Mean-squared-error,MSE)、峰值信噪比(Peak-signal-to-noise-ratio,PSNR)以及结构相似性指数(Structural Similarity Index,SSIM),这些指标最初都是被用于衡量图像质量的,随后被扩展到视频领域。
这些指标通常会用在循环用在编码内部,可用于对编码决策进行优化并估算最终编码后视频的质量。但是由于这些算法衡量标准单一,缺乏对画面前后序列的总体评估,导致计算的结果很多情况下与主观感受并不相符。

视频质量

阿里云视频云每天都会生产、处理大量来自不同应用场景、不同编码类型的视频数据。除了采用窄带高清等技术以外,我们还会借助 VMAF 标准对处理后的视频做质量评估,形成 媒体生产-->画质评估-->编码优化-->产品迭代 的技术闭环。基于这套反馈机制,对不同的场景做针对性优化,达到画质最优、成本最低的效果。

VMAF 介绍

面对不同特征的源内容、失真类型,以及扭曲程度,每个基本指标都各有优劣,缺少一个通用的、能反应主观意识的画质评估手段。VMAF (Video Multimethod Assessment Fusion) 由 Netflix 开发并开源,利用大量的主观数据作为训练集,通过机器学习的手段将不同评估维度的算法进行“融合”,得到一个能准确反映主观意志的画质评价标准。
VMAF 主要包括3种指标:visual quality fidelity(VIF)、detail loss measure(DLM)、temporal information(TI)。其中 VIF 和 DLM 是空间域的也即一帧画面之内的特征,TI 是时间域的也即多帧画面之间相关性的特征。这些特性之间融合计算总分的过程使用了训练好的 SVM 来预测。
工作流程如图:
file

VMAF 模型分析

VMAF 默认提供了 vmaf_float_v0.6.1.pkl 模型,可以分为 HDTV、Phone、4K 超分辨率三种使用模式,满足不同播放场景下的画质评测需求。

1.HDTV 模式

HDTV 是针对客厅电视的场景设计的,参照 SMPTE EG-18-1994 标准,所有训练集的主观数据 (EMOS) 是遵循这种方式收集的:将视频 scale 成 1080p,并以三倍于屏幕高度 (3H) 的观看距离或 60 像素/度的角度分辨率进行显示。
可以说,VMAF 模型试图捕捉的是 3H 外显示的 1080p 视频的感知质量。这是默认 VMAF 模型的隐含假设。因此,我们在对除 1080p 以外的其他分辨率进行 VMAF 计算时,需要将视频先 scale 成1080p,才能保证结果的准确性。

file

试想一下,如果将一个 480p 的视频用 HDTV 模式来做评测,会发生什么情况呢?这就好像 480p 视频是从 1080p 视频中剪切出来的一样。如果 480p 视频的高度为 H ',则 H = 1080 / 480 * H ',其中 H 为所显示的 1080p 视频的高度。因此,VMAF 建模的是 3H = 6.75H ' 的观看距离。
换句话说,如果你计算 480p 分辨率的视频对的 VMAF,你将预测观看距离是其高度的 6.75 倍时的感知质量。在此观看距离会隐藏大量主观画质的感知细节,从而让 VMAF 分数可能偏高。

2.Phone 模式

默认的 vmaf_float_v0.6.1.pkl 模型也提供了移动设备场景的画质评估功能,可以通过参数 “--phone-model” 开启。在此模式下,每个受试者在他/她感到舒适的距离观看视频。
在训练过的模型中,分数在 0 - 100 之间,与主观投票量表呈线性关系,粗略的 “bad” 映射为20分,“excellent” 映射为 100 分。
横向对比可以发现,如果将一部 540p 的视频分别放在标准电视、手机设备、4K 设备显示,在手机设备上的 VMAF 质量会比其他两者更快的逼近 100 分的临界值。

file

3. 4K 模式

由于 vmaf_float_v0.6.1.pkl 模型的训练集中包括了 4K 和 1080p 的视频源,当需要对比 A/B 两个 4K 视频哪一个画质更好时,也能使用此模型。
但是由于默认模型采用的是 1080p + 3H 观看距离的方式采集的 EMOS 数据,无法算出准确的 4K VMAF 分数。Netflix 后来专门提供了 vmaf_4k_v0.6.1.pkl 用于 4K 的画质评估。

VMAF 核心模块

VMAF 基于 SVM 的 nuSvr 算法,在运行的过程中,根据事先训练好的 model,赋予每种视频特征以不同的权重。对每一帧画面都生成一个评分,最终以均值算法进行归总(也可以使用其他的归总算法),算出该视频的最终评分。其中主要的几个核心模块如下:

file

VMAF 分别用 python 和 C++ 实现了两套接口,同时提供了 C 版本的 lib 库,最新版本的 ffmpeg 已经将 VMAF 作为一个filter集成进去。
下面我们分析下各个模块的作用:

Asset

一个 Asset 单元,包含了一个正在执行的任务信息。比如目标视频与原始视频的帧范围,低分辨率视频帧上采样信息等(VMAF 会在特征提取前通过上采样的方式保证两个视频分辨率相同)。

Executor

Executor 会取走并计算 Asset 链表中每一个 Asset 单元,将执行结果返回到一个 Results 链表中。Executor 类是 FeatureExtractor 与 QualityRunner 的基类。它提供了一些基函数,包括 Results 的操作函数、FIFO 管道函数、clean 函数等。

Result

Result 是以 key-value 形式,将 Executor 执行的结果存储起来。key 存储的是 “FrameNum” 或者质量分数的类型(VMAF_feature_vif_scale0_score 或 VMAF_feature_vif_scale1_score 等),value 存储的是一系列分值组成的链表。
Result 类也提供了一个汇总工具,将每个单元的质量分数汇总成一个值。默认的汇总算法是“均值算法”,但是 Result.set_score_aggregate_method() 方法允许定制其他的算法。

ResultStore

ResultStore 类提供了 Result 数据集的存储、加载的能力。

FeatureExtractor

FeatureExtractor 是 Extractor 子类,专门用于从 Asset 集合中提取特征,作为基本的特征提取类。任何具体的特征提取接口,都继承自 FeatureExtractor,例如 VmafFeatureExtractor/PsnrFeatureExtractor/SsimFeatureExtractor 等。

FeatureAssembler

FeatureAssembler 是一个聚合类,通过在构造函数传入 feature_dict 参数,指定具体的特征提取标准,将该标准提取出的特征结果聚合,输出到一个 BasicResult 对象中。FeatureAssembler 被 QualityRunner 调用,用来将提取后的特征数组传给 TrainTestModel 使用。

TrainTestModel

TrainTestModel 是任何具体的回归因子接口的基类,回归因子必须提供一个 train() 方法去训练数据集,predict() 方法去预测数据集,以及 to_file(),frome_file() 方法去保存、加载训练好的模型。
回归方程的超参数必须通过 TrainTestModel 的构造函数传入。TrainTestModel 类提供了一些基础方法,例如归一化、反归一化、评估预测性能。

CrossValidation

CrossValidation 提供了一组静态方法来促进 TrainTestModel 训练结果的验证。因此,它还提供了搜索 TrainTestModel 最优超参的方法。

QualityRunner

QualityRunner 是 Executor 子类,用来评估 Asset 任务集合的画质分数。任何用于生成最终质量评分的接口都应该继承 QualityRunner。例如跑 vmaf 标准的 VmafQualityRunner,跑 psnr 标准的 PsnrQualityRunner 都是 QualityRunner 的子类。

自定义 VMAF

最新版本的 vmaf 提供了 1080p、4k、mobilephone 三种场景下的 model 文件。Netflix 号称使用了海量的、多分辨率、多码率视频素材(高噪声视频、CG动漫、电视剧)作为数据集,得到的这三组 model。在日常使用中,这三组 model 基本满足需求了。不过,VMAF 提供了 model 训练工具,可以用于训练私有 model。

1.创建新的数据集

首先,按照 dataset 格式,定义数据集文件,比如定义一个 example_dataset.py:

dataset_name = 'example_dataset'
yuv_fmt = 'yuv420p'
width = 1920
height = 1080
ref_videos = [
{'content_id': 0,
'content_name': 'BigBuckBunny',
'path': ref_dir + '/BigBuckBunny_25fps.yuv'}
...
]
dis_videos = [{'asset_id': 0,
'content_id': 0,
'dmos': 100.0,
'path': ref_dir + '/BigBuckBunny_25fps.yuv',
}
...
]

ref_video 是比对视频集,dis_video 是训练集。每个训练集样本视频都有一个主观评分 DMOS,进行主观训练。SVM 会根据 DMOS 做有监督学习,所以 DMOS 直接关系到训练后 model 的准确性。

PS: 将所有观察者针对每个样本视频的分数汇总在一起计算出微分平均意见分数 (Differential Mean Opinion Score) 即 DMOS,并换算成 0-100 的标准分,分数越高表示主观感受越好。

2.验证数据集

./run_testing quality_type test_dataset_file [--vmaf-model optional_VMAF_model_path] [--cache-result] [--parallelize]

数据集创建后,用现有的 VMAF 或其他指标 (PSNR,SSIM) 验证数据集是否正确,验证无误后才能训练。

3.训练新的模型

验证完数据集没问题后,便可以基于数据集,训练一个新的质量评估模型。
./run_vmaf_training train_dataset_filepath feature_param_file model_param_file output_model_file [--cache-result] [--parallelize]

例如,
./run_vmaf_training example_dataset.py resource/feature_param/vmaf_feature_v2.py resource/model_param/libsvmnusvr_v2.py workspace/model/test_model.pkl --cache-result --parallelize

feature_param_file 定义了使用那些 VMAF 特征属性。例如:
feature_dict = {'VMAF_feature':'all', } 或 feature_dict = {'VMAF_feature':['vif', 'adm'], }

model_param_file 定义了回归量的类型和使用的参数集。当前版本的 VMAF 支持nuSVR 和随机森林两种机器算法,默认使用的 nuSVR。
output_model_file 是新生成的 model 文件。

4.交叉验证

vmaf 提供了 run_vmaf_cross_validation.py 工具用于对新生成的 model 文件做交叉验证。

5.自定义特征和回归因子

vmaf 具有很好的可扩展性,不仅可以训练私有的 model,也可以定制化或插入第三方的特征属性、SVM 回归因子。
通过 feature_param_file 类型文件,支持自定义或插入第三方特征,需要注意的是所有的新特征必须要是 FeatureExtractor 子类。类似的,也可以通过 param_model_file 类型文件,自定义或插入一个第三方的回归因子。同样需要注意的是,所有创建的新因子,必须是 TrainTestModel 子类。

总结

一套普适的主观质量评价标准,不仅要有时域、空域的多维度评价标准,符合主观意识的融合算法,还要有大量有效的、符合标准规范的 EMOS 数据集。是一个需要长期投入,不断迭代的优化过程。

「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实践技术文章,在这里与音视频领域一流工程师交流切磋。