BackgroundSubtractorMOG部分代码
2016-03-05 09:52
465 查看
1、Opencv的帮助文档地址:http://docs.opencv.org/2.4/modules/video/doc/motion_analysis_and_object_tracking.html?highlight=backgroundsubtractormog#backgroundsubtractormog
2、关键函数
2.1、BackgroundSubtractorMOG::BackgroundSubtractorMOG(int _history, int _nmixtures,
double _backgroundRatio,
double _noiseSigma)
2.2、void BackgroundSubtractorMOG::operator()(InputArray _image, OutputArray _fgmask, double learningRate)
3、几点说明:
3.1、这个参数int _history 的用途。仅仅用于第一帧学习率,或者在学习率为负值时的学习率计算,其他地方没有使用
learningRate = learningRate >= 0 && nframes > 1 ? learningRate : 1./min( nframes, history );
3.2、 _backgroundRatio的用途,是个阈值,用于判断前多少个model作为背景模型。是前n个模型权重的和的比较阈值。具体可以参考下面代码注释部分
**代码摘自opencv
[1]: 《An Improved Adaptive Background Mixture Model for Realtime Tracking with Shadow Detection》
2、关键函数
2.1、BackgroundSubtractorMOG::BackgroundSubtractorMOG(int _history, int _nmixtures,
double _backgroundRatio,
double _noiseSigma)
2.2、void BackgroundSubtractorMOG::operator()(InputArray _image, OutputArray _fgmask, double learningRate)
3、几点说明:
3.1、这个参数int _history 的用途。仅仅用于第一帧学习率,或者在学习率为负值时的学习率计算,其他地方没有使用
learningRate = learningRate >= 0 && nframes > 1 ? learningRate : 1./min( nframes, history );
3.2、 _backgroundRatio的用途,是个阈值,用于判断前多少个model作为背景模型。是前n个模型权重的和的比较阈值。具体可以参考下面代码注释部分
**代码摘自opencv
//backgroundRatio : 通过代码可知,就是k个模型的权重累加值>= backgroundRatio ,此时前k个model就是背景的model,大于k的model就是前景的model //nmixtures : model数量 static void process8uC1( const Mat& image, Mat& fgmask, double learningRate, Mat& bgmodel, int nmixtures, double backgroundRatio, double varThreshold, double noiseSigma ) { int x, y, k, k1, rows = image.rows, cols = image.cols; float alpha = (float)learningRate, T = (float)backgroundRatio, vT = (float)varThreshold; int K = nmixtures; MixData<float>* mptr = (MixData<float>*)bgmodel.data; const float w0 = (float)defaultInitialWeight; const float sk0 = (float)(w0/(defaultNoiseSigma*2)); const float var0 = (float)(defaultNoiseSigma*defaultNoiseSigma*4); const float minVar = (float)(noiseSigma*noiseSigma); for( y = 0; y < rows; y++ ) { const uchar* src = image.ptr<uchar>(y); uchar* dst = fgmask.ptr<uchar>(y); if( alpha > 0 ) { // 考虑更新模型的情况。 for( x = 0; x < cols; x++, mptr += K ) { float wsum = 0; float pix = src[x]; int kHit = -1, kForeground = -1; // K:是高斯分布数量 for( k = 0; k < K; k++ ) { float w = mptr[k].weight; wsum += w; if( w < FLT_EPSILON ) // 由于mptr是按权重降序排列的,因此权重太小的情况就结束循环 break; float mu = mptr[k].mean; float var = mptr[k].var; float diff = pix - mu; float d2 = diff*diff; if( d2 < vT*var ) //同样判断是否是匹配的分布 { wsum -= w; // 这里得到的wsum是前面k-1个不匹配的分布的权重的累加和 float dw = alpha*(1.f - w); // mptr[k].weight = w + dw; //更新权重 mptr[k].mean = mu + alpha*diff; // 更新均值 var = max(var + alpha*(d2 - var), minVar); // 更新方差 mptr[k].var = var; mptr[k].sortKey = w/sqrt(var); // 排序的关键字,为什么? for( k1 = k-1; k1 >= 0; k1-- ) // 重新排序,通过交换的方式,将该高斯分布适当前移 { if( mptr[k1].sortKey >= mptr[k1+1].sortKey ) break; std::swap( mptr[k1], mptr[k1+1] ); } kHit = k1+1; break; } } if( kHit < 0 ) // no appropriate gaussian mixture found at all, remove the weakest mixture and create a new one { kHit = k = min(k, K-1); wsum += w0 - mptr[k].weight; mptr[k].weight = w0; mptr[k].mean = pix; mptr[k].var = var0; mptr[k].sortKey = sk0; } else for( ; k < K; k++ ) wsum += mptr[k].weight; float wscale = 1.f/wsum; wsum = 0; for( k = 0; k < K; k++ ) { wsum += mptr[k].weight *= wscale; mptr[k].sortKey *= wscale; // 前面权重或者分布有变化,这里做更新 if( wsum > T && kForeground < 0 ) kForeground = k+1; } dst[x] = (uchar)(-(kHit >= kForeground)); } } else { //不考虑更新模型的情况。这里更好理解些,看完这个在看考虑学习率的场景 for( x = 0; x < cols; x++, mptr += K ) { float pix = src[x]; int kHit = -1, kForeground = -1; //kForeground:前多少个分布是背景的分布。大于kForeground的就是前景分布 //kHit: 表示给定的像素最符合哪个分布 ; //kHit <0 ,表示没有匹配的分布,自然是前景; //kHit<kForeground 自然是背景;否则是前景 //这里判断给定的像素值与哪个高斯分布最匹配,匹配的依据就是小于vT倍的方差 for( k = 0; k < K; k++ ) { if( mptr[k].weight < FLT_EPSILON ) break; float mu = mptr[k].mean; float var = mptr[k].var; float diff = pix - mu; float d2 = diff*diff; if( d2 < vT*var ) { kHit = k; break; } } if( kHit >= 0 ) //若是没有找到匹配的分布,就被判定为为前景,不需要下面的计算 { float wsum = 0; for( k = 0; k < K; k++ ) { wsum += mptr[k].weight; if( wsum > T ) { kForeground = k+1; // 前k个作为背景模型,这里计算的到k值。 break; } } } dst[x] = (uchar)(kHit < 0 || kHit >= kForeground ? 255 : 0);// kForeground表示前kForeground个作为背景模型,若是kHit>=kForeground说明匹配的高斯分布已经不在前kForeground中,因此该像素点就是前景了。否则就判定为背景点 } } } }
[1]: 《An Improved Adaptive Background Mixture Model for Realtime Tracking with Shadow Detection》
相关文章推荐
- python中使用OpenCV进行人脸检测的例子
- opencv 做人脸识别 opencv 人脸匹配分析
- 使用opencv拉伸图像扩大分辨率示例
- 基于C++实现kinect+opencv 获取深度及彩色数据
- OpenCV 2.4.3 C++ 平滑处理分析
- Python中使用OpenCV库来进行简单的气象学遥感影像计算
- 利用Python和OpenCV库将URL转换为OpenCV格式的方法
- python结合opencv实现人脸检测与跟踪
- Python环境搭建之OpenCV的步骤方法
- Python实现OpenCV的安装与使用示例
- 在树莓派2或树莓派B+上安装Python和OpenCV的教程
- opencv-python学习一--人脸检测
- 在Ubuntu上安装OpenCV3.0和Python-openCV的经历
- OpenCV配置,从来没有这么简单!
- ubuntu下opencv和qt的安装配置
- OpenCV学习笔记(二十五)——OpenCV图形界面设计Qt+VS2008
- 分享一些OpenCV实现立体视觉的经验
- 关于OpenCv图像变换与基本图形检测
- "应用程序正常初始化失败"-0xc0150002 解决办法
- OpenCV->HSV色彩空间