Opencv实现绿幕视频背景替换功能

 更新时间:2019年05月21日 11:53:39   作者:东城青年  
这篇文章主要为大家详细介绍了Opencv实现绿幕视频背景替换功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

基于hsv颜色空间的实时背景替换: 

#include<opencv2\opencv.hpp>
using namespace cv;
Mat replace_and_blend(Mat &frame, Mat&mask);
Mat background,frame, hsv, mask,result;
int main(int arc, char** argv) { 
 background = imread("2.jpg");
 namedWindow("input", CV_WINDOW_AUTOSIZE);
 imshow("src", background);
 
 VideoCapture capture;
 capture.open("1.mp4");
 
    CvSize size = cvSize(capture.get(CV_CAP_PROP_FRAME_WIDTH), capture.get(CV_CAP_PROP_FRAME_HEIGHT)); 
 VideoWriter writer("qq.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'),12.0, size, true);
  
 while (capture.read(frame)) {
 imshow("input", frame);
 cvtColor(frame, hsv, CV_BGR2HSV);
 inRange(hsv, Scalar(35, 43, 46), Scalar(77, 255, 255), mask);//颜色过滤,得到mask绿色部分为1,其它部分都为0
 imshow("mask", mask);
 Mat kernel = getStructuringElement(MORPH_RECT,Size(3,3));
 morphologyEx(mask, mask, MORPH_DILATE, kernel);
 GaussianBlur(mask, mask, Size(3, 3), 0, 0);//0,0会根据Size自动算的
 
 result = replace_and_blend(frame, mask);
        writer.write(result);
 char c = waitKey(1);
 if (c == 27) {
  break;
 } 
 imshow("input", frame);
 imshow("result", result);
 }
 waitKey(0);
 return 0;
}
 
//通过颜色过滤得到的掩码为单通道图像
Mat replace_and_blend(Mat &frame, Mat &mask)
{
 int rows = frame.rows;
 int cols = frame.cols;
 result = Mat::zeros(frame.size(), frame.type());
 for (int i = 0; i < rows; i++)
 {
 uchar *pf = frame.ptr(i);//人物前景
 uchar *pm = mask.ptr(i);//掩码
 uchar *pb = background.ptr(i);//背景
 uchar *pr = result.ptr(i);//结果
 
 for (int j = 0; j < cols; j++)
 {
  pm++;
  if (*pm == 255)//背景
  {
  pr[3 * j] = pb[3 * j];
  pr[3 * j + 1] = pb[3 * j + 1];
  pr[3 * j + 2] = pb[3 * j + 2];
  }
  else if (*pm == 0)//前景
  {
  pr[3 * j] = pf[3 * j];
  pr[3 * j + 1] = pf[3 * j + 1];
  pr[3 * j + 2] = pf[3 * j + 2];
  }
  else //融合部分
  {
  int m = *pm;
  double w = m / 255.0;
  pr[3 * j] = w *pb[3 * j] + (1-w) * pf[3 * j];
  pr[3 * j + 1] = w * pb[3 * j + 1] + (1-w) * pf[3 * j + 1];
  pr[3 * j + 2] = w * pb[3 * j + 2] + (1-w) * pf[3 * j + 2];
                //或者取前景和背景的平均值
  /*pr[3 * j] = (pb[3 * j] + pf[3 * j])/2;
  pr[3 * j + 1] = (pb[3 * j + 1] + pf[3 * j + 1])/2;
  pr[3 * j + 2] = (pb[3 * j + 2] + pf[3 * j + 2])/2;*/
  }
 }
 }
 return result; 
}

 
/*
Mat replace_and_blend(Mat &frame, Mat&mask) {
 result = Mat::zeros(frame.size(), frame.type());
 int h = frame.rows;
 int w = frame.cols;
 int dims = frame.channels();
 int m ;
 double wt ;
 int b , g, r;
 int b1, g1, r1;
 int b2 , g2, r2 ;
 //指针操作速度最快,直接访问地址
 for (int row = 0; row < h; row++) {
 uchar* current = frame.ptr<uchar>(row);
 uchar* bgrow = background.ptr<uchar>(row);
 uchar* maskrow = mask.ptr<uchar>(row);
 uchar* targetrow = result.ptr<uchar>(row);
 for (int col = 0; col < w; col++) {
  m = *maskrow++;
  if (m == 255) {//背景
  *targetrow++ = *bgrow++;
  *targetrow++ = *bgrow++;
  *targetrow++ = *bgrow++;
  current += 3;
  }
  else if (m == 0) {//前景
  *targetrow++ = *current++;
  *targetrow++ = *current++;
  *targetrow++ = *current++;
  bgrow += 3;
  }
  else {
  b1 = *bgrow++;
  g1 = *bgrow++;
  r1 = *bgrow++;
  b2 = *current++;
  g2 = *current++;
  r2 = *current++;
  wt = m/ 255.0;
  b = wt*b1 + (1 - wt)*b2;
  g = wt*g1 + (1 - wt)*g2;
  r = wt*r1 + (1 - wt)*r2;
  *targetrow++ = b;
  *targetrow++ = g;
  *targetrow++ = r;
  }
 } 
 }
 return result;
}
*/

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Qt编写秒表功能

    Qt编写秒表功能

    这篇文章主要为大家详细介绍了Qt编写秒表功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • C++浅析引用的定义与使用

    C++浅析引用的定义与使用

    引用是C++一个很重要的特性,顾名思义是某一个变量或对象的别名,对引用的操作与对其所绑定的变量或对象的操作完全等价,这篇文章主要给大家总结介绍了C++中引用的相关知识点,需要的朋友可以参考下
    2022-07-07
  • C++实现停车场管理系统的示例代码

    C++实现停车场管理系统的示例代码

    停车场管理系统就是模拟停车场进行车辆管理的系统,该系统分为汽车信息模块,用户使用模块和管理员用户模块,本文将用C++实现这一简单的系统,希望对大家有所帮助
    2023-04-04
  • 一篇文章带你了解C语言内存对齐解决的问题

    一篇文章带你了解C语言内存对齐解决的问题

    内存对齐的目的是为了提高CPU读写内存里数据的速度。现代的CPU读取内存并不是一个一个字节挨着读取,这样做的效率非常低。现代的CPU一般以4个字节(32bit数据总线)或者8个字节(64bit数据总线)为一组,一组一组地读写内存里的数据
    2021-08-08
  • c语言求余数的实例讲解

    c语言求余数的实例讲解

    在本篇文章里小编给大家整理的是关于c语言如何求余数的相关知识点内容,有需要的朋友们可以学习下。
    2020-02-02
  • C语言之qsort函数详解

    C语言之qsort函数详解

    这篇文章主要介绍了C语言中qsort函数的用法实例详解的相关资料,希望通过本文能帮助到大家,让大家理解掌握这部分内容,需要的朋友可以参考下
    2021-08-08
  • C/C++中I/O进阶详解及其作用介绍

    C/C++中I/O进阶详解及其作用介绍

    这篇文章主要介绍了C/C++中I/O进阶详解及其作用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • C++类与对象深入之运算符重载与const及初始化列表详解

    C++类与对象深入之运算符重载与const及初始化列表详解

    运算符是程序中最最常见的操作,例如对于内置类型的赋值我们直接使用=赋值即可,因为这些编译器已经帮我们做好了,但是对象的赋值呢?能直接赋值吗
    2022-06-06
  • C语言通过案例讲解并发编程模型

    C语言通过案例讲解并发编程模型

    所谓并发编程是指在一台处理器上“同时”处理多个任务。并发是在同一实体上的多个事件。多个事件在同一时间间隔发生,下面我们根据样例来理解
    2022-04-04
  • C语言实现简易扫雷程序

    C语言实现简易扫雷程序

    这篇文章主要为大家详细介绍了C语言实现简易扫雷程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07

最新评论