OpenCV背景去除的几种方法

1、肤色侦测法
   肤色提取是基于人机互动方面常见的方法。因为肤色是人体的一大特征,它可以迅速从复杂的背景下分离出自己的特征区域。一下介绍两种常见的肤色提取:

1)HSV空间的肤色提取
 
    HSV色彩空间是一个圆锥形的模型,具体如右图所示:
 色相(H)是色彩的基本属性,就是平常说的颜色名称,例如红色、黄色等,
依照右图的标准色轮上的位置,取360度得数值。(也有0~100%的方法确定) 饱和度(S)是色彩的纯度,越高色彩越纯,低则变灰。取值为0~100%。明度(V)也叫亮度,取值0~100。
     根据肤色在HSV三个分量上的值,就可以简单的侦测出一张图像上肤色的部分。一下是肤色侦测函数的源代码:

[c-sharp] view plaincopy
  1. void skinDetectionHSV(IplImage* pImage,int lower,int upper,IplImage* process)  
  2. {  
  3.     IplImage* pImageHSV = NULL;  
  4.     IplImage* pImageH = NULL;  
  5.     IplImage* pImageS = NULL;  
  6.     IplImage* pImageProcessed = NULL;  
  7.     IplImage* tmpH = NULL;  
  8.     IplImage* tmpS = NULL;  
  9.     static IplImage* pyrImage = NULL;  
  10.   
  11.     CvSize imgSize;  
  12.     imgSize.height = pImage->height;  
  13.     imgSize.width = pImage->width ;  
  14.   
  15.     //create you want to use image and give them memory allocation  
  16.     pImageHSV = cvCreateImage(imgSize,IPL_DEPTH_8U,3);  
  17.     pImageH = cvCreateImage(imgSize,IPL_DEPTH_8U,1);  
  18.     pImageS = cvCreateImage(imgSize,IPL_DEPTH_8U,1);  
  19.     tmpS = cvCreateImage(imgSize,IPL_DEPTH_8U,1);  
  20.     tmpH = cvCreateImage(imgSize,IPL_DEPTH_8U,1);  
  21.     pImageProcessed = cvCreateImage(imgSize,IPL_DEPTH_8U,1);  
  22.     pyrImage = cvCreateImage(cvSize(pImage->width/2,pImage->height/2),IPL_DEPTH_8U,1);  
  23.   
  24.     //convert RGB image to HSV image  
  25.     cvCvtColor(pImage,pImageHSV,CV_BGR2HSV);  
  26.   
  27.     //Then split HSV to three single channel images  
  28.     cvCvtPixToPlane(pImageHSV,pImageH,pImageS,NULL,NULL);  
  29.     //The skin scalar range in H and S, Do they AND algorithm  
  30.     cvInRangeS(pImageH,cvScalar(0.0,0.0,0,0),cvScalar(lower,0.0,0,0),tmpH);  
  31.     cvInRangeS(pImageS,cvScalar(26,0.0,0,0),cvScalar(upper,0.0,0,0),tmpS);  
  32.     cvAnd(tmpH,tmpS,pImageProcessed,0);  
  33.     //  
  34.     //cvPyrDown(pImageProcessed,pyrImage,CV_GAUSSIAN_5x5);  
  35.     //cvPyrUp(pyrImage,pImageProcessed,CV_GAUSSIAN_5x5);  
  36.     //Erode and dilate  
  37.     cvErode(pImageProcessed,pImageProcessed,0,2);  
  38.     cvDilate(pImageProcessed,pImageProcessed,0,1);  
  39.   
  40.     cvCopy(pImageProcessed,process,0);  
  41.     //do clean  
  42.     cvReleaseImage(&pyrImage);  
  43.     cvReleaseImage(&pImageHSV);  
  44.     cvReleaseImage(&pImageH);  
  45.     cvReleaseImage(&pImageS);  
  46.     cvReleaseImage(&pyrImage);  
  47.     cvReleaseImage(&tmpH);  
  48.     cvReleaseImage(&tmpS);  
  49.     cvReleaseImage(&pImageProcessed);  
  50. }  

 (2)YCrCb空间的肤色提取
   YCrCb也是一种颜色空间,也可以说是YUV的颜色空间。Y是亮度的分量,而肤色侦测是对亮度比较敏感的,由摄像头拍摄的RGB图像转化为YCrCb空间的话可以去除亮度对肤色侦测的影响。下面给出基于YCrCb肤色侦测函数的源代码:

[c-sharp] view plaincopy
  1. void skinDetectionYCrCb(IplImage* imageRGB,int lower,int upper,IplImage* imgProcessed)  
  2. {  
  3.   
  4.         assert(imageRGB->nChannels==3);  
  5.     IplImage* imageYCrCb = NULL;  
  6.     IplImage* imageCb = NULL;  
  7.     imageYCrCb = cvCreateImage(cvGetSize(imageRGB),8,3);  
  8.     imageCb = cvCreateImage(cvGetSize(imageRGB),8,1);  
  9.   
  10.     cvCvtColor(imageRGB,imageYCrCb,CV_BGR2YCrCb);  
  11.     cvSplit(imageYCrCb,0,0,imageCb,0);//Cb  
  12.     for (int h=0;h<imageCb->height;h++)  
  13.         {  
  14.         for (int w=0;w<imageCb->width;w++)  
  15.                  {  
  16.             unsigned char* p =(unsigned char*)(imageCb->imageData+h*imageCb->widthStep+w);  
  17.             if (*p<=upper&&*p>=lower)  
  18.                        {  
  19.                 *p=255;  
  20.             }  
  21.                         else  
  22.                         {  
  23.                 *p=0;  
  24.             }  
  25.         }  
  26.     }  
  27.     cvCopy(imageCb,imgProcessed,NULL);  
  28. }  

2、基于混合高斯模型去除背景法

   高斯模型去除背景法也是背景去除的一种常用的方法,经常会用到视频图像侦测中。这种方法对于动态的视频图像特征侦测比较适合,因为模型中是前景和背景分离开来的。分离前景和背景的基准是判断像素点变化率,会把变化慢的学习为背景,变化快的视为前景。

[c-sharp] view plaincopy
  1. //  
  2.  
  3. #include "stdafx.h"  
  4. #include "cv.h"  
  5. #include "highgui.h"  
  6. #include "cxtypes.h"  
  7. #include "cvaux.h"  
  8. # include <iostream>  
  9.   
  10. using namespace std;  
  11.   
  12.   
  13. int _tmain(int argc, _TCHAR* argv[])  
  14. {  
  15.     //IplImage* pFirstFrame = NULL;  
  16. IplImage* pFrame = NULL;  
  17.     IplImage* pFrImg = NULL;  
  18.     IplImage* pBkImg = NULL;  
  19.     IplImage* FirstImg = NULL;  
  20.     static IplImage* pyrImg =NULL;  
  21.     CvCapture* pCapture = NULL;  
  22.     int nFrmNum = 0;  
  23.     int first = 0,next = 0;  
  24.     int thresh = 0;  
  25.   
  26.     cvNamedWindow("video",0);  
  27.     //cvNamedWindow("background",0);  
  28.     cvNamedWindow("foreground",0);  
  29.     cvResizeWindow("video",400,400);  
  30.     cvResizeWindow("foreground",400,400);  
  31.     //cvCreateTrackbar("thresh","foreground",&thresh,255,NULL);  
  32.     //cvMoveWindow("background",360,0);  
  33.     //cvMoveWindow("foregtound",0,0);  
  34.   
  35.     if(!(pCapture = cvCaptureFromCAM(1)))  
  36.     {  
  37.         printf("Could not initialize camera , please check it !");  
  38.         return -1;  
  39.     }  
  40.   
  41.     CvGaussBGModel* bg_model = NULL;  
  42.   
  43.     while(pFrame = cvQueryFrame(pCapture))  
  44.     {  
  45.         nFrmNum++;  
  46.         if(nFrmNum == 1)  
  47.         {  
  48.             pBkImg = cvCreateImage(cvGetSize(pFrame),IPL_DEPTH_8U,3);  
  49.             pFrImg = cvCreateImage(cvGetSize(pFrame),IPL_DEPTH_8U,1);  
  50.             FirstImg = cvCreateImage(cvGetSize(pFrame),IPL_DEPTH_8U,1);  
  51.             pyrImg = cvCreateImage(cvSize(pFrame->width/2,pFrame->height/2),IPL_DEPTH_8U,1);  
  52.               
  53.             CvGaussBGStatModelParams params;  
  54.             params.win_size = 2000;             //Learning rate = 1/win_size;  
  55.             params.bg_threshold = 0.7;         //Threshold  sum of weights for background test  
  56.             params.weight_init = 0.05;  
  57.             params.variance_init = 30;  
  58.             params.minArea = 15.f;  
  59.             params.n_gauss = 5; //= K =Number of gaussian in mixture  
  60.             params.std_threshold = 2.5;  
  61.   
  62.             //cvCopy(pFrame,pFirstFrame,0);  
  63.           
  64.             bg_model = (CvGaussBGModel*)cvCreateGaussianBGModel(pFrame,¶ms);  
  65.         }  
  66.         else  
  67.         {  
  68.                 int regioncount = 0;  
  69.                 int totalNum = pFrImg->width *pFrImg->height ;  
  70.                   
  71.                 cvSmooth(pFrame,pFrame,CV_GAUSSIAN,3,0,0,0);  
  72.       
  73.                 cvUpdateBGStatModel(pFrame,(CvBGStatModel*)bg_model,-0.00001);  
  74.                 cvCopy(bg_model->foreground ,pFrImg,0);  
  75.                 cvCopy(bg_model->background ,pBkImg,0);  
  76.                 //cvShowImage("background",pBkImg);  
  77.   
  78.                 //cvSmooth(pFrImg,pFrImg,CV_GAUSSIAN,3,0,0,0);  
  79.                 //cvPyrDown(pFrImg,pyrImg,CV_GAUSSIAN_5x5);  
  80.                 //cvPyrUp(pyrImg,pFrImg,CV_GAUSSIAN_5x5);  
  81.                 //cvSmooth(pFrImg,pFrImg,CV_GAUSSIAN,3,0,0,0);  
  82.                 cvErode(pFrImg,pFrImg,0,1);  
  83.                 cvDilate(pFrImg,pFrImg,0,3);  
  84.   
  85.                 //pBkImg->origin = 1;  
  86.                 //pFrImg->origin = 1;  
  87.               
  88.             cvShowImage("video",pFrame);  
  89.             cvShowImage("foreground",pFrImg);  
  90.             //cvReleaseBGStatModel((CvBGStatModel**)&bg_model);  
  91.             //bg_model = (CvGaussBGModel*)cvCreateGaussianBGModel(pFrame,0);  
  92.             /* 
  93.             //catch target frame 
  94.             if(nFrmNum>10 &&(double)cvSumImage(pFrImg)>0.3 * totalNum) 
  95.             { 
  96.                  
  97.                 first = cvSumImage(FirstImg); 
  98.                 next = cvSumImage(pFrImg); 
  99.                 printf("Next number is :%d /n",next); 
  100.                 cvCopy(pFrImg,FirstImg,0); 
  101.             } 
  102.             cvShowImage("foreground",pFrImg); 
  103.             cvCopy(pFrImg,FirstImg,0); 
  104.             */  
  105.             if(cvWaitKey(2)== 27)  
  106.             {  
  107.                 break;  
  108.             }  
  109.         }  
  110.     }  
  111.     cvReleaseBGStatModel((CvBGStatModel**)&bg_model);  
  112.     cvDestroyAllWindows();  
  113.     cvReleaseImage(&pFrImg);  
  114.     cvReleaseImage(&FirstImg);  
  115.     cvReleaseImage(&pFrame);  
  116.     cvReleaseImage(&pBkImg);  
  117.     cvReleaseCapture(&pCapture);  
  118.   
  119.     return 0;  
  120. }  

3、背景相减背景去除方法

   所谓的背景相减,是指把摄像头捕捉的图像第一帧作为背景,以后的每一帧都减去背景帧,这样减去之后剩下的就是多出来的特征物体(要侦测的物体)的部分。但是相减的部分也会对特征物体的灰阶值产生影响,一般是设定相关阈值要进行判断。以下是代码部分:


 

[c-sharp] view plaincopy
  1. int _tmain(int argc, _TCHAR* argv[])  
  2. {  
  3.     int thresh_low = 30;  
  4.       
  5.     IplImage* pImgFrame = NULL;   
  6.     IplImage* pImgProcessed = NULL;  
  7.     IplImage* pImgBackground = NULL;  
  8.     IplImage* pyrImage = NULL;  
  9.   
  10.     CvMat* pMatFrame = NULL;  
  11.     CvMat* pMatProcessed = NULL;  
  12.     CvMat* pMatBackground = NULL;  
  13.   
  14.     CvCapture* pCapture = NULL;  
  15.   
  16.     cvNamedWindow("video", 0);  
  17.     cvNamedWindow("background",0);  
  18.     cvNamedWindow("processed",0);  
  19.     //Create trackbar  
  20.     cvCreateTrackbar("Low","processed",&thresh_low,255,NULL);  
  21.   
  22.     cvResizeWindow("video",400,400);  
  23.     cvResizeWindow("background",400,400);  
  24.     cvResizeWindow("processed",400,400);  
  25.   
  26.     cvMoveWindow("video", 0, 0);  
  27.     cvMoveWindow("background", 400, 0);  
  28.     cvMoveWindow("processed", 800, 0);  
  29.       
  30.     if( !(pCapture = cvCaptureFromCAM(1)))  
  31.     {  
  32.         fprintf(stderr, "Can not open camera./n");  
  33.         return -2;  
  34.     }  
  35.   
  36.     //first frame  
  37.     pImgFrame = cvQueryFrame( pCapture );  
  38.     pImgBackground = cvCreateImage(cvSize(pImgFrame->width, pImgFrame->height),  IPL_DEPTH_8U,1);  
  39.     pImgProcessed = cvCreateImage(cvSize(pImgFrame->width, pImgFrame->height),  IPL_DEPTH_8U,1);  
  40.     pyrImage = cvCreateImage(cvSize(pImgFrame->width/2, pImgFrame->height/2),  IPL_DEPTH_8U,1);  
  41.   
  42.     pMatBackground = cvCreateMat(pImgFrame->height, pImgFrame->width, CV_32FC1);  
  43.     pMatProcessed = cvCreateMat(pImgFrame->height, pImgFrame->width, CV_32FC1);  
  44.     pMatFrame = cvCreateMat(pImgFrame->height, pImgFrame->width, CV_32FC1);  
  45.   
  46.     cvSmooth(pImgFrame, pImgFrame, CV_GAUSSIAN, 3, 0, 0);  
  47.     cvCvtColor(pImgFrame, pImgBackground, CV_BGR2GRAY);  
  48.     cvCvtColor(pImgFrame, pImgProcessed, CV_BGR2GRAY);  
  49.   
  50.     cvConvert(pImgProcessed, pMatFrame);  
  51.     cvConvert(pImgProcessed, pMatProcessed);  
  52.     cvConvert(pImgProcessed, pMatBackground);  
  53.     cvSmooth(pMatBackground, pMatBackground, CV_GAUSSIAN, 3, 0, 0);  
  54.   
  55.     while(pImgFrame = cvQueryFrame( pCapture ))  
  56.     {  
  57.         cvShowImage("video", pImgFrame);  
  58.         cvSmooth(pImgFrame, pImgFrame, CV_GAUSSIAN, 3, 0, 0);  
  59.   
  60.         cvCvtColor(pImgFrame, pImgProcessed, CV_BGR2GRAY);  
  61.         cvConvert(pImgProcessed, pMatFrame);  
  62.   
  63.         cvSmooth(pMatFrame, pMatFrame, CV_GAUSSIAN, 3, 0, 0);  
  64.         cvAbsDiff(pMatFrame, pMatBackground, pMatProcessed);  
  65.         //cvConvert(pMatProcessed,pImgProcessed);  
  66.         //cvThresholdBidirection(pImgProcessed,thresh_low);  
  67.         cvThreshold(pMatProcessed, pImgProcessed, 30, 255.0, CV_THRESH_BINARY);  
  68.           
  69.         cvPyrDown(pImgProcessed,pyrImage,CV_GAUSSIAN_5x5);  
  70.         cvPyrUp(pyrImage,pImgProcessed,CV_GAUSSIAN_5x5);  
  71.         //Erode and dilate  
  72.         cvErode(pImgProcessed, pImgProcessed, 0, 1);  
  73.         cvDilate(pImgProcessed, pImgProcessed, 0, 1);     
  74.           
  75.         //background update  
  76.         cvRunningAvg(pMatFrame, pMatBackground, 0.0003, 0);                   
  77.         cvConvert(pMatBackground, pImgBackground);  
  78.           
  79.           
  80.         cvShowImage("background", pImgBackground);  
  81.         cvShowImage("processed", pImgProcessed);  
  82.           
  83.         //cvZero(pImgProcessed);  
  84.         if( cvWaitKey(10) == 27 )  
  85.         {  
  86.             break;  
  87.         }  
  88.     }  
  89.   
  90.     cvDestroyWindow("video");  
  91.     cvDestroyWindow("background");  
  92.     cvDestroyWindow("processed");  
  93.   
  94.     cvReleaseImage(&pImgProcessed);  
  95.     cvReleaseImage(&pImgBackground);  
  96.   
  97.     cvReleaseMat(&pMatFrame);  
  98.     cvReleaseMat(&pMatProcessed);  
  99.     cvReleaseMat(&pMatBackground);  
  100.   
  101.     cvReleaseCapture(&pCapture);  
  102.   
  103.     return 0;  
  104. }  
原文地址:https://www.cnblogs.com/mfryf/p/2424024.html