绿幕背景视频抠图

绿幕背景视频抠图对实时性要求比较高,如果使用kmeans或者GMM的话那么就太耗时了,达不到要求,因此将RGB空间转换到HSV色彩空间进行处理

       关于HSV 中颜色分量范围请看这篇博客:http://blog.csdn.net/linqianbi/article/details/78975998

 绿幕背景视频抠图的流程图:



下面看代码:

[cpp]  view plain  copy
  1. #include<opencv2\opencv.hpp>  
  2. using namespace cv;  
  3. //定义两张背景图  
  4. Mat background_01;  
  5. Mat background_02;  
  6. Mat background_03;  
  7. //绿幕抠图的实现函数  
  8. Mat replace_and_blend(Mat &frame, Mat &mask);  
  9. int main()  
  10. {  
  11.     background_01 = imread("1.jpg");  
  12.     background_02 = imread("2.jpg");  
  13.     background_03 = imread("3.jpg");  
  14.     //读入视频  
  15.     VideoCapture capture;  
  16.     capture.open("01.mp4");  
  17.     if (!capture.isOpened())  
  18.     {  
  19.         printf("could not open capture...\n");  
  20.         return -1;  
  21.     }  
  22.     char * title = "读取视频";  
  23.     char * resultWin = "效果图";  
  24.     namedWindow(title, CV_WINDOW_AUTOSIZE);  
  25.     namedWindow(resultWin, CV_WINDOW_AUTOSIZE);  
  26.     Mat frame;//定义一个Mat变量,用来存储每一帧的图像  
  27.     Mat hsv, mask;  
  28.     //如果读到了每一帧的图像  
  29.     while (capture.read(frame))  
  30.     {  
  31.         //将每一帧的图像转换到hsv空间  
  32.         cvtColor(frame, hsv, COLOR_BGR2HSV);  
  33.         //绿幕的颜色范围,将结果存在mask中  
  34.         inRange(hsv, Scalar(35, 43, 46), Scalar(155, 255, 255), mask);  
  35.         //对mask进行形态学操作  
  36.         //定义一个结构  
  37.         Mat k = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));  
  38.         //对mask进行形态学闭操作  
  39.         morphologyEx(mask, mask, MORPH_CLOSE, k);  
  40.         erode(mask, mask, k);  
  41.         //高斯模糊  
  42.         GaussianBlur(mask, mask, Size(3, 3), 0, 0);  
  43.         Mat result = replace_and_blend(frame, mask);  
  44.         char c = waitKey(30);//延时30ms  
  45.         if (c == 27)//如果按下ESC那么就退出  
  46.             break;  
  47.         imshow(title, frame);  
  48.         imshow(resultWin, result);  
  49.           
  50.     }  
  51.     waitKey(0);  
  52.     return 0;  
  53. }  
  54.   
  55. //对视频的每一帧的图像进行处理  
  56. Mat replace_and_blend(Mat &frame, Mat &mask)  
  57. {  
  58.     //创建一张结果图  
  59.     Mat result = Mat(frame.size(), frame.type());  
  60.     //图像的高 宽 与通道数  
  61.     int height = result.rows;  
  62.     int width = result.cols;  
  63.     int channels = result.channels();  
  64.     //int nStep = width*channels;  
  65.   
  66.     // replace and blend  
  67.     int m = 0;//mask的像素值  
  68.     double wt = 0;//融合的比例  
  69.   
  70.     int r = 0, g = 0, b = 0;//输出的像素  
  71.     int r1 = 0, g1 = 0, b1 = 0;  
  72.     int r2 = 0, g2 = 0, b2 = 0;  
  73.     for (int i = 0; i < height; i++)  
  74.     {  
  75.         //定义每一行 每一帧图像的指针,mask图像的指针,两张背景图的指针,结果图的指针  
  76.         uchar *pbg = background_03.ptr<uchar>(i);  
  77.         uchar *pframe = frame.ptr<uchar>(i);  
  78.         uchar *pmask = mask.ptr<uchar>(i);  
  79.         uchar *presult = result.ptr<uchar>(i);  
  80.         for (int j = 0; j < width; j++)  
  81.         {  
  82.             m = *pmask++;//读取mask的像素值  
  83.             if (m == 255)//如果是背景的话  
  84.             {  
  85.                 //进行三个通道的赋值  
  86.                 *presult++ = *pbg++;  
  87.                 *presult++ = *pbg++;  
  88.                 *presult++ = *pbg++;  
  89.                 pframe += 3;//将frame的图像的像素的通道也移动单个保持一致  
  90.             }  
  91.             else if (m == 0)//如果是前景的话  
  92.             {  
  93.                 //进行三个通道的赋值  
  94.                 *presult++ = *pframe++;  
  95.                 *presult++ = *pframe++;  
  96.                 *presult++ = *pframe++;  
  97.                 pbg += 3;//将frame的图像的像素的通道也移动单个保持一致  
  98.             }  
  99.             else  
  100.             {  
  101.                 //背景图每个像素的三个通道  
  102.                 b1 = *pbg++;  
  103.                 g1 = *pbg++;  
  104.                 r1 = *pbg++;  
  105.   
  106.                 //每一帧每一个像素的三个通道  
  107.                 b2 = *pframe++;  
  108.                 g2 = *pframe++;  
  109.                 r2 = *pframe++;  
  110.   
  111.                 // 权重  
  112.                 wt = m / 255.0;  
  113.   
  114.                 // 混合  
  115.                 b = b1*wt + b2*(1.0 - wt);  
  116.                 g = g1*wt + g2*(1.0 - wt);  
  117.                 r = r1*wt + r2*(1.0 - wt);  
  118.   
  119.                 *presult++ = b;  
  120.                 *presult++ = g;  
  121.                 *presult++ = r;  
  122.             }  
  123.         }  
  124.     }  
  125.       
  126.   
  127.     return result;  
  128. }  

原始视频图:



效果视频图:

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值