首页 > 编程 > C > 正文

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

2020-01-26 13:27:16
字体:
来源:转载
供稿:网友

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

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选