如何在MacOS下编译vmaf并训练自己的模型

VMAF是Netflix开发的、用于评估视频感知质量的算法。VMAF包括一个独立的C语言库libvmaf及其对该库的Python包装。在Python库中,还提供了一组工具,以方便用户可以训练和测试自定义的VMAF模型。目前为止,在工业实践中,VMAF是视频质量评估领域中最优秀的全参考评估算法。

但是,在MacOS上编译并使用VMAF的过程中,发现会有一些问题导致无法编译成功,并且和模型训练相关的python代码也存在某些小的冲突,导致在整个模型训练的过程会出现某些异常。

本文就是对自己在调试过程中遇到的问题的总结。

我所使用的VMAF的版本为commit id为6f1f0c98的这次提交。遇到的所有问题也都是基于这次提交,这一点要额外注意。主要解决的问题和具体的解决方法可以参考文章接下来的部分。

libvmaf test/tools链接问题

在编译libvmaf的C库的时候,发现当编译testtools目录下的文件时,会出现异常。

经过排查以后,发现是对应的编译产出的链接库出现了异常。在编译时,如果配置default_libraryboth,则会产出libvmaf的静态链接库和动态链接库,并且在产出testtools相关对象时,会优先选择采用静态链接库进行链编。具体如下所示:

1
2
3
4
5
6
vmaf = executable(
'vmaf',
...
link_with : get_option('default_library') == 'both' ? libvmaf.get_static_lib() : libvmaf,
...
)

不确定为什么这里采用静态链接库时会出现异常,但是把静态链接库改成动态链接库之后,整个工程就可以成功编译了。至于原因,等有时间再仔细定位一下。

1
2
3
4
5
6
vmaf = executable(
'vmaf',
...
link_with : libvmaf,
...
)

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
2
3
4
#!/usr/bin/env python3

import matplotlib
matplotlib.use('Agg')

在使用libsvm训练完模型之后,会对VMAF的SRCCPCC等指标进行计算,并利用python/vmaf/config.py中的DisplayConfig.show()最终调用matplotlib来进行结果的可视化展现。但是,在DisplayConfig.show()中,却是使用是否存在参数write_to_dir来判断调用什么backends,这就会和之前的Agg配置出现冲突,因此这里需要做一个简单的升级,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if matplotlib.rcParams['backend'] == 'agg':
if 'write_to_dir' in kwargs:
format = kwargs['format'] if 'format' in kwargs else 'png'
filedir = kwargs['write_to_dir'] if kwargs['write_to_dir'] is not None else VmafConfig.workspace_path('output')
os.makedirs(filedir, exist_ok=True)
for fignum in plt.get_fignums():
fig = plt.figure(fignum)
fig.savefig(os.path.join(filedir, str(fignum) + '.' + format), format=format)
else:
format = 'png'
filedir = VmafConfig.workspace_path('output')
os.makedirs(filedir, exist_ok=True)
for fignum in plt.get_fignums():
fig = plt.figure(fignum)
fig.savefig(os.path.join(filedir, str(fignum) + '.' + format), format=format)
else:
plt.show()

实际上,只有在MacOS上才会出现该问题,因此更合理的方式是根据系统来设置Matplotlib的backends,而不是直接修改Config类。具体可以参考这里的讨论

libvmaf的特征和python中使用的特征的差异

libvmaf种各特征的类型

默认情况下,编译出来的libvmaf库使用的是integer类型的特征,具体如meson_option.txt所示:

1
2
3
4
option('enable_float',
type: 'boolean',
value: false,
description: 'Compile floating-point feature extractors into the library')

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
''' 抽取各特征的integer类型特征
feature_dict = {
'VMAF_integer_feature': ['vif_scale0',
'vif_scale1',
'vif_scale2',
'vif_scale3',
'adm2',
'motion']
}

''' 抽取各特征的float类型特征
feature_dict = {
'VMAF_feature': ['vif_scale0',
'vif_scale1',
'vif_scale2',
'vif_scale3',
'adm2',
'motion']
}

保持libvmaf和python的对应

因此,在自己训练模型的时候要特别注意:务必保证libvmaf和python两处的特征类型必须对应起来。

  1. 可以修改meson_option.txt的配置,让libvmaf的float类型的特征生效,此时需要使用feature_dict['VMAF_feature']来训练模型。

    1
    2
    3
    4
    option('enable_float',
    type: 'boolean',
    value: true,
    description: 'Compile floating-point feature extractors into the library')

    如上的所有改动,可以参考update.diff

  2. 当然,也可以在编译的时候使用-Denable_float=true来开启float类型的特征支持。

    1
    meson setup build -Denable_float=true
  3. 使用feature_dict['VMAF_integer_feature']来训练模型,此时不需要修改libvmaf的编译脚本。但是需要修改feature_extractor.py,将VmafIntegerFeatureExtractor类中的float_ansnr特征去掉。具体如下所示:

    1
    2
    3
    4
    5
    6
    7
    8
    ExternalProgramCaller.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},
    }
    )
打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2020-2024 Wang Wei
  • 本站访问人数: | 本站浏览次数:

请我喝杯咖啡吧~

微信