cvbgfg_acmmm2003 源代码注释(一)
来源:互联网 发布:淘宝店logo设计 编辑:程序博客网 时间:2024/05/21 10:41
前面的模型定义还有参数的变量定义可以参考源文件background_segm.hpp 里面英文注释已经说得很清楚了 我就不再写了 这里只写文件cvbgfg_acmmm2003
论文是Foreground Object Detection from Videos Containing Complex Background,其实如果已经打算看这个源代码了,应该不会不知道这篇论文。
没有看过论文的不建议看代码,不知道作者理论来源的也不会有很大收获
为了易看,以插入代码的方式书写
论文是Foreground Object Detection from Videos Containing Complex Background,其实如果已经打算看这个源代码了,应该不会不知道这篇论文。
没有看过论文的不建议看代码,不知道作者理论来源的也不会有很大收获
为了易看,以插入代码的方式书写
#include "_cvaux.h"#include <math.h>#include <stdio.h>#include <stdlib.h>//#include <algorithm>/*选出最大元素*/static double* _cv_max_element( double* start, double* end ){ double* p = start++; for( ; start != end; ++start) { if (*p < *start) p = start; } return p;}static void CV_CDECL icvReleaseFGDStatModel( CvFGDStatModel** model );static int CV_CDECL icvUpdateFGDStatModel( IplImage* curr_frame, CvFGDStatModel* model );// Function cvCreateFGDStatModel initializes foreground detection process// parameters:// first_frame - frame from video sequence// parameters - (optional) if NULL default parameters of the algorithm will be used// p_model - pointer to CvFGDStatModel structureCV_IMPL CvBGStatModel*cvCreateFGDStatModel( IplImage* first_frame, CvFGDStatModelParams* parameters ){ CvFGDStatModel* p_model = 0; CV_FUNCNAME( "cvCreateFGDStatModel" ); __BEGIN__; int i, j, k, pixel_count, buf_size; CvFGDStatModelParams params; if( !CV_IS_IMAGE(first_frame) ) CV_ERROR( CV_StsBadArg, "Invalid or NULL first_frame parameter" ); if (first_frame->nChannels != 3) CV_ERROR( CV_StsBadArg, "first_frame must have 3 color channels" ); // Initialize parameters: if( parameters == NULL ) { params.Lc = CV_BGFG_FGD_LC; params.N1c = CV_BGFG_FGD_N1C; params.N2c = CV_BGFG_FGD_N2C; params.Lcc = CV_BGFG_FGD_LCC; params.N1cc = CV_BGFG_FGD_N1CC; params.N2cc = CV_BGFG_FGD_N2CC; params.delta = CV_BGFG_FGD_DELTA; params.alpha1 = CV_BGFG_FGD_ALPHA_1; params.alpha2 = CV_BGFG_FGD_ALPHA_2; params.alpha3 = CV_BGFG_FGD_ALPHA_3; params.T = CV_BGFG_FGD_T; params.minArea = CV_BGFG_FGD_MINAREA; params.is_obj_without_holes = 1; params.perform_morphing = 1; } else { params = *parameters; } CV_CALL( p_model = (CvFGDStatModel*)cvAlloc( sizeof(*p_model) )); memset( p_model, 0, sizeof(*p_model) ); p_model->type = CV_BG_MODEL_FGD; p_model->release = (CvReleaseBGStatModel)icvReleaseFGDStatModel; p_model->update = (CvUpdateBGStatModel)icvUpdateFGDStatModel;; p_model->params = params; // Initialize storage pools: /*下面为申请内存空间 此处方法与GMM的方法一样 即申请一个整块空间 然后给不同的点分配相应的入口地址 并非是各个点分别申请空间 因此后面访问的时候一定要注意相应点的边界问题不要越界 否则大部分访问是不会出错的 但是实际访问的是其他点的数据 */ pixel_count = first_frame->width * first_frame->height; buf_size = pixel_count*sizeof(p_model->pixel_stat[0]); CV_CALL( p_model->pixel_stat = (CvBGPixelStat*)cvAlloc(buf_size) ); memset( p_model->pixel_stat, 0, buf_size ); /* 还要注意的是每个像素点均维护两种类型的表 即c和cc 表的个数由参数N2c和N2cc指定 */ buf_size = pixel_count*params.N2c*sizeof(p_model->pixel_stat[0].ctable[0]); CV_CALL( p_model->pixel_stat[0].ctable = (CvBGPixelCStatTable*)cvAlloc(buf_size) ); memset( p_model->pixel_stat[0].ctable, 0, buf_size ); buf_size = pixel_count*params.N2cc*sizeof(p_model->pixel_stat[0].cctable[0]); CV_CALL( p_model->pixel_stat[0].cctable = (CvBGPixelCCStatTable*)cvAlloc(buf_size) ); memset( p_model->pixel_stat[0].cctable, 0, buf_size ); for( i = 0, k = 0; i < first_frame->height; i++ ) { for( j = 0; j < first_frame->width; j++, k++ ) { p_model->pixel_stat[k].ctable = p_model->pixel_stat[0].ctable + k*params.N2c; p_model->pixel_stat[k].cctable = p_model->pixel_stat[0].cctable + k*params.N2cc; } } // Init temporary images: /*下面的前两个空间用来分别存储两种差分的结果 第三个是为了画出前景 三个均为单通道*/ CV_CALL( p_model->Ftd = cvCreateImage(cvSize(first_frame->width, first_frame->height), IPL_DEPTH_8U, 1)); CV_CALL( p_model->Fbd = cvCreateImage(cvSize(first_frame->width, first_frame->height), IPL_DEPTH_8U, 1)); CV_CALL( p_model->foreground = cvCreateImage(cvSize(first_frame->width, first_frame->height), IPL_DEPTH_8U, 1)); CV_CALL( p_model->background = cvCloneImage(first_frame)); CV_CALL( p_model->prev_frame = cvCloneImage(first_frame)); CV_CALL( p_model->storage = cvCreateMemStorage()); __END__; if( cvGetErrStatus() < 0 ) { CvBGStatModel* base_ptr = (CvBGStatModel*)p_model; if( p_model && p_model->release ) p_model->release( &base_ptr ); else cvFree( &p_model ); p_model = 0; } return (CvBGStatModel*)p_model;}/*释放内存空间*/static void CV_CDECLicvReleaseFGDStatModel( CvFGDStatModel** _model ){ CV_FUNCNAME( "icvReleaseFGDStatModel" ); __BEGIN__; if( !_model ) CV_ERROR( CV_StsNullPtr, "" ); if( *_model ) { CvFGDStatModel* model = *_model; if( model->pixel_stat ) { cvFree( &model->pixel_stat[0].ctable ); cvFree( &model->pixel_stat[0].cctable ); cvFree( &model->pixel_stat ); } cvReleaseImage( &model->Ftd ); cvReleaseImage( &model->Fbd ); cvReleaseImage( &model->foreground ); cvReleaseImage( &model->background ); cvReleaseImage( &model->prev_frame ); cvReleaseMemStorage(&model->storage); cvFree( _model ); } __END__;}// Function cvChangeDetection performs change detection for Foreground detection algorithm// parameters:// prev_frame -// curr_frame -// change_mask -/*用两幅三通道图像做差分 change_mask用来存储差分结果*/CV_IMPL intcvChangeDetection( IplImage* prev_frame, IplImage* curr_frame, IplImage* change_mask ){ int i, j, b, x, y, thres; const int PIXELRANGE=256; if( !prev_frame || !curr_frame || !change_mask || prev_frame->nChannels != 3 || curr_frame->nChannels != 3 || change_mask->nChannels != 1 || prev_frame->depth != IPL_DEPTH_8U || curr_frame->depth != IPL_DEPTH_8U || change_mask->depth != IPL_DEPTH_8U || prev_frame->width != curr_frame->width || prev_frame->height != curr_frame->height || prev_frame->width != change_mask->width || prev_frame->height != change_mask->height ){ return 0; } cvZero ( change_mask ); // All operations per colour /*分别对每个通道处理 相当于对向量的各个分量分别处理 这也是理所当然的*/ for (b=0 ; b<prev_frame->nChannels ; b++) { // Create histogram: long HISTOGRAM[PIXELRANGE]; //对0-255每个灰度差值进行统计 for (i=0 ; i<PIXELRANGE; i++) HISTOGRAM[i]=0; //差值统计的初始化 /*对应像素进行求差 然后统计*/ for (y=0 ; y<curr_frame->height ; y++) { uchar* rowStart1 = (uchar*)curr_frame->imageData + y * curr_frame->widthStep + b; uchar* rowStart2 = (uchar*)prev_frame->imageData + y * prev_frame->widthStep + b; for (x=0 ; x<curr_frame->width ; x++, rowStart1+=curr_frame->nChannels, rowStart2+=prev_frame->nChannels) { int diff = abs( int(*rowStart1) - int(*rowStart2) ); HISTOGRAM[diff]++; } } double c[PIXELRANGE]; for (i=0 ; i<PIXELRANGE; i++) relativeVariance[i]=0; //方差初始化 /*后面所写的x均值随机变量 不特指程序中的任何一个变量 以下每个差值的概率分布均是指累计概率分布 不过此处的随机变量是从255-0进行累计,并非通常的0-255 即为 p(X)=1-sum(p(x<X)) = sum(p(x>=X)) 所以此处是对每一个差值均构建了概率分布 也就是并非一条概率曲线的存在 而是254-0 共有255条概率曲线存在 每条曲线确定一个差值的方差 */ for (thres=PIXELRANGE-2; thres>=0 ; thres--) { // fprintf(stderr, "Iter %d\n", thres); double sum=0; double sqsum=0; int count=0; // fprintf(stderr, "Iter %d entering loop\n", thres); for (j=thres ; j<PIXELRANGE ; j++) { sum += double(j)*double(HISTOGRAM[j]); //因为后面会除总的统计数count 因而此处可以看做求E(x) sqsum += double(j*j)*double(HISTOGRAM[j]); //E(x*x) count += HISTOGRAM[j]; //统计总量 为求概率 } count = count == 0 ? 1 : count; // fprintf(stderr, "Iter %d finishing loop\n", thres); double my = sum / count; //均值 double sigma = sqrt( sqsum/count - my*my); //方差 D(x) = E(x*x) - E(x)*E(x) // fprintf(stderr, "Iter %d sum=%g sqsum=%g count=%d sigma = %g\n", thres, sum, sqsum, count, sigma); // fprintf(stderr, "Writing to %x\n", &(relativeVariance[thres])); relativeVariance[thres] = sigma; // fprintf(stderr, "Iter %d finished\n", thres); } // Find maximum: uchar bestThres = 0; //求出方差最大值 也就是变化值得期望 如果大于这个期望 可以认为这个点发生了较大变化 进行标注*/ double* pBestThres = _cv_max_element(relativeVariance, relativeVariance+PIXELRANGE); bestThres = (uchar)(*pBestThres); if (bestThres <10) bestThres=10; //因为uchar表示0-255,这里可以认为对最大方差进行规格化.同时设定方差的下界 for (y=0 ; y<prev_frame->height ; y++) { uchar* rowStart1 = (uchar*)(curr_frame->imageData) + y * curr_frame->widthStep + b; uchar* rowStart2 = (uchar*)(prev_frame->imageData) + y * prev_frame->widthStep + b; uchar* rowStart3 = (uchar*)(change_mask->imageData) + y * change_mask->widthStep; for (x = 0; x < curr_frame->width; x++, rowStart1+=curr_frame->nChannels, rowStart2+=prev_frame->nChannels, rowStart3+=change_mask->nChannels) { // OR between different color channels int diff = abs( int(*rowStart1) - int(*rowStart2) ); if ( diff > bestThres) //只要有一个分量发生了较大变化就可以标注 *rowStart3 |=255; //为什么不直接赋值? 与直接赋值的结果应当没有区别 } } } return 1;}
- cvbgfg_acmmm2003 源代码注释(一)
- 背景建模之:贝叶斯背景建模——cvbgfg_acmmm2003 源代码注释(一)
- FGD模型的理解 和 cvbgfg_acmmm2003 源代码注释(二)(
- 背景建模之:贝叶斯背景建模—— cvbgfg_acmmm2003 源代码注释(二)
- 注释PEMaker6源代码(一)
- 注释PEMaker6源代码(三)
- 注释PEMaker6源代码(二)
- FCKeditor源代码分析(一)-----fckeditor.js的中文注释分析(原创)
- Buffalo 学习笔记- buffalo.js 源代码注释(一)
- 编译第一步:去源代码(C)注释
- CollectConfg 源代码(一)
- SplitConfg 源代码 (一)
- linux源代码(一)
- Xcode注释插件(一)
- 作业一目标一给定一个源代码文件(.cs, .java),输出该文件的总行数、空行数、注释行数、代码行数
- 源代码 远程控制注释
- 实用:源代码注释模板
- JAVA源代码的注释
- 倾情奉献ios5.0编译ffmpeg,真机ok!
- aspnet oracle连接字符串 连接虚拟机
- 比较全的机油教程(android)
- 同步、异步和并行
- spring动态数据源1
- cvbgfg_acmmm2003 源代码注释(一)
- android Fragments详解三:实现Fragment的界面
- Service详解(二)
- “#if 0/#if 1 ... #endif”的作用
- 在Spring的项目中配置Log4j存放日志文件到指定目录下
- 学习iphone 开发过程(1)--在vmware上安装mac osx 10.7
- 支付宝设计逻辑错误
- Linux系统信息查看命令大全
- 每天进步一点点-->C语言文件操作函数