视频绿幕抠像应用:用FastDeploy部署RVM拯救视频剪辑师的发量

视频绿幕抠像应用:用FastDeploy部署RVM拯救视频剪辑师的发量

本项目为自动抠像,不管背景是什么,都可以抠像成绿幕视频。上传视频或图片,一键抠图抠像!将绿幕视频下载后,就可以用视频编辑软件进行透底与合成操作了。

苹果系统下可以使用系统自带的iMovie进行编辑,Windows下更有多种软件可以进行编辑,请自行搜索下载。当然还可以使用PE等专业视频编辑软件。

遗憾之处是AIStudio新版的应用部署只能用cpu,这样7秒的视频需要渲染7分钟(高端版cpu版本需要3分钟),有点慢。优点是不用运行项目,不需要编程知识,只要在应用页面上传视频并“提交”即可。如果想加快速度(比如在调试项目的时候,需要多次调用执行),就到notebook里面使用GPU来处理吧。

技术选型,使用FastDeploy部署,抠像模型选择明星产品RVM(未来会尝试PP-Matting模型)。
关于RVM模型具体部署,参考文档:https://github.com/PaddlePaddle/FastDeploy/tree/develop/examples/vision/matting/rvm/python

步骤分解,整个工作分为两部分:

  • 1、 在notebook下调通
  • 2、 在应用中部署调通

效果图:

一、在notebook下调通RVM视频抠像

FastDeploy是一款全场景、易用灵活、极致高效的AI推理部署工具。提供📦开箱即用的云边端部署体验, 支持超过 🔥150+ Text, Vision, Speech和跨模态模型,并实现🔚端到端的推理性能优化。包括图像分类、物体检测、图像分割、人脸检测、人脸识别、关键点检测、抠图、OCR、NLP、TTS等任务,满足开发者多场景、多硬件、多平台的产业部署需求。github地址:https://github.com/PaddlePaddle/FastDeploy 【AI快车道-FastDeploy推理部署套件系列直播课】:https://aistudio.baidu.com/aistudio/course/introduce/27800

1、安装FastDeploy环境

FastDeploy提供各平台预编译库,供开发者直接下载安装使用,不过对cpu和GPU平台,最快捷的方法是直接使用pip install进行安装。最终“应用部署”AIStudio提供的是cpu环境,不过调试的时候为了加快速度,可以使用gou版本,

!pip install fastdeploy-gpu-python -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html
# !pip install fastdeploy-python -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html

2、运行官方RVM抠像测试代码

RobustVideoMatting是明星抠像模型,具体效果可以参见我以前的项目拍电影没有绿幕,AI给我们造!超强的稳定视频抠像RVM ,FastDeply 部署文档:
https://github.com/PaddlePaddle/FastDeploy/blob/develop/examples/vision/matting/rvm/python/README.md

  • 首先下载RobustVideoMatting模型文件、测试图片以及视频。
    将文件存放在~/work目录
%cd work
# 下载RobustVideoMatting模型文件和测试图片以及视频
## 原版ONNX模型
!wget https://bj.bcebos.com/paddlehub/fastdeploy/rvm_mobilenetv3_fp32.onnx
## 为加载TRT特殊处理ONNX模型
!wget https://bj.bcebos.com/paddlehub/fastdeploy/rvm_mobilenetv3_trt.onnx
!wget https://bj.bcebos.com/paddlehub/fastdeploy/matting_input.jpg
!wget https://bj.bcebos.com/paddlehub/fastdeploy/matting_bgr.jpg
!wget https://bj.bcebos.com/paddlehub/fastdeploy/video.mp4
%cd ~/
  • 下载FastDeploy源代码,主要是需要使用这个文件https://github.com/PaddlePaddle/FastDeploy/blob/develop/examples/vision/matting/rvm/python/infer.py
    本项目已经将抠像使用的infer.py文件放入~/work目录,可省去下载源代码这步。
    最终在应用部署中使用的是修改后的代码,存为~/work/rvm.py文件。
# !git clone https://github.com/PaddlePaddle/FastDeploy
# !git clone https://gitee.com/PaddlePaddle/FastDeploy

3、RobustVideoMatting Python部署示例

测试时发现自己拍的视频无法正常抠像,表现为生成的视频文件只有几百个字节。经测试和读源码,发现视频抠像的输入限定大小为1080 * 1920的竖构图格式,请使用的时候注意。大部分手机录视频都支持这个格式,选好即可。大家快拿起手机,发挥自己的创意吧!

推理成功后,会在work目录生成alpha.mp4和composition.mp4两个文件,一个是绿幕视频,一个是叠加背景图的视频。

%cd ~/work/
# CPU推理
## 图片
!python infer.py --model rvm_mobilenetv3_fp32.onnx --image matting_input.jpg --bg matting_bgr.jpg --device cpu
## 视频 因cpu下速度较慢,不进行测试
# !python infer.py --model rvm_mobilenetv3_fp32.onnx --video video.mp4 --bg matting_bgr.jpg --device cpu
# GPU推理
## 图片
!python infer.py --model rvm_mobilenetv3_fp32.onnx --image matting_input.jpg --bg matting_bgr.jpg --device gpu
## 视频
!python infer.py --model rvm_mobilenetv3_fp32.onnx --video video.mp4 --bg matting_bgr.jpg --device gpu
# TRT推理
## 图片
!python infer.py --model rvm_mobilenetv3_trt.onnx --image matting_input.jpg --bg matting_bgr.jpg --device gpu --use_trt True
## 视频
!python infer.py --model rvm_mobilenetv3_trt.onnx --video video.mp4 --bg matting_bgr.jpg --device gpu --use_trt True
%cd ~/
# gpu 29s
# !cd ~/work && python infer.py --model rvm_mobilenetv3_fp32.onnx --video video.mp4 --bg matting_bgr.jpg --device gpu
# 测试手机视频抠像
# !cd ~/work && python infer.py --model rvm_mobilenetv3_fp32.onnx --video test.mp4 --bg matting_bgr.jpg --device gpu
# cpu174秒
# !cd ~/work && python infer.py --model rvm_mobilenetv3_fp32.onnx --video video.mp4 --bg matting_bgr.jpg --device cpu

4、将整个应用在notebook下跑通

这里其实走弯路了,一开始只完成了前三步,就直接在“应用”中进行调试了,而没有在notebook下全面调试代码。导致的问题就是:

  • 没有拆解问题,导致“应用中”问题层出不穷
  • 在“应用中”调试耗时耗力
  • 一些代码问题和“应用多线程”问题交织在一起,干扰了问题的定位

在走过一些弯路后,才明白,应该首先在notebook下将所有函数和流程全部调通,也就是除streamlit图像、视频展示和上传文件等必须在“应用”中调试之外,其它所有代码都可以在notebook阶段调通并且应该在notebook阶段调通,否则就会很浪费时间。

具体就是如下几部分代码调通:

  • 将官方RVM主代码infer.py文件修改为可调用函数。

def rvmmatting(video=None, image=None, bg=None, device="cpu", use_openvino=False ):

初期主要是写rvmmatting功能函数,后期主要是解决rvmmatting函数在多线程下存储文件的问题。

  • 多线程存储文件问题,初期采用固定文件名会有问题(这个会在“应用”调试时暴露比较彻底),后期采用tmpfile函数辅助
        video_alpha = tempfile.NamedTemporaryFile(delete=True)
        video_composition = tempfile.NamedTemporaryFile(delete=True)
        video_alpha_name = video_alpha.name + ".mp4"
        video_composition_name = video_composition.name + ".mp4"
        cap = cv2.VideoCapture(video)
        fps =int(cap.get(cv2.CAP_PROP_FPS))
        # Define the codec and create VideoWriter object
        fourcc = cv2.VideoWriter_fourcc(*'mp4v')
        composition = cv2.VideoWriter(video_composition_name, fourcc, fps,
                                    (1080, 1920))
        alpha = cv2.VideoWriter(video_alpha_name, fourcc, fps, (1080, 1920))

  • 使用ffmpeg进行编码转变,以解决Chrome不支持非h264编码的问题。
                video_alpha = tempfile.NamedTemporaryFile(delete=False)
                video_alpha_name = video_alpha.name + ".mp4"
                os.system(f'ffmpeg -y -i {out["video_alpha_name"]} -vcodec libx264  -strict -2 {video_alpha_name}')

首先考虑的是直接用opencv进行格式转变,但是默认安装的opencv不支持h264编码,最终使用ffmpeg进行编码转变。

二、应用部署

BML CodeLab提供用户创建应用、调试应用和部署应用等功能。相关功能以Streamlit作为底层技术,为用户提供快速搭建交互式图形化界面的能力,只需要几行代码即可搭建一个炫酷的图形化界面。

部署核心可分为三步:

  • BML CodeLab启动页新增应用创建工具选项。点击该选项,即在文件列表自动创建一个带有皇冠标识的应用文件,文件默认命名为untitled.streamlit.py
  • 调试应用,双击应用文件,即可开始编写并调试应用代码。
  • 部署应用
    实际操作中,在部署前还需要先将代码块在notebook中调通,以提高后面的部署效率。

1、首先修改infer.py文件,以便在应用中使用

如前面所述,这步应该在notebook里面先调通。

主要是将infer.py文件的主体部分改写到rvm.py文件rvmmatting函数中,并加入if __name__ == "__main__" :语句,这样可以通过直接执行python rvm.py测试程序体是否正常,并方便下一步在应用中调用。

测试rvm.py文件执行是否正常

使用python rvm.py进行测试。测试通过。

后来进行了速度测试,比较观看openvino是否能加速。
运行速度cpu 181秒 openvino 398秒
GPU 27秒
发现openvino不仅没快,反而更慢了,个人认为是自己配置不对,或者AIStudio没有支持openvino导致,或者AIStudio的虚拟化影响了openvino的性能。

经过这次测试,决定在应用中,老老实实用cpu推理就行了。

!cd ~/work && python rvm.py

测试调用rvmmatting函数

通过设置video和image参数,可以分别测试抠图和抠像部分。两个参数均设置,则抠图和抠像一起执行。
测试成功

%cd ~/work
from rvm import rvmmatting
# import cv2

input_image= "matting_input.jpg"
argsbg = "matting_bgr.jpg"

argsvideo = "video.mp4"

rvmmatting( video=argsvideo, image=input_image, bg=argsbg )
# rvmmatting( video=argsvideo, bg=argsbg )
# rvmmatting(image=input_image, bg=argsbg, device="gpu")
%cd ~/

在“应用”多线程的情况下,原来官方代码固定存盘文件名会导致文件冲突的问题,所以要使用tmpfile库来解决该问题。

回过头来看,这步如果提前在notebook下调通,将能节省大量的时间!

2、用“应用创建工具”创建应用

参考文档:https://ai.baidu.com/ai-doc/AISTUDIO/Gktuwqf1x#应用

主要思路就是按照执行顺序,写好:视频上传、视频处理和输出展示3个部分。其中视频处理主要就是前面将的rvm.py文件,而视频上传和输出展示,本身是挺简单的,只需要几句话就行,但是在多线程的情况下,视频需要用tmpfile来实现非固定式名字,以免同文件名导致冲突。在实践中,发现“应用”的文件空间是共享的,所以图片的存储也需要不同的文件名,否则也会发生冲突,导致出现生成图片并不是“自己上传图片”的怪事。

前面讲过,Chrome只支持mp4里面的h264编码,怎么进行编码转换,这里花了较多的时间调试和排查。

具体可以查看源文件:~/work/app.streamlit.py

BML CodeLab启动页新增应用创建工具选项。

点击该选项,即在文件列表自动创建一个带有皇冠标识的应用文件,文件默认命名为untitled.streamlit.py,在本项目中修改名字为app.streamlit.py,当然这都不重要。

调试应用

双击应用文件,即可开始编写并调试应用代码。

如前面所述,除了图片视频上传、显示等,需要在“应用”中调试,其它代码都可以在notebook下调试。

需要注意的的几点:

  • 本地运行和“浏览器打开”的时候,需要提前安装好相关库,对本项目来说,需要提前在notebook或控制台安装好FastDeploy库。
  • 本地运行和“浏览器打开”的时候,不管app.streamlit.py文件在哪个目录,运行环境的根目录都是在项目根目录~/
    也就是如果大家fork了这个项目,在本地运行“应用”的时候,需要把work目录里的文件cp到~/根目录,否则会报错文件找不到。

部署应用

部署的时候,需要在requirements.txt文件中写入需要安装的库文件,比如fastdeploy-python -f https://www.paddlepaddle.org.cn/whl/fastdeploy.html

部署之后,运行环境的根目录就是部署时设定的那个目录。

因为部署采用了多线程,所以普通的文件存盘可能会发生问题,解决的方法就是用tmpfile,也就是随机文件名并放入/tmp目录中。

好了,大家也来应用里面试用下吧,点击上传,一键抠图抠像,妈妈再也不用担心我的头发啦!

调试

Matting的文档比较简单

想偷懒,直接用FastDeploy封装的一句话搞定,但是光看文档,不知道该怎么办,看API文档,也太简略了,连例子都没有。最终解决的方法,看infer.py源文件,并进行适当修改。

视频抠图的时候输出很多无用信息

WARNING:root:DEPRECATED: fastdeploy.vision.swap_background_matting is deprecated, please use fastdeploy.vision.swap_background function instead.

根据提示,把fastdeploy.vision.swap_background_matting替换成fastdeploy.vision.swap_background即可。

自己上传的视频无法转换成功

发现自己的视频格式是:编解码器:AAC,H.264
成功的那个视频格式是:MPEG-4 Video
再仔细看,发现是自己的背景图720.jpeg,代码里一直写的720.jpg,怪不得一直报错。

修改过文件名之后,经测试,不同大小的背景图都ok。但h.264格式视频还是无法抠像。

最终发现是需要固定1280 * 1920大小的视频才能转换成功。而背景图的大小不受限。至于编码格式,H.264 和MPEG-4 Video都是可以的。

在应用中同时写两个上传控件报错:

原来如果写两个上传控件,需要设置一个key参数,如:

per_image = st.file_uploader("上传图片", type=['png', 'jpg', 'jpeg'],           label_visibility='hidden', key="x1")
per_image_bgr = st.file_uploader("上传图片", type=['png', 'jpg', 'jpeg'],           label_visibility='hidden', key="x2")

在引用浏览器测试的时候,碰到图像斜向扭曲

好像以前也碰到过,但是忘记是怎么回事了? 好像横纵比例不对导致的?点击图片在新页面打开,发现是好的。偶尔会碰到,不去管它了。

项目调试报错:ModuleNotFoundError: No module named ‘fastdeploy’

明明已经在requirements.txt文件中写入预安装Fastdeploy库了,但是应用启动后就是报没有这个库的错。

我感觉可能是我文件名字写错了,或者有拼写错误。
发现问题了,原来是requirements.txt文件名写错了,真是醉了,

应该是:requirements.txt,写成了requirements.py

问:如何切换模型推理后端

答:FastDeploy中各视觉模型可支持多种后端,包括

  • OpenVINO (支持Paddle/ONNX两种格式模型, 仅支持CPU上推理)
  • ONNX Runtime (支持Paddle/ONNX两种格式模型, 支持CPU/GPU)
  • TensorRT (支持Paddle/ONNX两种格式模型,仅支持GPU上推理)
  • Paddle Inference(支持Paddle格式模型, 支持CPU/GPU)
import fastdeploy as fd
option = fd.RuntimeOption()

# 切换使用CPU/GPU
option.use_cpu()
option.use_gpu()

# 切换不同后端
option.use_paddle_backend() # Paddle Inference
option.use_trt_backend() # TensorRT
option.use_openvino_backend() # OpenVINO
option.use_ort_backend() # ONNX Runtime

应用在一个浏览器Safari正常另一个Chrome浏览器不正常

刚开始误以为是非作者账户下应用有问题,绕了很大的弯路,才确定原因:Chrome浏览器不显示MPEG-4 Video编码格式视频。

Chrome浏览器只支持H264格式,本想在python代码里直接使用cv代码生成该格式,后来发现需要重新编译cv或ffmpeg,这个在AIStudio,尤其是在“应用里面”不现实。解决的方法为:使用ffmpeg转换格式,具体见后面。

具体来说,我测试了如下格式:

fourcc = cv2.VideoWriter_fourcc(*'mp4v')
fourcc = cv2.VideoWriter_fourcc(*'H264')
fourcc = 0x00000021
# fourcc = cv2.VideoWriter_fourcc(*"MP42")
# fourcc = cv2.VideoWriter_fourcc(*'H265')
# fourcc = cv2.VideoWriter_fourcc(*'DAVC')
# fourcc = cv2.VideoWriter_fourcc(*'I420')
# fourcc = cv2.VideoWriter_fourcc('H', 'E', 'V', 'C')

获得的新知识就是;

  • fourcc就是4字符编码配置,可以分开写,也可以用* 号加字符串;要全部大写或小写
  • fourcc编码配置还需要ffmpeg支持,若不支持会报错
  • 谷歌Chrome只支持h264(我的理解应该是mpg4里只支持这一种编码)

编码h264报错为:

OpenCV: FFMPEG: tag 0x34363248/'H264' is not supported with codec id 27 and format 'mp4 / MP4 (MPEG-4 Part 14)'
OpenCV: FFMPEG: fallback to use tag 0x31637661/'avc1'
[ERROR:0@3614.785] global /io/opencv/modules/videoio/src/cap_ffmpeg_impl.hpp (2927) open Could not find encoder for codec_id=27, error: Encoder not found
[ERROR:0@3614.785] global /io/opencv/modules/videoio/src/cap_ffmpeg_impl.hpp (3002) open VIDEOIO/FFMPEG: Failed to initialize VideoWriter

Chrome浏览器不支持h264以外编码的解决方法

将视频其它编码转为h264编码。

解决的方法,可以只用这句话:ffmpeg -i out.mp4 -vcodec libx264 -acodec aac output.mp4

在应用中,在python代码中,可以使用os.system()执行上面转换语句。

报错could not find a writer for the specified extension in function ‘imwrite_’

解决方法:保存图片记得加上拓展名字bmg/img/jpg均可

应用中调用rvmmatting函数,发现生成的视频文件不见了

主要是的问题是修改rvm.py文件后,在应用中并没有及时体现,也就是好像代码被缓存了似的。

因为“代码被缓存”,导致调试的时候走了很多弯路,最终也没有确定是否是delete=True参数导致的文件没有存下来,不过后来使用了加后缀名的方法,使文件能够长久保存。当然后面还要解决过期后删除的问题。

痛定思痛,还是要优化“应用”的开发和调试最优路径

应用开发中,需要经历如下几个步骤:notebook调通,“应用运行”调通,“在浏览器打开”调通,以及“应用部署”调通,“应用部署”后非作者账户调通等五个步骤,且应用部署和之后的调试,都不支持gpu,在处理需要较长时间的时候,尤其是处理视频的时候。

最优开发路径

  • notebook调通,所有的函数全调通。除了streamlit图像、视频展示和上传文件等,其它操作可以全部在notebook阶段调通
  • 应用运行调通。要注意运行的目录,不管xx.streamlit.py文件在哪个目录执行,根目录都是~/目录。相关库需要在notebook或终端pip安装。
  • “在浏览器打开”调通,相关库需要写入requirements.txt文件中,根目录在~/目录,可以使用gpu。
  • “应用部署”调通,相关库需要写入requirements.txt文件中,根目录为部署时“部署包目录”,临时文件建议使用python tempfile方法创建,这个在第一步notebook环境下测试较好,否则直接往当前目录写,可能会(文件乱套会让人怀疑人生)存在问题。只能使用cpu。
  • “应用部署”后非作者账户调试,本步骤可以忽略,但确实可以发现不同浏览器的问题,比如Chrome不支持h264编码之外的mp4视频。

排除掉不确定因素之后,应用还是挺容易调通的。
不确定因素有:执行根目录问题;依赖库requirements.txt问题,临时文件读写问题等。

应用中测试时发现ffmpeg转换的文件不在

手工测试,在命令行测试的时候,发现报错
[aac @ 0x1ad4820] The encoder 'aac' is experimental but experimental codecs are not enabled, add '-strict -2' if you want to use it.
于是加上该选项。另外如果有同名文件存在的话,它会问是否覆盖,估计这也是前面测试一直失败的原因。

同时还找到另外一个问题,就是上传的测试视频是1920 * 1080的横构图(一直误以为它是1080 * 1920 ),这样抠像就会失败,不会输出视频,进而导致ffmpeg转换的时候报错。虽然是一个小疏忽,但是调试中简直怀疑人生!

应用测试中发现切换图片后报错

一开始代码中并没有针对切换图片就行相应修改,导致上传图片后参与抠图的图片也不会变。

修改代码后,发现上传图片报错:

AttributeError: 'NoneType' object has no attribute 'read'
Traceback:
File "/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 562, in _run_script
    exec(code, module.__dict__)
File "/home/aistudio/work/app.streamlit.py", line 47, in <module>
    tfileper_image_bgr.write(per_image.read())

tfileper_image_bgr = tempfile.NamedTemporaryFile(delete=True)修改为tfileper_image_bgr = tempfile.NamedTemporaryFile(delete=False)
上面报错问题解决,出现新的报错

报错AttributeError: ‘NoneType’ object has no attribute ‘read’

AttributeError: 'NoneType' object has no attribute 'read'
Traceback:
File "/usr/local/lib/python3.7/dist-packages/streamlit/runtime/scriptrunner/script_runner.py", line 564, in _run_script
    exec(code, module.__dict__)
File "/home/serving/a1671975443390/app.streamlit.py", line 46, in <module>
    tfileper_image_bgr.write(per_image.read())
    

查看创建文件语句,感觉这里还是要加后缀啊!

tfileper_image = tempfile.NamedTemporaryFile(delete=False)  # 创建可删除文件
        tfileper_image.write(per_image.read())
        uploadimage = tfileper_image.name

全部加上后缀,问题解决:

    if per_image:
        st.image(per_image)
        tfileper_image = tempfile.NamedTemporaryFile(delete=True)
        uploadimage = tfileper_image.name+per_image.name
        cur_img = Image.open(per_image)
        cur_img.save(uploadimage)

想加上定时删除功能,失败

想像普通程序那样使用time.time()来定时删除临时图片和视频文件,但是没有成功。
我认为原因是那个时间基数在streamlit里也在不停的在走啊。
即类似这样的语句在应用中失效:

# 超过1小时后,删除视频文件
                deletetime = time.time()
                if time.time()-deletetime > 30:
                    for i in out:
                        os.system(f"rm {out[i]}")

版本

0.11 2022.12.25日,终于调试通过,可以在Chrome浏览器下正常使用了!

结束语

让我们荡起双桨,在AI的海洋乘风破浪!

飞桨官网:https://www.paddlepaddle.org.cn

因为水平有限,难免有不足之处,还请大家多多帮助。

作者:段春华, 网名skywalk 或 天马行空,济宁市极快软件科技有限公司的AI架构师,百度飞桨PPDE。

我在AI Studio上获得至尊等级,点亮10个徽章,来互关呀~ https://aistudio.baidu.com/aistudio/personalcenter/thirdview/141218

此文章为搬运
原项目链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值