本文章记录对RobustVideoMatting模型进行C++推理的过程。

文章目录

  • 相关参考
  • 一、基于lite.ai.toolkit的RVM推理编译
    • 1.源码编译
  • 二、推理功能改进与完善
    • 1.修改背景颜色
    • 2.灵活输入输出
    • 3.同时输出视频mask和result
    • 4.可在控制台选择模型 | 下采样比 | 推理线程数
    • 5.视频抠图可实现背景替换
  • 总结

相关参考

本文参考模型代码:
[1]RobustVideoMatting.
本文参考C++推理工具:
[2]lite.ai.toolkit-RVM.


提示:该案例运行环境为Windows+CPU环境

一、基于lite.ai.toolkit的RVM推理编译

1.源码编译

从参考【2】处下载源码后,需要使用cmake进行编译。从官网下载 cmake的GUI版本,安装成功后对RVM源码编译:

Step 1:将源码中lite.ai.toolkit\lib文件夹下的所有依赖库替换(源码中dylib是Mac系统的动态依赖库格式,Windows下是dll格式);将cmakelist.txt中不需要的推理格式(我这里仅保留onnxruntime)注释掉。

Step 2:在cmake中选择好生成路径,点击Configure编译,成功后点击Generate生成。


成功后会提示Configuring done 及 Generating done

Step 3:上述步骤完成后会发现在对应生成路径下有了sln文件。点击进入:

在这里切换版本为Release,右击ALL_BUILD生成:

成功生成后显示如下:

Step 4:下面运行一下看一看吧~
打开test_lite_rvm.cpp,如下图配置好路径后,将lite.ai.toolkit\lib文件夹下所有的dll文件拷贝到RobustVideoMatting-v1.0\examples\build\Release文件夹下

双击lite_rvm.exe,运行结果:

在logs文件夹下即可查看推理结果

以上,一个在Windows+CPU环境下的视频人像分割的C++推理demo就搞定啦~ 接下来我们就在作者原版demo上自己修改玩一下吧!

二、推理功能改进与完善

1.修改背景颜色

lite.ai.toolkit/sourceFile/rvm.cpp更改以下代码(改为白色):

  cv::Mat mbmat = bmat.mul(pmat) + rest * 255.;cv::Mat mgmat = gmat.mul(pmat) + rest * 255.;cv::Mat mrmat = rmat.mul(pmat) + rest * 255.;

重新生成lite.ai.toolkit.dll,将其copy至与exe相同目录下,得到结果:


2.灵活输入输出

按照原版本,在推理前要把待推理的视频放到resource文件夹下,即路径是写死的。现在简单改动一下,能够让用户在命令行里通过拖拽文件进行推理。

在RobustVideoMatting.lite.ai.toolkit/test_lite_rvm.cpp中,增加获取文件名函数:

//get the file's name that you input
string get_file_name(string file_path)
{int location = file_path.rfind("\\") + 1;//记录最后一次出现"\"的位置string file_name = file_path.substr(location);//提取"\"后字符串,作为文件名return file_name;
}

为test_video()和test_image()增加string类型参数,主函数调用如下:

 cout << "请输入待处理视频路径:" << endl;cin >> VideoPath;test_video(VideoPath);cout << "请输入待处理图片路径:(若无输入图片退出即可)" << endl;cin >> ImagePath;test_image(ImagePath);

重新编译后,将文件拖拽到命令行中,即可get到文件的路径,进行推理啦:


3.同时输出视频mask和result

为了方便对MIOU评价指标的计算,同时能够更好地呈现结果,现在试试同时输出mask和result吧

在lite.ai.toolkit/rvm.cpp中,修改函数detect_video,增加一输出路径,函数更改后如下:

 void RobustVideoMatting::detect_video(const std::string &video_path,const std::string &output_path,//// const std::string &output_path_mask,//std::vector<types::MattingContent> &contents,bool save_contents, float downsample_ratio,unsigned int writer_fps)
{int location = output_path.rfind("\\") + 1;const std::string fileName = output_path.substr(location);const std::string fileNameMask = "mask_" + fileName;const std::string output_path_mask = output_path.substr(0,location)+fileNameMask;// 0. init video capturecv::VideoCapture video_capture(video_path);const unsigned int width = video_capture.get(cv::CAP_PROP_FRAME_WIDTH);const unsigned int height = video_capture.get(cv::CAP_PROP_FRAME_HEIGHT);const unsigned int frame_count = video_capture.get(cv::CAP_PROP_FRAME_COUNT);if (!video_capture.isOpened()){std::cout << "Can not open video: " << video_path << "\n";return;}// 1. init video writercv::VideoWriter video_writer(output_path, cv::VideoWriter::fourcc('m', 'p', '4', 'v'),writer_fps, cv::Size(width, height));//cv::VideoWriter video_writer_mask(output_path_mask, cv::VideoWriter::fourcc('m', 'p', '4', 'v'),writer_fps, cv::Size(width, height));//if (!video_writer.isOpened()){std::cout << "Can not open writer: " << output_path << "\n";return;}//if (!video_writer_mask.isOpened()){std::cout << "Can not open writer mask: " << output_path_mask << "\n";return;}//// 2. matting loopcv::Mat mat;unsigned int i = 0;while (video_capture.read(mat)){i += 1;types::MattingContent content;this->detect(mat, content, downsample_ratio);// 3. save contents and writing out.if (content.flag){if (save_contents) contents.push_back(content);if (!content.merge_mat.empty()) video_writer.write(content.merge_mat);if(!content.pha_mat.empty())video_writer_mask.write(content.pha_mat * 255.);}// 4. check context states.if (!context_is_update) break;
#ifdef LITEORT_DEBUGstd::cout << i << "/" << frame_count << " done!" << "\n";
#endif}// 5. releasevideo_capture.release();video_writer.release();//video_writer_mask.release();//
}

接下来推一个demo试试看:

结果输出如下:

OK,实现mask和result同时输出啦!

嗷对了,记得将新生成的lite.ai.toolkit.dll复制到exe同路径下!


4.可在控制台选择模型 | 下采样比 | 推理线程数

由于不同模型及下采样比适用的效果不同,同时不同机器的CPU型号不一样,最大的推理线程数也不同。为了方便使用,我这里将这些功能集成到控制台里能够自由选择,使用时的效果如下:


5.视频抠图可实现背景替换

之前将视频中的人像分割出来以后我们仅将背景颜色做了一定修改,现在能否给视频换个背景呢?
lite.ai.toolkit作者最近将背景替换功能加入了工具箱中,现在我们将这部分功能添加到这个独立的子工程里。

重新编译lite.ai.toolkit,将最新生成的lite.ai.toolkit.dll、lite.ai.toolkit.exp、lite.ai.toolkit.lib拷贝至lite_rvm相同的目录下:

修改rvm.h中detect_video()和detect()接口:

void detect(const cv::Mat& mat, types::MattingContent& content,float downsample_ratio = 0.25f, bool video_mode = false,bool remove_noise = false, bool minimum_post_process = false);void detect_video(const std::string& video_path,const std::string& output_path,std::vector<types::MattingContent>& contents,bool save_contents = false,float downsample_ratio = 0.25f,unsigned int writer_fps = 20,bool remove_noise = false,bool minimum_post_process = false,const cv::Mat& background = cv::Mat());

在utils.h中加入新增功能函数定义:

//Matting&Segmentation UtilsLITE_EXPORTS void swap_background(const cv::Mat& fgr_mat, const cv::Mat& pha_mat, const cv::Mat& bgr_mat, cv::Mat& out_mat, bool fgr_is_already_mul_pha = false);LITE_EXPORTS void remove_small_connected_area(cv::Mat& alpha_pred, float threshold = 0.05f);

现在我们来推一个视频看看吧:

输出结果:

总结

本文最终经过改进的应用程序可以直接下载使用:
(背景替换功能暂未添加)
下载地址: 视频人像分割系统
提取码:o9jl

另外需要源码学习的小伙伴可在下面链接中找到Windows端能够运行的lite.ai.toolkit :下载地址: 视频人像分割系统源码
提取码:nuxp

视频人像分割算法—C++推理(视频抠图 图片抠图)相关推荐

  1. 视频物体分割算法:如何提升复杂场景的分割精度?

    在此文章中,阿里巴巴资深算法专家为我们介绍了视频物体分割的三个研究方向,然后结合阿里文娱摩酷实验室的探索,分享了他们在视频领域的最新应用. 视频物体分割(Video Object Segmentati ...

  2. 如何使用视频合并分割软件将MP4视频合并分割 1

    现在抖音和微视等短视频平台已经占据了很大的市场和很多的空余时间,这些短视频在拍摄之后不是直接上传的,而是需要先将视频文件剪切合成并添加一些好看的转场特效以及适应场合的音乐,完成之后,再上传网络的,但是 ...

  3. 如何快速从一个视频中分割出多个视频

    在我们看视频多的时候不乏会有一些自己喜欢的视频,这些视频中有电影.综艺节目或短视频等不同类型的视频.而遇到这些喜欢的视频时我们难免会有把视频保存下来的冲动,但是视频太长而保存喜欢的只是一个片段保存完整 ...

  4. php 分隔视频,视频画面分割器怎么将视频画面分割成三部分?怎么分割视频画面并凸显部分?...

    今天要介绍的视频画面分割器不是屏幕分割器怎么用,画面分割器使用说明,八画面视频分割器怎么用等问题哦,而是电脑视频画面分割器,可以对视频画面切割,解决视频分割器怎么用等问题哦!是将视频画面分割成上中下三 ...

  5. 视频合并分割软件怎么给视频加片头

    可能很多朋友在观看别人制作的一些视频的时候都会发现片头会被加上作者的名称,这种方式呢,第一是为了防止有些人不经过允许搬运别人的视频,第二呢,就是为了证明这个视频是自己制作的.我们在制作一些视频的时候也 ...

  6. 如何使用视频合并分割软件将MP4视频合并分割

    现在抖音和微视等短视频平台已经占据了很大的市场和很多的空余时间,这些短视频在拍摄之后不是直接上传的,而是需要先将视频文件剪切合成并添加一些好看的转场特效以及适应场合的音乐,完成之后,再上传网络的,但是 ...

  7. 视频合并分割软件如何剪切视频

    在比较早期的时候,视频编辑都只有像影视制作这样专业的人员才能完成,而现如今,随着时代的发展,视频编辑软件越来越多,也越来越简单便捷,像我们这些非专业人士也能完成一些比较简单的视频剪切与编辑了.通常视频 ...

  8. 视频合并分割软件如何合并视频

    有些朋友可能会问到,怎么把我间断拍摄的几段视频拼接.合并在一起呢?其实使用迅捷视频合并分割软件就能非常简单地将几段视频合并在一起了,作为一款颠覆性的视频合并软件,这款软件的人性化界面令不仅能够让用户快 ...

  9. 视频分割算法在移动端如何应用

    语义分割任务要求图像中的每个像素都被赋予具有语义的标记.视频语义分割任务要求每个视频帧中的每个像素都被赋予一个带语义的标签. 视频分割是一种广泛使用的技术,可用于将场景的前景与背景分离.通过修改或替换 ...

最新文章

  1. 方便的画拓扑图的软件,大家一起分享
  2. C#各种配置文件使用,操作方法总结
  3. c语言学生成绩查询课设报告,C语言课设报告(学生考试成绩查询程序)【荐】.doc...
  4. 第十节: 利用SQLServer实现Quartz的持久化和双机热备的集群模式 :
  5. 设计素材|美丽的几何和多边形背景纹理
  6. python函数执行顺序_python下for循环接if判断的函数执行顺序
  7. 截取字符串--sql和access的区别
  8. CKeditor与CKfinder的简单配置
  9. [小工具] 五笔输入法
  10. Jenkins详细教程
  11. python 定时任务框架APScheduler
  12. 第六章 三维全景技术
  13. Excel中纵向查找函数-VLOOKUP函数
  14. 边缘计算相关论文汇总
  15. 多台计算机直接连接打印机,多台电脑如何连接打印机?
  16. F5负载均衡器通过iRules实现http应用的灵活转发
  17. 数仓分层(ODS、DWD、DWS、DWT、ADS)和数仓建模
  18. 如何在阿里云服务器构建discuz论坛(快速lamp架构)
  19. 软件项目方案模板~!
  20. 请问如何判断一段文本中是否含有词典中的词语,并且把它们统计出来呀,有无大神赐教呀!!!

热门文章

  1. Linux底层IIC 总线的理解、调用函数以及常见面试问题
  2. 财富自由的声音:蚂蚁上市前,取消了周报
  3. 直播美颜sdk免费版有吗?为什么美颜sdk没有免费版?
  4. BUUCTF MD5
  5. 简历背景图片设置html代码,怎么在简历中添加背景图片
  6. 趋势:TypeScript - 一种思维方式
  7. java作为微信小程序的后端_微信小程序连接java后端
  8. (十二)系统集成中级-质量管理
  9. iOS UIButton文字与图片交换位置
  10. 图片添加水印及打印文件