目标检测中背景建模.md

来源:互联网 发布:linux java 参数设置 编辑:程序博客网 时间:2024/05/02 11:40

目标检测中背景建模方法

  1. Single Gaussian (单高斯模型) 
    Real-time tracking of the human body
  2. 混合高斯模型(Mixture of Gaussian Model) 
    An improved adaptive background mixture model for real-time tracking with shadow detection
  3. 滑动高斯平均(Running Gaussian average)—Single Gaussian 
    Real-time tracking of the human body 
    对于单高斯和混合高斯估计大家都熟悉,这里不再累述(混合高斯在现有的背景建模算法中应该算是比较好的,很多新的算法或改进的算法都是基于它的一些原理的不同变体,但混合高斯算法的缺点是计算量相对比较大,速度偏慢,对光照敏感);
  4. 码本 (CodeBook) 
    Real-time foreground–background segmentation using codebook model 
    Real-time foreground-background segmentation using a modified codebook model 
    对与Codebook算法,曾经做过实验,效果还可以,后来也有多种变体,没有进一步的进行研究,但算法对光照也敏感);
  5. 自组织背景检测( SOBS-Self-organization background subtraction) 
    A self-Organizing approach to background subtraction for+visual surveillance 
    对于自组织背景建模算法即SOBS算法,该算法对光照有一定的鲁棒性,但MAP的模型比输入图片大,计算量比较大,但是可以通过并行处理来解决算法的速度问题,可以进行尝试;
  6. 样本一致性背景建模算法 (SACON) 
    A consensus-based method for tracking 
    A consensus-based method for tracking-Modelling background scenario and foreground appearance 
    SACON-Background subtraction based on a robust consensus method 
    SACON算法是基于统计的知识,代码实现过,并做过实验,效果还可以,但没有进一步的分析;
  7. VIBE算法 
    vibe 
    ViBe-A Universal Background Subtraction 
    VIBE算法是B哥的一个大作,网上有现成的算法可用,但已申请了专利,用于做研究还是可以的,该算法速度非常快,计算量比较小,而且对噪声有一定的鲁棒性,检测效果不错;
  8. 基于颜色信息的背景建模方法(Color) 
    A statistical approach for real-time robust background subtraction and shadow detection 
    基于颜色信息的背景建模方法,简称Color算法,该算法将像素点的差异分解成Chromaticity差异和Brightness差异,对光照具有很强的鲁棒性,并有比较好的效果,计算速度也比较快,基本可以满足实时性的要求,做了许多视频序列的检测,效果比较理想;
  9. 统计平均法
  10. 中值滤波法( Temporal Median filter) 
    Automatic congestion detection system for underground platform 
    Detecting moving objects,ghost,and shadows in video streams 
    统计平均法和中值滤波法,对于这两个算法,只对统计平均法做了实现,并进行了测试,算法的应用具有很大的局限性,只能算是理论上的一个补充;
  11. W4方法 
    W4.pdf 
    W4算法应该是最早被用于实际应用的一个算法,这个大家可以去查看相关的资料,这里不再细说;
  12. 本征背景法 
    A Bayesian computer vision system for modeling human interactions 
    本征背景法没实现过,看很多文献有讲解,然后该算法又是基于贝叶斯框架,本人一直对贝叶斯框架不感冒,理论上很Perfect,实际应用就是Shit;
  13. 核密度估计方法 
    Non-parametric model for background subtraction 
    最后就是核密度估计算法,该算法应该是一个比较鲁棒的算法,可以解决很多算法参数设置方面的问题,无需设置参数应该是算法的一大优势。

个人观点:SOBS、Color、VIBE、SACON、PDF等可以进行深入的了解,特别是近年来出现的Block-based或Region-Based、Features-Based、基于层次分类或层次训练器的算法可以进行深入的研究。 
推荐一篇综述文章:Evaluation of Background Subtraction Techniques for Video Surveillance

VIBE算法如下 
main.cpp

  1. #include "vibe.h"
  2. #include <cstdio>
  3. using namespace cv;
  4. using namespace std;
  5. int main(int argc, char* argv[])
  6. {
  7. Mat frame, gray, mask;
  8. VideoCapture capture;
  9. capture.open("2.avi");
  10. capture.set(CV_CAP_PROP_FRAME_WIDTH,640);
  11. capture.set(CV_CAP_PROP_FRAME_HEIGHT,480);
  12. if (!capture.isOpened())
  13. {
  14. cout<<"No camera or video input!\n"<<endl;
  15. return -1;
  16. }
  17. ViBe_BGS Vibe_Bgs;
  18. bool count =true;
  19. while (1)
  20. {
  21. capture >> frame;
  22. if (frame.empty())
  23. continue;
  24. cvtColor(frame, gray, CV_RGB2GRAY);
  25. if (count)
  26. {
  27. Vibe_Bgs.init(gray);
  28. Vibe_Bgs.processFirstFrame(gray);
  29. cout<<" Training ViBe complete!"<<endl;
  30. count=false;
  31. }
  32. else
  33. {
  34. Vibe_Bgs.testAndUpdate(gray);
  35. mask = Vibe_Bgs.getMask();
  36. morphologyEx(mask, mask, MORPH_OPEN, Mat());
  37. imshow("mask", mask);
  38. }
  39. imshow("input", frame);
  40. if ( cvWaitKey(30) == 27 )
  41. break;
  42. }
  43. return 0;
  44. }

vibe.h

  1. #include <iostream>
  2. #include "opencv2/opencv.hpp"
  3. using namespace cv;
  4. using namespace std;
  5. #define NUM_SAMPLES 20 //每个像素点的样本个数
  6. #define MIN_MATCHES 2 //#min指数
  7. #define RADIUS 20 //Sqthere半径
  8. #define SUBSAMPLE_FACTOR 16 //子采样概率
  9. class ViBe_BGS
  10. {
  11. public:
  12. ViBe_BGS(void);
  13. ~ViBe_BGS(void);
  14. void init(const Mat _image); //初始化
  15. void processFirstFrame(const Mat _image);
  16. void testAndUpdate(const Mat _image); //更新
  17. Mat getMask(void){return m_mask;};
  18. void deleteSamples(){delete samples;};
  19. private:
  20. unsigned char ***samples;
  21. // float samples[1024][1024][NUM_SAMPLES+1];//保存每个像素点的样本值
  22. /*
  23. Mat m_samples[NUM_SAMPLES];
  24. Mat m_foregroundMatchCount;*/
  25. Mat m_mask;
  26. };

vibe.cpp

  1. #include "vibe.h"
  2. using namespace std;
  3. using namespace cv;
  4. int c_xoff[9] = {-1, 0, 1, -1, 1, -1, 0, 1, 0}; //x的邻居点
  5. int c_yoff[9] = {-1, 0, 1, -1, 1, -1, 0, 1, 0}; //y的邻居点
  6. ViBe_BGS::ViBe_BGS(void)
  7. {
  8. }
  9. ViBe_BGS::~ViBe_BGS(void)
  10. {
  11. }
  12. /**************** Assign space and init ***************************/
  13. void ViBe_BGS::init(const Mat _image)
  14. {
  15. //动态分配三维数组,samples[][][NUM_SAMPLES]存储前景被连续检测的次数
  16. samples=new unsigned char **[_image.rows];
  17. for (int i=0;i<_image.rows;i++)
  18. {
  19. samples[i]=new unsigned char *[1024];
  20. for (int j=0;j<_image.cols;j++)
  21. {
  22. samples[i][j]=new unsigned char [NUM_SAMPLES+1];
  23. for (int k=0;k<NUM_SAMPLES+1;k++)
  24. {
  25. samples[i][j][k]=0;
  26. }
  27. }
  28. }
  29. m_mask = Mat::zeros(_image.size(),CV_8UC1);
  30. }
  31. /**************** Init model from first frame ********************/
  32. void ViBe_BGS::processFirstFrame(const Mat _image)
  33. {
  34. RNG rng;
  35. int row, col;
  36. for(int i = 0; i < _image.rows; i++)
  37. {
  38. for(int j = 0; j < _image.cols; j++)
  39. {
  40. for(int k = 0 ; k < NUM_SAMPLES; k++)
  41. {
  42. // Random pick up NUM_SAMPLES pixel in neighbourhood to construct the model
  43. int random = rng.uniform(0, 9);
  44. row = i + c_yoff[random];
  45. if (row < 0)
  46. row = 0;
  47. if (row >= _image.rows)
  48. row = _image.rows - 1;
  49. col = j + c_xoff[random];
  50. if (col < 0)
  51. col = 0;
  52. if (col >= _image.cols)
  53. col = _image.cols - 1;
  54. samples[i][j][k]=_image.at<uchar>(row, col);
  55. }
  56. }
  57. }
  58. }
  59. /**************** Test a new frame and update model ********************/
  60. void ViBe_BGS::testAndUpdate(const Mat _image)
  61. {
  62. RNG rng;
  63. for(int i = 0; i < _image.rows; i++)
  64. {
  65. for(int j = 0; j < _image.cols; j++)
  66. {
  67. int matches(0), count(0);
  68. int dist;
  69. while(matches < MIN_MATCHES && count < NUM_SAMPLES)
  70. {
  71. dist = abs(samples[i][j][count] - _image.at<uchar>(i, j));
  72. if (dist < RADIUS)
  73. matches++;
  74. count++;
  75. }
  76. if (matches >= MIN_MATCHES)
  77. {
  78. // It is a background pixel
  79. samples[i][j][NUM_SAMPLES]=0;
  80. // Set background pixel to 0
  81. m_mask.at<uchar>(i, j) = 0;
  82. // 如果一个像素是背景点,那么它有 1 / defaultSubsamplingFactor 的概率去更新自己的模型样本值
  83. int random = rng.uniform(0, SUBSAMPLE_FACTOR);
  84. if (random == 0)
  85. {
  86. random = rng.uniform(0, NUM_SAMPLES);
  87. samples[i][j][random]=_image.at<uchar>(i, j);
  88. }
  89. // 同时也有 1 / defaultSubsamplingFactor 的概率去更新它的邻居点的模型样本值
  90. random = rng.uniform(0, SUBSAMPLE_FACTOR);
  91. if (random == 0)
  92. {
  93. int row, col;
  94. random = rng.uniform(0, 9);
  95. row = i + c_yoff[random];
  96. if (row < 0)
  97. row = 0;
  98. if (row >= _image.rows)
  99. row = _image.rows - 1;
  100. random = rng.uniform(0, 9);
  101. col = j + c_xoff[random];
  102. if (col < 0)
  103. col = 0;
  104. if (col >= _image.cols)
  105. col = _image.cols - 1;
  106. random = rng.uniform(0, NUM_SAMPLES);
  107. samples[i][j][random]=_image.at<uchar>(i, j);
  108. }
  109. }
  110. else
  111. {
  112. // It is a foreground pixel
  113. samples[i][j][NUM_SAMPLES]++;
  114. // Set background pixel to 255
  115. m_mask.at<uchar>(i, j) = 255;
  116. //如果某个像素点连续N次被检测为前景,则认为一块静止区域被误判为运动,将其更新为背景点
  117. if(samples[i][j][NUM_SAMPLES]>50)
  118. {
  119. int random = rng.uniform(0, NUM_SAMPLES);
  120. if (random == 0)
  121. {
  122. random = rng.uniform(0, NUM_SAMPLES);
  123. samples[i][j][random]=_image.at<uchar>(i, j);
  124. }
  125. }
  126. }
  127. }
  128. }
  129. }
0 0