VMAF是Netflix开发的、用于评估视频感知质量的算法。VMAF包括一个独立的C语言库libvmaf及其对该库的Python包装。在Python库中,还提供了一组工具,以方便用户可以训练和测试自定义的VMAF模型。目前为止,在工业实践中,VMAF是视频质量评估领域中最优秀的全参考评估算法。
但是,在MacOS上编译并使用VMAF的过程中,发现会有一些问题导致无法编译成功,并且和模型训练相关的python代码也存在某些小的冲突,导致在整个模型训练的过程会出现某些异常。
本文就是对自己在调试过程中遇到的问题的总结。
我所使用的VMAF的版本为commit id为6f1f0c98的这次提交。遇到的所有问题也都是基于这次提交,这一点要额外注意。主要解决的问题和具体的解决方法可以参考文章接下来的部分。
libvmaf test/tools链接问题
在编译libvmaf的C
库的时候,发现当编译test
和tools
目录下的文件时,会出现异常。
经过排查以后,发现是对应的编译产出的链接库出现了异常。在编译时,如果配置default_library
为both
,则会产出libvmaf的静态链接库和动态链接库,并且在产出test
和tools
相关对象时,会优先选择采用静态链接库进行链编。具体如下所示:
1 | vmaf = executable( |
不确定为什么这里采用静态链接库时会出现异常,但是把静态链接库改成动态链接库之后,整个工程就可以成功编译了。至于原因,等有时间再仔细定位一下。
1 | vmaf = executable( |
libsvm库的路径设置问题
在使用python目录下提供的相关工具进行模型训练的时候,最终会使用python/vmaf/svmutil.py
来实现对libsvm
库的调用,进而根据训练数据产出SVM
的模型文件。
但是,在svmutil.py
中会配置libsvm
库的路径,默认情况下,这个路径的配置如下:
1 | libsvm_path = VmafConfig.root_path('third_party', 'libsvm', 'python') |
而实际上,在我所编译的机器上,使用pip3 install libsvm
之后,libsvm
的路径并非是如上指定的路径,因此会导致在调用libsvm
时出现异常,根据自己编译机器的具体情况,修改libsvm_path
的路径即可解决问题,具体如下:
1 | libsvm_path = VmafConfig.root_path('site-packages', 'libsvm') |
Matplotlib中设置backend为agg带来的问题
关于Matplotlib中的backend相关的问题,此处不再详细展开,具体可以参见matplotlib的backends以及非交互式绘图。
默认情况下,在vmaf中,Matplotlib的backend会设置为agg模式。例如,在python/vmaf/script/run_vmaf_training.py中,就进行了相关的配置:
1 | #!/usr/bin/env python3 |
在使用libsvm
训练完模型之后,会对VMAF的SRCC
,PCC
等指标进行计算,并利用python/vmaf/config.py
中的DisplayConfig.show()
最终调用matplotlib
来进行结果的可视化展现。但是,在DisplayConfig.show()
中,却是使用是否存在参数write_to_dir
来判断调用什么backends
,这就会和之前的Agg
配置出现冲突,因此这里需要做一个简单的升级,如下所示:
1 | if matplotlib.rcParams['backend'] == 'agg': |
实际上,只有在MacOS上才会出现该问题,因此更合理的方式是根据系统来设置Matplotlib的backends,而不是直接修改Config类。具体可以参考这里的讨论。
libvmaf的特征和python中使用的特征的差异
libvmaf种各特征的类型
默认情况下,编译出来的libvmaf库使用的是integer类型的特征,具体如meson_option.txt
所示:
1 | option('enable_float', |
python训练模型时各特征的类型
在使用python来训练模型时,会根据run_vmaf_training.py
指定的特征文件来确定是抽取float
类型的特征还是integer
类型的特征。
当feature_dict
的key为VMAF_integer_feature
时,则抽取的是integer
类型的特征,当key为VMAF_feature
时,抽取的为float
类型的特征。具体的判断逻辑位于feature_assembler.py中的FeatureAssembler.run()
。
1 | ''' 抽取各特征的integer类型特征 |
保持libvmaf和python的对应
因此,在自己训练模型的时候要特别注意:务必保证libvmaf和python两处的特征类型必须对应起来。
-
可以修改
meson_option.txt
的配置,让libvmaf
的float类型的特征生效,此时需要使用feature_dict['VMAF_feature']
来训练模型。1
2
3
4option('enable_float',
type: 'boolean',
value: true,
description: 'Compile floating-point feature extractors into the library')如上的所有改动,可以参考update.diff。
-
当然,也可以在编译的时候使用
-Denable_float=true
来开启float类型的特征支持。1
meson setup build -Denable_float=true
-
使用
feature_dict['VMAF_integer_feature']
来训练模型,此时不需要修改libvmaf的编译脚本。但是需要修改feature_extractor.py,将VmafIntegerFeatureExtractor
类中的float_ansnr
特征去掉。具体如下所示:1
2
3
4
5
6
7
8ExternalProgramCaller.call_vmafexec_multi_features(
['adm', 'vif', 'motion'],
yuv_type, ref_path, dis_path, w, h, log_file_path, logger, options={
'adm': {'debug': True},
'vif': {'debug': True},
'motion': {'debug': True},
}
)