C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > Opencv实现绿幕视频背景替换功能

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

作者:东城青年

这篇文章主要为大家详细介绍了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;
}
*/

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

您可能感兴趣的文章:
阅读全文