chroma key (绿背景抠图)

本文介绍了一种基于绿幕的图像抠图算法实现过程。首先通过计算每个像素的绿色分量与红蓝分量之差来创建掩膜(mask),区分前景与背景;接着使用掩膜将前景图像从原始图像中分离出来;最后进一步优化去除残留的绿色像素,确保抠图效果更佳。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ChromaKey

1.创建掩图(mask.

  根据输入的绿背景图,我们可以访问其每一个像素,获取每一个像素RGB值,用th来表示 -(g-(r+b))的值,然后我们寻找到某一个界点值k,当th的值大于k的时候表示src图上该点的是绿色,生成的mask图对应的位置就用黑色标定,当th的值小于k的时候表示src图不是绿色,那么mask图上对应位置的像素用白色来表示。在图形学中,我们常用黑色来表示背景,用白色来表示前景。

 

2.利用第一步生成好mask图,把src复制(copyTo)到一张新的背景图中,在新的背景图中只显示我们要扣出来的object

   

3.因为在第一步生成mask也不是那么完美,可能还有某些绿色没有去掉,我们还需要再访问图片中每一个像素点,因为rgb图上绿色点的rgb的值是有范围的,那么我们就根据这个范围找出残留在图片上绿色的点,然后我们去掉该点。



[cpp]  view plain  copy
  1. #include<iostream>  
  2. #include<cv.h>  
  3. #include<highgui.h>  
  4. using namespace std;  
  5. using namespace cv;  
  6.   
  7. //int main()  
  8. //{  
  9. //  IplImage *src = 0;  
  10. //  IplImage *histimg = 0;  
  11. //  if ((src = cvLoadImage("screen.jpg", 0)) == NULL) // force to gray image  
  12. //      return -1;  
  13. //  cvNamedWindow("Histogram", 3);   //创建直方图窗口  
  14. //  histimg = cvCreateImage(cvGetSize(src), src->depth, 3);  
  15. //  //改变背景色  
  16. //  for (int h = 0; h < histimg->height; h++)  
  17. //  {  
  18. //      for (int w = 0; w < histimg->width * 3; w++)  
  19. //      {  
  20. //          ((uchar*)((int)histimg->imageData + histimg->widthStep*h))[w] = (uchar)125;  //将背静改为白色  
  21. //      }  
  22. //  }  
  23. //  cvShowImage("Histogram", histimg);  
  24. //  cvWaitKey(0);  
  25. //}  
  26.   
  27.   
  28. int main()  
  29. {  
  30.     Mat img = imread("foreground1.png");  
  31.     //imshow("Lena Original", img);  
  32.     for (int row = 0; row < img.rows; row++)  
  33.     {  
  34.         for (int col = 0; col < img.cols; col++)  
  35.         {  
  36.             /* 注意 Mat::at 函数是个模板函数, 需要指明参数类型, 因为这张图是具有红蓝绿三通道的图, 
  37.             所以它的参数类型可以传递一个 Vec3b, 这是一个存放 3 个 uchar 数据的 Vec(向量). 这里 
  38.             提供了索引重载, [2]表示的是返回第三个通道, 在这里是 Red 通道, 第一个通道(Blue)用[0]返回 */  
  39.             if ( img.at<Vec3b>(row, col)[1]>140)  
  40.                 {if(img.at<Vec3b>(row, col)[0]<128)   
  41.                     if(img.at<Vec3b>(row, col)[2]<128)  
  42.                     {  
  43.                         img.at<Vec3b>(row, col)[0] = 255;  
  44.                         img.at<Vec3b>(row, col)[1] = 255;  
  45.                         img.at<Vec3b>(row, col)[2] = 255;  
  46.                  }  
  47.             }  
  48. //          else  
  49. //          {  
  50. //              img.at<Vec3b>(row, col)[0] = 0;  
  51. //              img.at<Vec3b>(row, col)[1] = 0;  
  52. //              img.at<Vec3b>(row, col)[2] = 0;  
  53. //          }  
  54.                   
  55.         }  
  56.     }  
  57.     imshow("result", img);  
  58.     imwrite("result.png",img);  
  59.   
  60. //  cv::Mat result;  
  61. //  result = imread("display1.bmp");  
  62. //  cv::Mat forground= imread("screen.jpg",-1);  
  63. //  //cv::compare(result,cv::GC_PR_FGD,result,cv::CMP_EQ);  
  64. //  cv::Mat forground1(forground.size(),CV_8UC3,cv::Scalar(255,255,255));  
  65. //  forground.copyTo(forground1,result); // bg pixels not copied  
  66. //  cv::namedWindow("Segmented Image");  
  67. //  cv::imshow("Segmented Image",forground1);  
  68. //  cv::imwrite("foreground1.png",forground1);  
  69.     cvWaitKey();  
  70.     return 0;  
  71. }  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值