【人像抠图】使用vs2022,onnxruntime框架进行部署(视频和多图片处理)

一、人像抠图的应用场景

1. 图像编辑:在图像编辑软件中,人像抠图是常用操作之一。通过抠图可以将人物从原背景中分离出来,放到新背景中,实现人物换背景的效果。这在电影后期特效、游戏角色置换等领域有很广泛的应用。

2. 视频特效:在视频编辑与特效制作中,人像抠图也是关键技术之一。通过实时对视频帧中的人物进行抠图与追踪,可以实现人物消失、人物换衣等特效,大大丰富视频的视觉效果。3. AR特效:在AR(增强现实)与静止画面中的特效制作中,抠取人物或目标物体是非常重要的一步。只有准确抠取人物或物体,才能在现实场景中实时替换或跟踪,实现各种有趣的AR特效。这在很多手机AR美妆与界面中都有所体现。4. 人脸识别:在人脸识别系统中,检测和定位人脸是第一步,人像抠图技术 frequently 被用来辅助检测和定位过程,提高系统的性能与准确率。5. 虚拟化妆:通过人像抠图,可以分离出人物的脸部区域。然后在脸部区域上添加各种妆容与装饰,再融合回原图像,实现给人物戴上各种动态妆容与装饰的效果,这在现代化妆领域有较广泛需求。综上,人像抠图在图像处理、计算机视觉与人工智能等领域有着很重要的应用价值。随着相关技术的进步,人像抠图的效果不断提高,应用范围也在持续扩展,它作为基础技术将服务于更加多元化的应用场景。这也为从事相关行业的研究人员和开发者带来很多机会与挑战。

二、抠图效果

26bd5d2b20ebf743acabe03eb8c4295f.png

22195cc69aaaf7dc466d76ebae8d0eab.png

遍历文件夹抠图

视频人像抠图

三、部署

从参考网址1下载源码,按照Readme文件,下载onnxruntime-win-x64-gpu-1.9.0,添加(opencv4.5.5和onnxruntime-win-x64-gpu-1.9.0)的包含目录、库目录、windows运行库目录,链接器-输入-附加依赖项(opencv_world455.lib、onnxruntime.lib)。

配置属性-Vcpkg-Use Vcpkg设置为否

修改头文件里的 cuda引用

//#include <cuda_provider_factory.h> 
#include <tensorrt_provider_factory.h>

修改Detect_video.cpp文件

#include "Detect_video.h"
#include "Detect.h"


// 调用摄像头或者读取本地视频文件,进行抠图效果展示
void detect_video(float downsample_ratio, Ort::Session& session, string choose,
  std::vector<std::vector<int64_t>>& dynamic_input_node_dims,
  std::vector<float>& dynamic_src_value_handler,
  std::vector<float>& dynamic_r1i_value_handler,
  std::vector<float>& dynamic_r2i_value_handler,
  std::vector<float>& dynamic_r3i_value_handler,
  std::vector<float>& dynamic_r4i_value_handler,
  std::vector<float>& dynamic_dsr_value_handler,
  std::vector<const char*>& input_node_names,
  std::vector<const char*>& output_node_names,
  bool& context_is_update,
  unsigned int& num_inputs,
  unsigned int& num_outputs
)
{


  double inferenceTime = 0.0;


  cv::VideoCapture video_capture;
  cv:String outpath;
  // 选择视频地址抠图或者摄像头抠图
  if (choose == "movie") {
    cout << "视频地址:" << endl;
    cin >> choose;
    video_capture.open(choose);
    outpath = choose + "_out.mp4";
  }
  else
  {
    cout << "请输入调用摄像头的序号:" << endl;
    int num = 0;
    cin >> num;
    video_capture.open(num);
    outpath= cv::format("%d", num) + "_out.mp4";
  }


  if (!video_capture.isOpened())
  {
    std::cout << "Can not open video" << "\n";
    return;
  }
  // 获取视频信息 
  int fps = video_capture.get(cv::CAP_PROP_FPS);
  cv::Size size = cv::Size((int)video_capture.get(cv::CAP_PROP_FRAME_WIDTH),
    (int)video_capture.get(cv::CAP_PROP_FRAME_HEIGHT));
  // 创建视频写入对象 
  cv::VideoWriter outputVideo;
  //cv:String outpath = choose == "movie" ? choose + "_out.mp4" : cv::format("%d",num) + "_out.mp4";
  outputVideo.open(outpath,
    cv::VideoWriter::fourcc('M', 'J', 'P', 'G'),
    fps, size, true);


  if (!outputVideo.isOpened()) {
    printf("Failed to open video writer!");
    return ;
  }
  // 2. matting loop
  cv::Mat mat,dst1,dst2;


  while (video_capture.read(mat))
  {
    //开始时间
    double t1 = static_cast<double>(cv::getTickCount());
    cv::resize(mat, dst1, cv::Size(), 0.5, 0.5, cv::INTER_NEAREST);
    cv::imshow("原图", dst1);
    // 人像抠图
    mat = detect_human(mat, downsample_ratio, session,
      dynamic_input_node_dims,
      dynamic_src_value_handler,
      dynamic_r1i_value_handler,
      dynamic_r2i_value_handler,
      dynamic_r3i_value_handler,
      dynamic_r4i_value_handler,
      dynamic_dsr_value_handler,
      input_node_names,
      output_node_names,
      context_is_update,
      num_inputs,
      num_outputs
    );


    // 人像抠图显示mask
    /*mat = detect(mat,true, downsample_ratio, session,
      dynamic_input_node_dims,
      dynamic_src_value_handler,
      dynamic_r1i_value_handler,
      dynamic_r2i_value_handler,
      dynamic_r3i_value_handler,
      dynamic_r4i_value_handler,
      dynamic_dsr_value_handler,
      input_node_names,
      output_node_names,
      context_is_update,
      num_inputs,
      num_outputs
    );*/


    //结束时间,计算fps
    double t2 = static_cast<double>(cv::getTickCount());
    inferenceTime = (t2 - t1) / cv::getTickFrequency() * 1000;
    std::stringstream fpsSs;
    fpsSs << "FPS: " << int(1000.0f / inferenceTime * 100) / 100.0f;
    // 向每帧写入fps
    cv::putText(mat, fpsSs.str(), cv::Point(16, 32),
      cv::FONT_HERSHEY_COMPLEX, 0.8, cv::Scalar(0, 0, 255));
    //缩放显示
    cv::resize(mat, dst2, cv::Size(), 0.5, 0.5, cv::INTER_NEAREST);
    cv::imshow("抠图", dst2);
    // 写入该帧到视频  
    if (outputVideo.isOpened())
      outputVideo.write(mat);
    cv::waitKey(1);
    // 4. check context states.
    if (!context_is_update) break;


    if (_kbhit()) // 如果有按键被按下
    {
      if (_getch() == 'q') //如果按下了q键则跳出循环
      {
        break;
      }


    }
  }
  // 5. release
  video_capture.release();
  outputVideo.release();
  destroyAllWindows();
}

main.cpp

void showmenu()
{
  printf("----菜单----\n");
  printf("1-遍历文件夹抠图(保存对应抠图文件,默认选项)\n");
  printf("2-图片抠图展示(不保存)\n");
  printf("3-视频抠图展示(保存)\n");
  printf("4-摄像头抠图展示(保存)\n");
  printf("5-摄像头换背景展示(不保存)\n");
  printf("0-退出函数\n");
}

生成程序后,因为我的cuda路径有好几个版本

9f59ad460d77f08c6d6490ffd2ae1017.png

所以,根据缺少的dll提示,将C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v10.1 下的所有dll拷贝到 Release 下。缺少的hdf5.dll 也从系统里找到(everything搜索在V:\vcpkg-master\installed\x64-windows\bin 里有个,别的地方也有),拷贝进来。

OK,这么整下来,不在vs环境下运行,直接双击生成的exe没问题了。

参考网址:

1. https://github.com/caip1299920300/RobustVideoMatting_onnxruntime (源码地址)

2. https://github.com/microsoft/onnxruntime/releases/tag/v1.9.0

fadfdd950116a6956894b5e50dfefef3.png

The End

猜你喜欢

转载自blog.csdn.net/cxyhjl/article/details/130664591