您当前的位置: 首页 > 

鱼儿-1226

暂无认证

  • 0浏览

    0关注

    1100博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

绿幕背景视频抠图

鱼儿-1226 发布时间:2020-07-29 10:11:25 ,浏览量:0

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

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

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

 

下面看代码:

 

 
  1. #include

  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(i);

  77. uchar *pframe = frame.ptr(i);

  78. uchar *pmask = mask.ptr(i);

  79. uchar *presult = result.ptr(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. }

原始视频图:

 

效果视频图:

关注
打赏
1604459285
查看更多评论
立即登录/注册

微信扫码登录

0.0395s