OpenCV常见的几种背景消除的方法

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

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

 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肤色侦测函数的源代码:

 

 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、基于混合高斯模型去除背景法

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

 

 

  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、背景相减背景去除方法

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

 

  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 }

 

 

 

 

posted @ 2012-09-26 11:28  拿枪的程序员  阅读(13956)  评论(0编辑  收藏  举报