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

所属分类: 软件编程 / C 语言 阅读数: 60
收藏 0 赞 0 分享

基于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;
}
*/

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

更多精彩内容其他人还在看

C++无法重载点符号、::、sizeof等的原因

这篇文章主要介绍了C++无法重载点符号、::、sizeof等的原因的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

实例讲解C语言编程中的结构体对齐

这篇文章主要介绍了C语言编程中的结构体对齐,值得注意的是一些结构体对齐的例子在不同编译器下结果可能会不同,需要的朋友可以参考下
收藏 0 赞 0 分享

详解C语言的结构体中成员变量偏移问题

这篇文章主要介绍了C语言的结构体中成员变量偏移问题,以讲解如何编写宏来对成员变量进行修改为主,需要的朋友可以参考下
收藏 0 赞 0 分享

详解C语言结构体中的函数指针

这篇文章主要介绍了详解C语言结构体中的函数指针,文中对函数指针的基本概念也有讲解,需要的朋友可以参考下
收藏 0 赞 0 分享

C++编程中的函数指针初步解析

这篇文章主要介绍了C++编程中的函数指针初步解析,函数指针在C语言和C++学习中都是非常重要的知识,需要的朋友可以参考下
收藏 0 赞 0 分享

实例解析C++中类的成员函数指针

这篇文章主要介绍了C++中类的成员函数指针,例子中以讨论用函数指针调用类的成员函数为主,需要的朋友可以参考下
收藏 0 赞 0 分享

C语言中的函数指针基础学习教程

这篇文章主要介绍了C语言中的函数指针基础学习教程,包括函数指针作为参数来传递等重要知识,需要的朋友可以参考下
收藏 0 赞 0 分享

深入解析C语言中函数指针的定义与使用

这篇文章主要介绍了C语言中函数指针的定义与使用,是C语言入门学习中的基础知识,需要的朋友可以参考下
收藏 0 赞 0 分享

详解C语言编程中的函数指针以及函数回调

这篇文章主要介绍了C语言编程中的函数指针以及函数回调,函数回调实际上就是让函数指针作函数参数、调用时传入函数地址,需要的朋友可以参考下
收藏 0 赞 0 分享

C语言中的函数指针学习笔记

这篇文章主要介绍了C语言中的函数指针的一些学习知识点记录,文中作者整理了一些比较interesting的函数指针用法,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多