在FFmpeg中使用OpenVINO推理引擎

在2020年7月初,我把对OpenVINO(Open Visual Inference & Neural Network Optimization)推理引擎的调用加到了FFmpeg中,也就意味着现在FFmpeg深度学习模块的后端有三个了,分别是TensorFlow、OpenVINO和Native,如下图所示。之前已经对TensorFlow和Native后端有过一些介绍,本文对如何使用OpenVINO后端做个简单介绍。


file
  • 编译和安装OpenVINO

OpenVINO是Intel发布的一套深度学习框架,支持多种模型文件格式,包括Tensorflow、 Caffe、ONNX、MXNet、Kaldi和Torch(通过ONNX中转)等,也支持各种Intel硬件,包括CPU、GPU、FPGA、Movidius神经计算棒等。由于FFmpeg要求调用的库必须提供C API,而刚好OpenVINO在2020年发布版本中增加了这样的接口。再加上OpenVINO后端相对于TensorFlow后端可以提供更多的模型格式支持,而且可以更多更好的支持各种底层硬件。所以,FFmpeg社区接受了OpenVINO中的推理引擎作为一个新的深度学习后端。

编译OpenVINO推理引擎的具体操作如下所示,我的所有操作都在Ubuntu 18.04上进行。也可以参考官方文档https://github.com/openvinotoolkit/openvino/blob/master/build-instruction.md

OpenVINO使用CMake的方法,要求cmake版本是3.11或以上,
而Ubuntu 18.04默认cmake版本是3.10.2,所以,需要先升级cmake
$ wget https://github.com/Kitware/CMake/releases/download/v3.15.3/cmake-3.15.3.tar.gz
$ tar zxvf cmake-3.15.3.tar.gz 
$ cd cmake-3.15.3/
$ ./bootstrap
$ make
$ sudo make install
$ cmake --version
cmake version 3.15.3

然后下载OpenVINO源代码
$ git clone https://github.com/openvinotoolkit/openvino.git

由于openvino还用到了第三方库作为git的子模块,所以,还需要将这些子模块的代码也下载下来
$ cd openvino/
$ git submodule update --init --recursive

安装编译需要的依赖
$ ./install_dependencies.sh 

准备编译需要的目录
$ mkdir build
$ cd build/

由于OpenVINO功能广泛,默认选项会打开所有的支持,
这里只启用CPU硬件(ENABLE_MKL_DNN=ON),其他的做关闭OFF处理。
如果要启用GPU的话,则需设置ENABLE_CLDNN=ON,同时确保OpenCL驱动已安装,可用clinfo来检验。
其他的选项介绍,这里不再展开。
$ cmake  \
        -DENABLE_MKL_DNN=ON \
        -DENABLE_GNA=OFF \
        -DENABLE_CLDNN=OFF \
        -DENABLE_MYRIAD=OFF \
        -DENABLE_VPU=OFF \
        -DENABLE_OPENCV=OFF \
        ..

执行make开始编译。说明一下,在cmake和make阶段,都会自动下载需要的代码依赖,无需人工介入。
编译时间较长,请耐心等候。
$ make

我们可以看到默认被安装到/usr/local/deployment_tools/inference_engine/目录下,
记下这个位置,后面在编译FFmpeg的时候会用到。
$ sudo make install
...
-- Installing: /usr/local/lib/pkgconfig/gflags.pc
-- Installing: /usr/local/deployment_tools/inference_engine/lib/intel64/libinference_engine_c_api.so
-- Set runtime path of "/usr/local/deployment_tools/inference_engine/lib/intel64/libinference_engine_c_api.so" to ""
-- Up-to-date: /usr/local/deployment_tools/inference_engine/include/
-- Installing: /usr/local/deployment_tools/inference_engine/include//c_api
-- Installing: /usr/local/deployment_tools/inference_engine/include//c_api/ie_c_api.h
  • 重新编译FFmpeg

在默认编译选项下,FFmpeg不支持OpenVINO后端,所以,我们需要重新编译FFmpeg。具体过程如下。

首先获取源代码
$ git clone https://git.ffmpeg.org/ffmpeg.git

准备编译目录
$ cd ffmpeg/
$ mkdir build
$ cd build/

在ffmpeg的configure脚本中,
会生成、编译然后运行一个简单的程序来检测openvino在当前系统中是否存在,
所以,我们要先设置LD_LIBRARY_PATH
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/:/usr/local/deployment_tools/inference_engine/lib/intel64/:/usr/local/deployment_tools/inference_engine/external/tbb/lib/ 

由于openvino的默认安装位置不在系统目录中,所以还需要为configure指出头文件和库文件的位置
$ ../configure --enable-libopenvino --extra-cflags=-I/usr/local/deployment_tools/inference_engine/include/ --extra-ldflags=-L/usr/local/deployment_tools/inference_engine/lib/intel64
$ make

可以看到编译结果如下
$ ls
config.asm  doc      ffmpeg    ffprobe    fftools     libavdevice  libavformat  libswresample  Makefile  tests
config.h    ffbuild  ffmpeg_g  ffprobe_g  libavcodec  libavfilter  libavutil    libswscale     src

再提一句,FFmpeg中无法同时支持tensorflow后端和openvino后端,因为tensorflow c库将静态连接的hwloc的一些symbol也暴露出来了,和openvino的动态链接放在一起后,会在运行时产生混乱,详见https://github.com/tensorflow/tensorflow/issues/40830

  • 准备模型

在OpenVINO的model zoo中,和图像处理的模型文件有三个,分别是两种分辨率下的图像超分和一个文字超分模型,详见https://docs.openvinotoolkit.org/2020.3/usergroup9.html。我们只关注图像处理相关模型,是因为目前FFmpeg中没有基于深度学习模型的图像分析的filter,只有图像处理的通用filter,即dnn_processing,也因此我们使用dnn_processing作为演示的例子。

但是,这三个模型要求的输入,和目前dnn_processing支持的输入有点区别,比如,现在dnn_processing假设每个模型只有一个输入,而这两个图像超分模型要求有两个输入,另外,dnn_processing假设float类型的范围是[0.0, 1.0],而这三个模型则要求用[0.0, 255.0]来表示。所以,这三个模型都无法直接使用。当然,我也在考虑,如何为dnn_processing增加更多输入输出支持的灵活性,这是后话。

由于dnn_processing一开始对于输入输出的设计是基于tensorflow模型文件,所以,我们就选择使用tensorflow格式模型,然后将其转换为openvino格式,再来使用。我们选择之前介绍过的srcnn模型,此模型的输入输出图片的分辨率是相同的,模型的生成方法见之前介绍点击进入,也可以直接从https://github.com/guoyejun/dnn_processing/tree/master/models下载得到srcnn.pb模型文件。

我们知道,卷积层的一个特点是对输入图像size没有要求,所以,我们往往能够训练出适合多种分辨率的模型文件。比如srcnn.pb文件,其输入的shape是[ 1 -1 -1 1],第一个1表示一张图片,最后一个1表示一个通道,即灰度图,而中间的-1,-1表示图片的高宽尺寸是任意可选的。但是,在openvino格式中,必须要指定输入shape,不可以用-1表示size可变,而必须要用一个具体的数值。那么,openvino还支持可变size吗?答案是支持的,虽然模型文件中要指定具体size数值,但是,在推理运行时,还可以动态的修改这个size值,达到可变的效果,详见https://github.com/openvinotoolkit/openvino/issues/522中的讨论。

现在,让我们回到之前git clone到的openvino代码树下,执行以下操作,将srcnn.pb模型文件,转换为openvino支持的模型文件,会得到两个文件,srcnn.xml和srcnn.bin。实际上,这两个模型文件我也已经放在刚才的网址中了,和srcnn.pb文件放在一起。

$ cd your_path_to_openvino/model-optimizer

如前所述,我们必须要给定一个输入shape,
具体数值和我们后面的ffmpeg命令行参数相关
$ python3 mo_tf.py --input_model /yourpath/srcnn.pb --data_type=FP32 --input_shape [1,960,1440,1] --keep_shape_ops

查看生成结果
$ ls -s srcnn.xml srcnn.bin
32 srcnn.bin  12 srcnn.xml

模型转换后,输入的变量名保持不变,还叫x,输出变量名则变成了srcnn/Maximum。

  • 执行模型

然后,回到ffmpeg的编译目录,使用dnn_processing调用openvino进行超分模型的推理,命令如下所示。

$ cd /your_path_to_ffmpeg/build/

输入图片480p.jpg的size是720*480,
用到了3个filter,分别是format,scale和dnn_processing,
其中format用来将图片格式转换为yuv420p,这也是这个超分模型所需要的,因为它只处理Y通道。
scale则将图片放到2倍,到1440*960,这个数字对应着我们之前做模型转换使用的input_shape参数。
dnn_processing的参数,其中dnn_backend表示调用openvino推理引擎,model则指出模型文件(.bin文件要在同个目录下),input和output则分别是模型的输入输出的变量名。
$ ./ffmpeg -i 480p.jpg -vf format=yuv420p,scale=w=iw*2:h=ih*2,dnn_processing=dnn_backend=openvino:model=/your_path/srcnn.xml:input=x:output=srcnn/Maximum -y srcnn.ov.jpg

OpenVINO还有很多优化选项,将在后续持续启用,后续也将增加更多的基于深度学习的视频分析用的filter,比如目标检测,车牌识别等。

  • 做个广告

之前参与写了一本书,《OpenCV深度学习应用与性能优化实践》,已由机械工业出版社在2020年6月出版。在成书过程中,我提了无数的意见和一些建议,算是本书主要架构的贡献者。另外,主写了 1.2 机器学习的数学视角,2.4 DNN引擎层(部分内容),第3章 并行计算与GPU架构(包括并行计算浅谈,Intel GPU硬件计算架构,AOS和SOA两种思路,以及cl_intel_subgroups在Intel GPU上的参考实现等),6.2 Halide后端的实现,7.2 TensorBoard:助力TensorFlow程序的理解和调试。下面是宣传海报,欢迎转发,感谢支持。

file

以上内容是本人业余时间兴趣之作,限于水平,差错难免,仅代表个人观点,和本人任职公司无关。

本文首发于微信公众号:那遁去的一

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,271评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,725评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,252评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,634评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,549评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,985评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,471评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,128评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,257评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,233评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,235评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,940评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,528评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,623评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,858评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,245评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,790评论 2 339