分享

OpenCV背景去除的几种方法

 学海无涯GL 2013-04-21

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

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

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

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

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

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

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


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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多