ffmpeg 分辨率 压缩_用GPU加速FFmpeg中的超分辨率功能

5b8e85ac64ef46173a07458ab205d574.png

1. 简要回顾

首先简单复述一下FFmpeg中对深度学习的支持情况,如上图所示,FFmpeg在libavfilter中支持基于深度学习的filter,目前已经支持sr, derain和dnn_processing等filter,其中,dnn_processing是一个通用的filter,涵盖了sr和derain的功能,本文将要介绍的超分辨率(Super Resolution)功能也将使用dnn_processing来完成。

为了实现模型推理功能,FFmpeg提供了三种不同的方式(被称为后端backend),分别是native 后端、tensorflow后端和openvino后端。native后端的所有代码实现都在FFmpeg代码树中,目前以C语言的形式存在,可以跑在各种host端CPU上。tensorflow后端是指FFmpeg调用动态库libtensorflow.so进行模型加载和推理,可以跑在x86 cpu、NV GPU等各类计算设备上。openvino后端是指FFmpeg调用动态库libinference_engine_c_api.so进行模型加载和推理,可以跑在x86 cpu、Intel GPU等各类计算设备上。顺便提一下,由于FFmpeg的要求,不能调用C++接口,所以这些动态库都是提供C语言接口的库文件。

另外,在filter和后端之间,设计了一个用来解耦的接口层DNN interface,这样,filter可以很方便的从这个后端切换到另外一个后端,方便FFmpeg的开发者和用户无需修改代码,只需简单修改参数即可无缝切换到不同的计算设备上。

接下来将介绍如何使用tensorflow后端在NV GPU上加速Super Resolution,以及如何使用OpenVINO后端在Intel GPU上加速Super Resolution。

2. 资料准备

Super Resolution最本质上就是对视频图片的放大,在深度学习技术的加持下效果更好。我们采用ESPCN模型(Efficient Sub-Pixel Convolutional Neural Network model),这是论文地址https://arxiv.org/abs/1609.05158。这个模型的实现非常简洁,用了4层,依次是64个5x5的卷积层,32个3x3的卷积层,4个3x3的卷积层,卷积层的参数都是same,维持feature map尺寸不变;最后一层是depth2space层,将最后的4个feature map转换为长宽都乘以2的一张图片。

所有的模型文件和测试码流都已经放在了https://github.com/guoyejun/dnn_processing/tree/master/sr1080p, 可以直接下载。其中,onemin960x540.mp4是时长1分钟960x540分辨率的一段码流,用于输入测试;espcn.pb是tensorflow格式的模型文件;我们通过OpenVINO提供的格式转换工具,将espcn.pb文件转换成OpenVINO的格式,由于一些限制,OpenVINO格式文件对输入图片的大小有具体的数值要求(这个限制可以在OpenVINO后端中解决,但是尚未完成),所以,我们将使用espcn1080p.bin和espcn1080p.xml模型文件,来实现将输入的960x540分辨率的码流,转换成1080p(1920x1080分辨率)的码流。

要使用TensorFlow后端,只需要下载onemin960x540.mp4和espcn.pb;要使用OpenVINO后端,则需要下载onemin960x540.mp4、espcn1080p.bin和espcn1080p.xml。

3. 用NV GPU加速SR功能

要用NV GPU,软件库的调用关系是:FFmpeg -> TensorFlow -> cuDNN -> CUDA。其中的TensorFlow必须是提供C语言接口的库文件,而通过pip install tensorflow命令安装的软件包里面并不包含c接口的库。为了得到c接口的库文件,一种方法是我们从TensorFlow源代码开始编译出c接口库文件,但是往往涉及到各种选项,并不是一件容易的事情。另外就是使用TensorFlow的预编译好的c库文件,下载其中的Linux(支持 GPU)版本。很不幸的是,目前预编译的最新2.3 GPU版本存在问题,而预编译中的上一版本则是1.15,所以,我们只能选择TensorFlow 1.15 GPU的c库文件 。

选定TensorFlow 1.15后,根据TensorFlow文档,还需要在系统中安装配套的cuDNN7.4和CUDA10.0,在原生系统中配置起来太麻烦,我们就用docker image来完成,使用NV给出的官方image。根据NV的release notes,我们找到nvcr.io/nvidia/tensorflow:18.10-py2 是我们需要的image。所以,后续操作如下所示。

// 下载docker image
$ docker pull nvcr.io/nvidia/tensorflow:18.10-py2

// 进入container,用了--rm选项,退出的时候container会被自动删除
$ nvidia-docker run --rm -it --shm-size=1g --ulimit memlock=-1 --ulimit stack=67108864 nvcr.io/nvidia/tensorflow:18.10-py2

// 以下操作都在container中进行

// 在这个container中已经支持从python调用tensorflow,但是没有c库,所以,还需要下载。
# mkdir tfclib
# cd tfclib/
// 下载gpu版本压缩包。如果这里下载的是cpu版本的压缩包,那么后续tensorflow会使用cpu进行推理。
# wget https://storage.googleapis.com/tensorflow/libtensorflow/libtensorflow-gpu-linux-x86_64-1.15.0.tar.gz
# tar zxvf libtensorflow-gpu-linux-x86_64-1.15.0.tar.gz
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/workspace/tfclib/lib/

// FFmpeg默认不支持TensorFlow后端,必须从源代码重新编译
# cd /workspace
# git clone --depth=1 https://git.ffmpeg.org/ffmpeg.git
# cd ffmpeg/
# mkdir build
# cd build/
// 准备依赖库
# apt-get update
# apt install nasm
# ../configure --enable-libtensorflow --extra-cflags="-I/workspace/tfclib/include" --extra-ldflags="-L/workspace/tfclib/lib"
# make

// 下载测试资料
# wget https://github.com/guoyejun/dnn_processing/raw/master/sr1080p/onemin960x540.mp4
# wget https://github.com/guoyejun/dnn_processing/raw/master/sr1080p/espcn.pb

// 运行测试
// 这个时候我们在host端运行nvidia-smi,会观察一些奇怪现象,不知道最新版本是否已经修复。
// 比如,这么轻量级的模型竟然花了90%以上的显存,我换成python直接运行也是如此。
// 还有,这么轻量级的模型第一次推理竟然花了十多分钟乃至数十分钟。第二次运行的一开始也等待了好久。
// 运行结束后,用ffplay等工具检查一下输出结果(即视频文件espcn.tf.gpu.mp4)是否符合预期
# ./ffmpeg -i onemin960x540.mp4 -vf format=yuv420p,dnn_processing=dnn_backend=tensorflow:model=espcn.pb:input=x:output=y -y espcn.tf.gpu.mp4 -benchmark

在有些系统中,可能会插有多块NV显卡,我们可以用下面的方法来指定使用其中的一块或者若干块显卡。首先,要用下面的python脚本生成一串字符串:

import tensorflow as tf

// 这里的参数0表示指定使用gpu0,如果是"1,2"就表示使用gpu1和gpu2。
// 需要说明的是,这里的数字,可能和nvidia-smi显示的序号不一致。
gpu_options = tf.GPUOptions(visible_device_list='0')

config = tf.ConfigProto(gpu_options=gpu_options)
s = config.SerializeToString()
b = ''.join("%02x" % int(ord(b)) for b in s[::-1])
print('0x%s' % b)

假如上述python脚本的输出是0x30012a0332,那么指定使用gpu0的FFmpeg命令行如下所示,将这个字符串作为dnn_procesing的参数传递进去。

# ./ffmpeg -i onemin960x540.mp4 -vf format=yuv420p,dnn_processing=dnn_backend=tensorflow:model=espcn.pb:input=x:output=y:options=sess_config=0x30012a0332 -y espcn.tf.gpu.mp4 -benchmark

4. 用Intel GPU加速SR功能

要用Intel GPU,目前的软件库的调用关系是:FFmpeg -> OpenVINO -> clDNN -> OpenCL。在host系统中,这些软件库都用最新版本,是可以从源代码编译出来的,而且,默认情况下,OpenVINO的c库也会被编译出来。但是,我们还是使用更加简洁的docker image方案。在https://hub.docker.com/r/openvino/ 可以看到OpenVINO官方给出的image。由于dev image中没有安装git,所以在docker run的时候要加上-u root以获得apt-get install git的权限。在container中,从FFmpeg源代码开始的过程,和上一小节非常类似,只需要将TensorFlow相关的设置修改为OpenVINO相关的设置即可。所以,我们在这里换一种方法,将这些过程写到Docker文件中。

首先,创建一个文件,文件名为DockerFile,内容如下所示,主要是在openvino/ubuntu18_dev:2021.1的基础上增加FFmpeg软件包。

From openvino/ubuntu18_dev:2021.1

USER 0
RUN apt-get update
RUN apt-get install -y git nasm wget

WORKDIR /workspace

ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/intel/openvino/inference_engine/lib/intel64:/opt/intel/openvino/inference_engine/external/tbb/lib:/opt/intel/openvino/deployment_tools/ngraph/lib

RUN git clone --depth=1 https://github.com/FFmpeg/FFmpeg ffmpeg && \
cd ffmpeg && \
./configure \
--extra-cflags=-I/opt/intel/openvino_2021/inference_engine/include/ \
--extra-ldflags=-L/opt/intel/openvino_2021/inference_engine/lib/intel64 \
--enable-libopenvino && \
make -j $(nproc) && \
make install

RUN wget https://github.com/guoyejun/dnn_processing/raw/master/sr1080p/onemin960x540.mp4 && \
wget https://github.com/guoyejun/dnn_processing/raw/master/sr1080p/espcn1080p.bin && \
wget https://github.com/guoyejun/dnn_processing/raw/master/sr1080p/espcn1080p.xml

然后,运行以下命令

// 在DockerFile所在的目录,创建image
$ docker build --network=host $(env | grep -E '_(proxy|REPO|VER)=' | sed 's/^/--build-arg /') -t openvino_ffmpeg .

// 上一步得到的image支持CPU、GPU等多个计算设备,下面的命令参数使得container只支持GPU,
// 为什么需要device参数,这是为了OpenCL驱动在container中使用的。
$ docker run -it --rm --device /dev/dri:/dev/dri openvino_ffmpeg:latest

// 下条命令在container中进行
// 运行结束后,用ffplay等工具检查一下输出结果(即视频文件espcn.ov.gpu.mp4)是否符合预期
root@b31ec026f1dc:/workspace# ffmpeg -i onemin960x540.mp4 -vf format=yuv420p,dnn_processing=dnn_backend=openvino:model=espcn1080p.xml:input=x:output=espcn/prediction:options=device=GPU -y espcn.ov.gpu.mp4 -benchmark

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/575899.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql存储过程输入参数拆分_一文看懂mysql数据库存储过程、函数、视图、触发器、表...

概述抽空总结一下mysql的一些概念性内容,涉及存储过程、函数、视图、触发器等。一、查看存储过程、函数、视图、触发器、表1、存储过程select * from mysql.proc where typePROCEDURE;show procedure status; show create procedure proc_name; //存储过程定义2、函…

oracle vm发现无效设置_Oracle数据库编译失效对象相关命令总结大全,值得收藏

概述在日常数据库维护过程中,我们会发现数据库中一些对象(包Package、存储过程Procedure、函数Function、视图View、同义词.....)会失效,呈现无效状态(INVALID)。有时候需要定期检查数据库中存在哪些失效对象,对于存在异常的对象需要重新编译&#xff0c…

WCF-001:WCF的发布

随着“云”时代的到来,“云”已经无处不在了。什么是“云”,无非就是利用互联网强大的功能建立多个服务器,然后再利用互联网的传输数据的特点将数据从某个服务器中读取出来或者将你的数据上传上去。当然这个服务器不是一定就是传统意义的服务…

在线编辑_水墨-在线 Markdown 编辑器

水墨-在线 Markdown 编辑器基于 Spring-boot、FreeMarker、layui、Vditor 构建的一款在线 所见即所得的 Markdown 编辑器。水墨-在线 Markdown 编辑器。本人使用 Vditor 编辑器时日已久,眼看着其功能日益强大,特此基于 Vditor 构建一款 Web 编辑器&#…

退出出库复核是什么意思_细思极恐!为什么是黄晓明退出而不是李菲儿?因为女方是芒果艺人...

本文转载自:娱评人吴清功序言:《乘风破浪的姐姐》第二季即将接档《姐姐的爱乐之程》,于每周五晚上十点档播出。2021年1月5日,《乘风破浪的姐姐2》第一次公演举行,选手李菲儿和发起人黄晓明有亲密互动,李菲儿…

ie6 ie7下使用clear不能将浮动的元素换行问题

在主流浏览器中使用clear方法可以轻松完成浮动元素的换行。 例如&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.o…

传值类型_Java内存管理:Stackoverflow问答-Java是传值还是传引用(十一)

勿在流沙筑高台&#xff0c;出来混迟早要还的。做一个积极的人编码、改bug、提升自己我有一个乐园&#xff0c;面向编程&#xff0c;春暖花开&#xff01;本文导图&#xff1a;一、由一个提问引发的思考在Stack Overflow 看到这样一个问题&#xff1a;Is Java “pass-by-refere…

java位运算(转)

位移动运算符: <<表示左移, 左移一位表示原来的值乘2. 例如&#xff1a;3 <<2(3为int型) 1&#xff09;把3转换为二进制数字0000 0000 0000 0000 0000 0000 0000 0011&#xff0c; 2&#xff09;把该数字高位(左侧)的两个零移出&#xff0c;其他的数字都朝左平移2位…

可以批量转modis投影_SNAP批量处理Sentinel2数据

Sentinel-2数据以其高时空分辨率获得了越来越多的应用&#xff0c;然而由于Sentinel-2数据空间分辨率高&#xff0c;光谱分辨率高&#xff0c;数据量也较Landsat数据大幅上升。好在ESA SNAP软件批处理功能也很强大&#xff0c;可以支撑起大数据量的应用。下面就介绍一下如何使用…

struts2整合uploadify插件怎样传参数

关于uploadify3.1&#xff0c;先看下帮助文档中的有些知识。 其中有个onUploadStart方法&#xff0c;我们可以使用这个向后台传参。 下面举个例子&#xff0c; js&#xff1a; <script type"text/javascript">$(function () {$(#actpic).uploadify({debug: fal…

对齐方式有那些_Excel基础:开始菜单之对齐方式,那些被遗忘的实用功能

今天小编要分享的Excel基础系列文章是"第三区块-对齐方式"。对齐方式主要是出来文字的排版问题&#xff0c;对齐方式包含的所有功能下面思维导图已经列出来。大多数功能都是我们常用的&#xff0c;也是比较简单的&#xff0c;这些功能小编就不说了&#xff0c;小编来…

来自Java空间的传送门

变量是程序中存储数据的基本单元&#xff0c;在该存储空间中&#xff0c;存储的数据值可以改变。 通过变量名可以简单快速地找到它存储的数据 使用Java的过程中我们需要注意一些细节&#xff0c;那就是Java语言的规范性了&#xff0c;比如Java的变量命名&#xff1a; 1.标识符…

来及Java空间的传送门2

上一篇文章我们学习了Java的4种基本数据类型&#xff0c;今天我们就继续学习Java中的2种结构类型&#xff0c;分别是单分支结构&#xff0c;双分支结构和多重if结构 单分支结构&#xff1a;条件表达式的值必须为boolean类型 条件为true时执行if内的代码 双分支结构&#xff1…

redis value最大值_Redis 的 maxmemory 和 dbnum 默认值都是多少?对于最大值会有限制吗?...

一、Redis 的默认配置了解 Redis 的都知道&#xff0c;Redis 服务器状态有很多可配置的默认值。例如&#xff1a;数据库数量&#xff0c;最大可用内存&#xff0c;AOF 持久化相关配置和 RDB 持久化相关配置等等。我相信&#xff0c;关于 AOF 持久化和 RDB 持久化的配置大家都很…

实现页面适配_微信公众号文章页面适配深色模式

最近安卓微信7.0.10正式版发布&#xff0c;更新过后&#xff0c;很多用户发现&#xff0c;之前在测试版中对系统深色模式的适配功能被取消了&#xff0c;小伙伴们对此很是不满&#xff0c;好在Android 10系统手机用户占比很少&#xff0c;影响范围还不是很大&#xff0c;并且也…

iframe悬浮在html上_HTML Iframe

HTML Iframeiframe 用于在网页内显示网页。添加 iframe 的语法URL 指向隔离页面的位置。Iframe - 设置高度和宽度height 和 width 属性用于规定 iframe 的高度和宽度。属性值的默认单位是像素&#xff0c;但也可以用百分比来设定(比如 "80%")。实例&#xff1a;html&…

mysql 当前timestamp_MySQL表结构使用timestamp以自动获取当前时间

一、怀念ACCESS的时代ACCESS的表结构如果想自动插入当前时间的时候&#xff0c;可以在列定义的时候输入默认值now ()就可以实现自动插入当前时间了。而MySQL则行不通&#xff0c;MySQL这个东东默认是命令行下面的产物&#xff0c;如果不是后来有了phpMyAdmin这个图形化界面东东…

[转]如何设置win7一直以管理员身份运行

如何设置win7一直以管理员身份运行 在win7有些程序需要以管理员的身份才能运行&#xff0c;但是我们几乎天天都要运行这些程序&#xff0c;老是要手动选下很麻烦&#xff0c;怎么样设置才能这个程序以后运行都直接是以管理员的身份运行&#xff0c;不用在让我们去选择了&#x…

MySQL substring-index_mysql函数之SUBSTRING_INDEX(str,/,-1)

SUBSTRING_INDEX的用法&#xff1a; •SUBSTRING_INDEX(str,delim,count) 在定界符 delim 以及count 出现前&#xff0c;从字符串str返回自字符串。若count为正值,则返回最终定界符(从左边开始)若为-1则是从后往前截取SELECT substring_index(Hn_P00001, P, -1) -- 结果是0000…

integer 负数字符串比较_JAVA源码之Integer-1

四、方法toString三个方法&#xff0c;其中两个static方法。1、public String toString()&#xff1a;该方法内部使用toString(int i)实现。2、public static String toString(int i)&#xff1a;该方法内部使用stringSize方法巧妙的获取入参的size&#xff0c;然后用getChars把…