经过2天的努力终于算是大概弄清楚了opencv中的vs框架是大概是如何工作的了,下面贴一下我自己写的代码注释。非常详细。对初学者有帮助。尤其详细分析了RunBlobTrackingAuto()函数,在看注释之前应该首先大概了解一下

Blob Tracking Tests和Blob Tracking Modules的说明文档。这样比较容易理解。说明文档的位置在  opencv的安装位置的opencv\doc\vidsurv

代码注释为本人原创,转载请注明原为地址:http://blog.csdn.net/jia_zhengshen/article/details/9499103
程序的大体流程是:首先main函数读取一大堆参数,然后与预定的命令比较,比较完后给相应的参数赋值。然后给param这位二神赋值,然后通过param这个参数把pTRacker初始化,然后程序进入RunBlobTrackingAuto函数这个主循环,循环完后退出程序。流程图如下:

//#include "cvaux.h"
//#include "highgui.h"
#include<opencv/cv.h>//由于使用了source insight来写注释,所以偶尔会有乱码。
#include<opencv/highgui.h>
#include<opencv\cvaux.h>
#include <stdio.h> /* select the correct function for doing case insensitive string comparaison */
#ifdef WIN32
#define MY_STRNICMP strnicmp
#define MY_STRICMP stricmp
#else
#define MY_STRNICMP strncasecmp
#define MY_STRICMP strcasecmp
#endif /* list of FG DETECTION modules */
static CvFGDetector* cvCreateFGDetector0(){return cvCreateFGDetectorBase(CV_BG_MODEL_FGD, NULL);}
static CvFGDetector* cvCreateFGDetector0Simple(){return cvCreateFGDetectorBase(CV_BG_MODEL_FGD_SIMPLE, NULL);}
static CvFGDetector* cvCreateFGDetector1(){return cvCreateFGDetectorBase(CV_BG_MODEL_MOG, NULL);}
typedef struct DefModule_FGDetector
{
CvFGDetector* (*create)();//指向函数的指针。使用这种写法,可以使c语言具有面向对象的特性。
char* nickname;//这个FGDETECTOR的别名。Nickname相当于小名。
char* description;//这个邋fgDetector的简单描述。
} DefModule_FGDetector;
DefModule_FGDetector FGDetector_Modules[] =//这是个数组。
{
{cvCreateFGDetector0,"FG_0","Foreground Object Detection from Videos Containing Complex Background. ACM MM2003."},
{cvCreateFGDetector0Simple,"FG_0S","Simplyfied version of FG_0"},
{cvCreateFGDetector1,"FG_1","Adaptive background mixture models for real-time tracking. CVPR1999"},
{NULL,NULL,NULL}//全部为空,这里有的null有很大的作用,来指示这是这个数组的最后一个,增加其他的算法。在main函数使用这个数组时会使用到这一点。
}; /* list of BLOB DETECTION modules */
typedef struct DefModule_BlobDetector
{
CvBlobDetector* (*create)();//这个BlobDetector的作用是检验新的blob
char* nickname;
char* description;
} DefModule_BlobDetector;
DefModule_BlobDetector BlobDetector_Modules[] =//这里定义了3个blobDetector 来检验新的blob
{
{cvCreateBlobDetectorCC,"BD_CC","Detect new blob by tracking CC of FG mask"},
{cvCreateBlobDetectorSimple,"BD_Simple","Detect new blob by uniform moving of connected components of FG mask"},
{NULL,NULL,NULL}
}; /* list of BLOB TRACKING modules */
typedef struct DefModule_BlobTracker
{
CvBlobTracker* (*create)();//作用是找到blob的位置,大小,id
char* nickname;
char* description;
} DefModule_BlobTracker;
DefModule_BlobTracker BlobTracker_Modules[] =//定义了5个錌lobtracker
{
{cvCreateBlobTrackerCCMSPF,"CCMSPF","connected component tracking and MSPF resolver for collision"},
{cvCreateBlobTrackerCC,"CC","Simple connected component tracking"},
{cvCreateBlobTrackerMS,"MS","Mean shift algorithm "},
{cvCreateBlobTrackerMSFG,"MSFG","Mean shift algorithm with FG mask using"},
{cvCreateBlobTrackerMSPF,"MSPF","Particle filtering based on MS weight"},
{NULL,NULL,NULL}
}; /* list of BLOB TRAJECTORY GENERATION modules */
typedef struct DefModule_BlobTrackGen
{
CvBlobTrackGen* (*create)();//轨迹产生器(Trajectory Generator)主要作用是用于把轨迹存到一个文件中。
char* nickname;
char* description;
} DefModule_BlobTrackGen;
DefModule_BlobTrackGen BlobTrackGen_Modules[] =//定义了2个轨迹生成器。
{
{cvCreateModuleBlobTrackGenYML,"YML","Generate track record in YML format as synthetic video data"},
{cvCreateModuleBlobTrackGen1,"RawTracks","Generate raw track record (x,y,sx,sy),()... in each line"},
{NULL,NULL,NULL}
}; /* list of BLOB TRAJECTORY POST PROCESSING modules */
typedef struct DefModule_BlobTrackPostProc//轨迹的后续处理程序。
{
CvBlobTrackPostProc* (*create)();
char* nickname;
char* description;
} DefModule_BlobTrackPostProc;
DefModule_BlobTrackPostProc BlobTrackPostProc_Modules[] =
{
{cvCreateModuleBlobTrackPostProcKalman,"Kalman","Kalman filtering of blob position and size"},
{NULL,"None","No post processing filter"},
// {cvCreateModuleBlobTrackPostProcTimeAverRect,"TimeAverRect","Average by time using rectangle window"},
// {cvCreateModuleBlobTrackPostProcTimeAverExp,"TimeAverExp","Average by time using exponential window"},
{NULL,NULL,NULL}
}; /* list of BLOB TRAJECTORY ANALYSIS modules */
CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisDetector(); typedef struct DefModule_BlobTrackAnalysis
{
CvBlobTrackAnalysis* (*create)();
char* nickname;
char* description;
} DefModule_BlobTrackAnalysis;
DefModule_BlobTrackAnalysis BlobTrackAnalysis_Modules[] =
{
{cvCreateModuleBlobTrackAnalysisHistPVS,"HistPVS","Histogramm of 5D feture vector analysis (x,y,vx,vy,state)"},
{NULL,"None","No trajectory analiser"},
{cvCreateModuleBlobTrackAnalysisHistP,"HistP","Histogramm of 2D feture vector analysis (x,y)"},
{cvCreateModuleBlobTrackAnalysisHistPV,"HistPV","Histogramm of 4D feture vector analysis (x,y,vx,vy)"},
{cvCreateModuleBlobTrackAnalysisHistSS,"HistSS","Histogramm of 4D feture vector analysis (startpos,endpos)"},
{cvCreateModuleBlobTrackAnalysisTrackDist,"TrackDist","Compare tracks directly"},
{cvCreateModuleBlobTrackAnalysisIOR,"IOR","Integrator (by OR operation) of several analysers "},
{NULL,NULL,NULL}
};
/* list of Blob Trajectory ANALYSIS modules */
/*================= END MODULES DECRIPTION ===================================*/ /* run pipeline on all frames */
static int RunBlobTrackingAuto( CvCapture* pCap, CvBlobTrackerAuto* pTracker,char* fgavi_name = NULL, char* btavi_name = NULL )
{
int OneFrameProcess = 0;
int key;
int FrameNum = 0;
CvVideoWriter* pFGAvi = NULL;
CvVideoWriter* pBTAvi = NULL; //cvNamedWindow( "FG", 0 ); /* main cicle */
for( FrameNum=0; pCap && (key=cvWaitKey(OneFrameProcess?0:2))!=27;//按下esc键整个程序结束。
FrameNum++)
{/* main cicle */// 整个程序的主循环。这个循环终止,意味着这个程序结束。
IplImage* pImg = NULL;
IplImage* pMask = NULL; if(key!=-1)//这个我还不知道是什么意思。
{
OneFrameProcess = 1;
if(key=='r')OneFrameProcess = 0;
} pImg = cvQueryFrame(pCap);///从视频流中得到一帧图像pImg是这帧图像的指针。
if(pImg == NULL) break; /* Process */
pTracker->Process(pImg, pMask);//处理图像。这个函数应该执行完了所有的处理过程。 if(fgavi_name)//如果fgavi_name不为空。则执行下面的程序,如果传给 RunBlobTrackingAuto是空,则不执行。
if(pTracker->GetFGMask())//前景的图像的mask存在的话,执行下面的程序。
{/* debug FG */
IplImage* pFG = pTracker->GetFGMask();//得到前景的图像的mask,
cvShowImage("贾增申",pFG);//这里显示一下,我自己写的。
CvSize S = cvSize(pFG->width,pFG->height);
static IplImage* pI = NULL; if(pI==NULL)pI = cvCreateImage(S,pFG->depth,3);//创建一下,防止内存不存在。
cvCvtColor( pFG, pI, CV_GRAY2BGR );//由于创建的mask是一个gray图,所以为了下面显示方便,转换成bgr格式的。、、实际工程中应该可以不用这个功能。,但调试的时候很有用。 if(fgavi_name)//传过来的avi名字不为空,意思就是说,你想存一下。
{/* save fg to avi file */
if(pFGAvi==NULL)//第一次使用这个pFgAvi这个变量应该创建一下。
{
pFGAvi=cvCreateVideoWriter(
fgavi_name,
CV_FOURCC('x','v','i','d'),
25,
S );
}
cvWriteFrame( pFGAvi, pI );//写入video
} if(pTracker->GetBlobNum()>0)//pTracker找到了blob
{/* draw detected blobs */
int i;
for(i=pTracker->GetBlobNum();i>0;i--)//找到 了GetBlobNum() 个。
{
CvBlob* pB = pTracker->GetBlob(i-1);//得到第i-1个blob
CvPoint p = cvPointFrom32f(CV_BLOB_CENTER(pB));//通过看源代码,太牛逼了,这个宏竟然是个强制转换得来的。见下行。
//////////////////////////////////////////////////#define CV_BLOB_CENTER(pB) cvPoint2D32f(((CvBlob*)(pB))->x,((CvBlob*)(pB))->y)
CvSize s = cvSize(MAX(1,cvRound(CV_BLOB_RX(pB))), MAX(1,cvRound(CV_BLOB_RY(pB))));
int c = cvRound(255*pTracker->GetState(CV_BLOB_ID(pB)));
cvEllipse( pI,//在那个坐标附近话个椭圆呗 。
p,
s,
0, 0, 360,
CV_RGB(c,255-c,0), cvRound(1+(3*c)/255) );
}/* next blob */;
} cvNamedWindow( "FG",0);///显示出来。
cvShowImage( "FG",pI);
}/* debug FG*/ /* draw debug info */
if(pImg)//原始的每帧图像。
{/* draw all inforamtion about tets sequence */
char str[1024];
int line_type = CV_AA; // change it to 8 to see non-antialiased graphics
CvFont font;
int i;
IplImage* pI = cvCloneImage(pImg); cvInitFont( &font, CV_FONT_HERSHEY_PLAIN, 0.7, 0.7, 0, 1, line_type ); for(i=pTracker->GetBlobNum();i>0;i--)//得到了GetBlobNum个blob
{//下面的代码可以参看上十几行的注释,这些代码几乎一样。
CvSize TextSize;
CvBlob* pB = pTracker->GetBlob(i-1);
CvPoint p = cvPoint(cvRound(pB->x*256),cvRound(pB->y*256));
CvSize s = cvSize(MAX(1,cvRound(CV_BLOB_RX(pB)*256)), MAX(1,cvRound(CV_BLOB_RY(pB)*256)));
int c = cvRound(255*pTracker->GetState(CV_BLOB_ID(pB))); cvEllipse( pI,
p,
s,
0, 0, 360,
CV_RGB(c,255-c,0), cvRound(1+(3*0)/255), CV_AA, 8 );
p.x >>= 8;//下面代码的大概意思就是在找到的blob附近写下id。不再注释。
p.y >>= 8;
s.width >>= 8;
s.height >>= 8;
sprintf(str,"%03d",CV_BLOB_ID(pB));
cvGetTextSize( str, &font, &TextSize, NULL );
p.y -= s.height;
cvPutText( pI, str, p, &font, CV_RGB(0,255,255));
{
const char* pS = pTracker->GetStateDesc(CV_BLOB_ID(pB));
if(pS)
{
char* pStr = strdup(pS);
char* pStrFree = pStr;
for(;pStr && strlen(pStr)>0;)
{
char* str_next = strchr(pStr,'\n');
if(str_next)
{
str_next[0] = 0;
str_next++;
}
p.y += TextSize.height+1;
cvPutText( pI, pStr, p, &font, CV_RGB(0,255,255));
pStr = str_next;
}
free(pStrFree);
}
} }/* next blob */; cvNamedWindow( "Tracking", 0);//显示出画出椭圆的帧
cvShowImage( "Tracking",pI ); if(btavi_name && pI)//如果这一帧存在且,你想把图像存起来,就是传过来的参数不为空例如 btavi_name=“我日.avi" 就能存起来了。
{/* save to avi file */
CvSize S = cvSize(pI->width,pI->height);//下面的代码类似于fg的图像的存储代码,请参看上面的代码注释。
if(pBTAvi==NULL)
{
pBTAvi=cvCreateVideoWriter(
btavi_name,
CV_FOURCC('x','v','i','d'),
25,
S );
}
cvWriteFrame( pBTAvi, pI );
} cvReleaseImage(&pI);//释放掉这一帧
}/* draw all inforamtion about tets sequence */
}/* main cicle */ if(pFGAvi)cvReleaseVideoWriter( &pFGAvi );//把fg的图像存到硬盘上。
if(pBTAvi)cvReleaseVideoWriter( &pBTAvi );//把每帧图像存到硬盘上,同时释放资源。
return 0;//执行到这里的时候实际上已经退出了。我想如果不考虑内存泄露的话,可以改为exit(0) ,但是不建议,因为有内存泄露存在。还是返回到main函数比较好。
}/* RunBlobTrackingAuto */ /* read parameters from command line and transfer to specified module */
static void set_params(int argc, char* argv[], CvVSModule* pM, char* prefix, char* module)
{
int prefix_len = strlen(prefix);
int i;
for(i=0;i<argc;++i)
{
int j;
char* ptr_eq = NULL;
int cmd_param_len=0;
char* cmd = argv[i];
if(MY_STRNICMP(prefix,cmd,prefix_len)!=0) continue;
cmd += prefix_len;
if(cmd[0]!=':')continue;
cmd++; ptr_eq = strchr(cmd,'=');
if(ptr_eq)cmd_param_len = ptr_eq-cmd;
for(j=0;;++j)
{
int param_len;
const char* param = pM->GetParamName(j);
if(param==NULL) break;
param_len = strlen(param);
if(cmd_param_len!=param_len) continue;
if(MY_STRNICMP(param,cmd,param_len)!=0) continue;
cmd+=param_len;
if(cmd[0]!='=')continue;
cmd++;
pM->SetParamStr(param,cmd);
printf("%s:%s param set to %g\n",module,param,pM->GetParam(param));
}
}
pM->ParamUpdate();
}/* set_params */ /* print all parameters value for given module */
static void print_params(CvVSModule* pM, char* module, char* log_name)
{
FILE* log = log_name?fopen(log_name,"at"):NULL;
int i;
if(pM->GetParamName(0) == NULL ) return; printf("%s(%s) module parameters:\n",module,pM->GetNickName());
if(log)
fprintf(log,"%s(%s) module parameters:\n",module,pM->GetNickName());
for(i=0;;++i)
{
const char* param = pM->GetParamName(i);
const char* str = param?pM->GetParamStr(param):NULL;
if(param == NULL)break;
if(str)
{
printf(" %s: %s\n",param,str);
if(log)
fprintf(log," %s: %s\n",param,str);
}
else
{
printf(" %s: %g\n",param,pM->GetParam(param));
if(log)
fprintf(log," %s: %g\n",param,pM->GetParam(param));
}
}
if(log)fclose(log);
}/* print_params */
//本人认为,虽然这种命令行的形式可以使一个程序可以验证多种算法,但是命令行无可否认,太难用了。
int main(int argc, char* argv[])
{/* main function */
CvCapture* pCap = NULL;
CvBlobTrackerAutoParam1 param = {0};
CvBlobTrackerAuto* pTracker = NULL; float scale = 1;
char* scale_name = NULL;
char* yml_name = NULL;
char** yml_video_names = NULL;
int yml_video_num = 0;
char* avi_name = NULL;
char* fg_name = NULL;
char* fgavi_name = NULL;
char* btavi_name = NULL;
char* bd_name = NULL;
char* bt_name = NULL;
char* btgen_name = NULL;
char* btpp_name = NULL;
char* bta_name = NULL;
char* bta_data_name = NULL;
char* track_name = NULL;
char* comment_name = NULL;
char* FGTrainFrames = NULL;
char* log_name = NULL;
char* savestate_name = NULL;
char* loadstate_name = NULL;
char* bt_corr = NULL;
DefModule_FGDetector* pFGModule = NULL;
DefModule_BlobDetector* pBDModule = NULL;
DefModule_BlobTracker* pBTModule = NULL;
DefModule_BlobTrackPostProc* pBTPostProcModule = NULL;
DefModule_BlobTrackGen* pBTGenModule = NULL;
DefModule_BlobTrackAnalysis* pBTAnalysisModule = NULL; cvInitSystem(argc, argv); if(argc < 2)//如果你的参数连2个都没有就打印出帮助来。
{/* print help */
int i;
printf("blobtrack [fg=<fg_name>] [bd=<bd_name>]\n"
" [bt=<bt_name>] [btpp=<btpp_name>]\n"
" [bta=<bta_name>\n"
" [bta_data=<bta_data_name>\n"
" [bt_corr=<bt_corr_way>]\n"
" [btgen=<btgen_name>]\n"
" [track=<track_file_name>]\n"
" [scale=<scale val>] [noise=<noise_name>] [IVar=<IVar_name>]\n"
" [FGTrainFrames=<FGTrainFrames>]\n"
" [btavi=<avi output>] [fgavi=<avi output on FG>]\n"
" <avi_file>\n");
printf(" <bt_corr_way> is way of blob position corrrection for \"Blob Tracking\" module\n"
" <bt_corr_way>=none,PostProcRes\n"
" <FGTrainFrames> is number of frames for FG training\n"
" <track_file_name> is file name for save tracked trajectories\n"
" <bta_data> is file name for data base of trajectory analysis module\n"
" <avi_file> is file name of avi to process by BlobTrackerAuto\n"); puts("\nModules:");
#define PR(_name,_m,_mt)\
printf("<%s> is \"%s\" module name and can be:\n",_name,_mt);\
for(i=0;_m[i].nickname;++i)\
{\
printf(" %d. %s",i+1,_m[i].nickname);\
if(_m[i].description)printf(" - %s",_m[i].description);\
printf("\n");\
} PR("fg_name",FGDetector_Modules,"FG/BG Detection");
PR("bd_name",BlobDetector_Modules,"Blob Entrance Detection");
PR("bt_name",BlobTracker_Modules,"Blob Tracking");
PR("btpp_name",BlobTrackPostProc_Modules, "Blob Trajectory Post Processing");
PR("btgen_name",BlobTrackGen_Modules, "Blob Trajectory Generation");
PR("bta_name",BlobTrackAnalysis_Modules, "Blob Trajectory Analysis");
#undef PR
getchar();
return 0;
}/* print help */ {/* parse arguments */
int i;
for(i=1;i<argc;++i)//下面的是参数初始化。
{
int bParsed = 0;
size_t len = strlen(argv[i]);
#define RO(_n1,_n2) if(strncmp(argv[i],_n1,strlen(_n1))==0) {_n2 = argv[i]+strlen(_n1);bParsed=1;};
RO("fg=",fg_name);//着重分析这个宏,如果argv【i】等于"fg="这个字符串。
//我们就认为是给邋fg_name这个变量赋值。以下宏相同。
RO("fgavi=",fgavi_name);
RO("btavi=",btavi_name);
RO("bd=",bd_name);
RO("bt=",bt_name);
RO("bt_corr=",bt_corr);
RO("btpp=",btpp_name);
RO("bta=",bta_name);
RO("bta_data=",bta_data_name);
RO("btgen=",btgen_name);
RO("track=",track_name);
RO("comment=",comment_name);
RO("FGTrainFrames=",FGTrainFrames);
RO("log=",log_name);
RO("savestate=",savestate_name);
RO("loadstate=",loadstate_name);
#undef RO
{
char* ext = argv[i] + len-4;
if( strrchr(argv[i],'=') == NULL &&
!bParsed &&
(len>3 && (MY_STRICMP(ext,".avi") == 0 )))
{
avi_name = argv[i];//满足上面的if条件就给avi_name赋值,就是要打开的视频文件名称。
break;
}
}/* next argument */
}
}/* parse arguments */ if(track_name)//如果定义了轨迹存储的文件,就执行下面的程序。
{/* set Trajectory Generator module */
int i;
if(!btgen_name)btgen_name=BlobTrackGen_Modules[0].nickname;
for(i=0;BlobTrackGen_Modules[i].nickname;++i)//从最初这个数组的定义可以看到,最后的一个元素是null,可以根据这个条件来判断是否结束。
{
if(MY_STRICMP(BlobTrackGen_Modules[i].nickname,btgen_name)==0)
pBTGenModule = BlobTrackGen_Modules + i;
}
}/* set Trajectory Generator modulke */ /* init postprocessing module if tracker correction by postporcessing is reqierd *///后续处理,这个我没有使用,没有深究它
if(bt_corr && MY_STRICMP(bt_corr,"PostProcRes")!=0 && !btpp_name)
{
btpp_name = bt_corr;
if(MY_STRICMP(btpp_name,"none")!=0)bt_corr = "PostProcRes";
} {/* set default parameters for one processing */
if(!bt_corr) bt_corr = "none";
if(!fg_name) fg_name = FGDetector_Modules[0].nickname;//如果从main传过来的参数的邋fg_name为空,则将这个数组的第0个附给邋fg_name。
if(!bd_name) bd_name = BlobDetector_Modules[0].nickname;//同上。
if(!bt_name) bt_name = BlobTracker_Modules[0].nickname;
if(!btpp_name) btpp_name = BlobTrackPostProc_Modules[0].nickname;
if(!bta_name) bta_name = BlobTrackAnalysis_Modules[0].nickname;
if(!scale_name) scale_name = "1";
} if(scale_name) //scale这个参数在这个程序中没有使用。
scale = (float)atof(scale_name);
for(pFGModule=FGDetector_Modules;pFGModule->nickname;++pFGModule)//给邋邋邋pFGModule赋值。注意到文件最开头的几个数组的最后都是null结尾的。
if( fg_name && MY_STRICMP(fg_name,pFGModule->nickname)==0 ) break;//null是结束的标志。
for(pBDModule=BlobDetector_Modules;pBDModule->nickname;++pBDModule)
if( bd_name && MY_STRICMP(bd_name,pBDModule->nickname)==0 ) break;
for(pBTModule=BlobTracker_Modules;pBTModule->nickname;++pBTModule)
if( bt_name && MY_STRICMP(bt_name,pBTModule->nickname)==0 ) break;
for(pBTPostProcModule=BlobTrackPostProc_Modules;pBTPostProcModule->nickname;++pBTPostProcModule)
if( btpp_name && MY_STRICMP(btpp_name,pBTPostProcModule->nickname)==0 ) break;
for(pBTAnalysisModule=BlobTrackAnalysis_Modules;pBTAnalysisModule->nickname;++pBTAnalysisModule)
if( bta_name && MY_STRICMP(bta_name,pBTAnalysisModule->nickname)==0 ) break; /* create source video */
if(avi_name) //定义视频的来源。
pCap = cvCaptureFromFile(avi_name);//从邋avi_name的视频中读取数据。
//pCap = cvCreateCameraCapture(-1);//从摄像头中读取数据。 if(pCap==NULL)
{
printf("Can't open %s file\n",avi_name);
return -1;
} {/* display parameters */
int i;
FILE* log = log_name?fopen(log_name,"at"):NULL;
if(log)//rug如果定义了log的name那么就给你输出到一个log文件中。
{/* print to log file *///下面的大概意思是输出log的格式,没有深入分析。有兴趣可以自己分析。
fprintf(log,"\n=== Blob Tracking pipline in processing mode===\n");
if(avi_name)
{
fprintf(log,"AVIFile: %s\n",avi_name);
}
fprintf(log,"FGDetector: %s\n", pFGModule->nickname);
fprintf(log,"BlobDetector: %s\n", pBDModule->nickname);
fprintf(log,"BlobTracker: %s\n", pBTModule->nickname);
fprintf(log,"BlobTrackPostProc: %s\n", pBTPostProcModule->nickname);
fprintf(log,"BlobCorrection: %s\n", bt_corr);
fprintf(log,"Blob Trajectory Generator: %s (%s)\n",
pBTGenModule?pBTGenModule->nickname:"None",
track_name?track_name:"none");
fprintf(log,"BlobTrackAnalysis: %s\n", pBTAnalysisModule->nickname);
fclose(log);
} printf("\n=== Blob Tracking pipline in %s mode===\n","processing");
if(yml_name)//如果定义了yml_name 那么就读取配置文件。
{
printf("ConfigFile: %s\n",yml_name);
printf("BG: %s\n",yml_video_names[0]);
printf("FG: ");
for(i=1;i<(yml_video_num);++i){printf(yml_video_names[i]);if((i+1)<yml_video_num)printf("|");};
printf("\n");
}
if(avi_name)//这个判断是多余的,前面已经判断了很多遍了。
{
printf("AVIFile: %s\n",avi_name);
}
printf("FGDetector: %s\n", pFGModule->nickname);//输出各个模块的邋nick_name
printf("BlobDetector: %s\n", pBDModule->nickname);
printf("BlobTracker: %s\n", pBTModule->nickname);
printf("BlobTrackPostProc: %s\n", pBTPostProcModule->nickname);
printf("BlobCorrection: %s\n", bt_corr);
printf("Blob Trajectory Generator: %s (%s)\n",
pBTGenModule?pBTGenModule->nickname:"None",
track_name?track_name:"none");
printf("BlobTrackAnalysis: %s\n", pBTAnalysisModule->nickname);
}/* display parameters */ { /* create autotracker module and its components*///
param.FGTrainFrames = FGTrainFrames?atoi(FGTrainFrames):0;
//param二神出现了。。。为什么说是二神呢?因为大神还在后面。二神是为大神服务的。
//param的主要作用是param内部的指向各个模块的指针
//上面的FgTrainFrames 是int类型,,指示当前的训练的帧数。
/* Create FG Detection module */
param.pFG = pFGModule->create();//pFg的作用是指向CvFGDetector模块的地址。
if(!param.pFG)//如果没有成功,打印错误向屏幕。一般不会出现这种情况。
puts("Can not create FGDetector module");
param.pFG->SetNickName(pFGModule->nickname);//定义这个模块的昵称,原来写opencv的那群人也很浪漫,什么也得加个Nickname,比方说“小甜甜”,
set_params(argc, argv, param.pFG, "fg", pFGModule->nickname);//不太清楚这个函数是做什么的。 /* Create Blob Entrance Detection module */
param.pBD = pBDModule->create();//指向CvBlobDetector模块。
if(!param.pBD)
puts("Can not create BlobDetector module");
param.pBD->SetNickName(pBDModule->nickname);
set_params(argc, argv, param.pBD, "bd", pBDModule->nickname); /* Create blob tracker module */
param.pBT = pBTModule->create();//指向CvBlobTracker模块
if(!param.pBT)
puts("Can not create BlobTracker module");
param.pBT->SetNickName(pBTModule->nickname);
set_params(argc, argv, param.pBT, "bt", pBTModule->nickname); /* create blob trajectory generation module */
param.pBTGen = NULL;//指向CvBlobTrackGen模块
if(pBTGenModule && track_name && pBTGenModule->create)
{
param.pBTGen = pBTGenModule->create();
param.pBTGen->SetFileName(track_name);
}
if(param.pBTGen)
{
param.pBTGen->SetNickName(pBTGenModule->nickname);
set_params(argc, argv, param.pBTGen, "btgen", pBTGenModule->nickname);
} /* create blob trajectory post processing module *///你应该能看懂这句。
param.pBTPP = NULL;
if(pBTPostProcModule && pBTPostProcModule->create)
{
param.pBTPP = pBTPostProcModule->create();
}
if(param.pBTPP)
{
param.pBTPP->SetNickName(pBTPostProcModule->nickname);
set_params(argc, argv, param.pBTPP, "btpp", pBTPostProcModule->nickname);
} param.UsePPData = (bt_corr && MY_STRICMP(bt_corr,"PostProcRes")==0); /* create blob trajectory analysis module *///你应该能看懂这句。 param.pBTA = NULL;
if(pBTAnalysisModule && pBTAnalysisModule->create)
{
param.pBTA = pBTAnalysisModule->create();
param.pBTA->SetFileName(bta_data_name);
}
if(param.pBTA)
{
param.pBTA->SetNickName(pBTAnalysisModule->nickname);
set_params(argc, argv, param.pBTA, "bta", pBTAnalysisModule->nickname);
} /* create whole pipline *///pTracker大神终于出现了,原来上面全是param的初始化。通过param来初始化pTracker
pTracker = cvCreateBlobTrackerAuto1(¶m);
if(!pTracker)
puts("Can not create BlobTrackerAuto");
} { /* load states of each module from state file */
CvFileStorage* fs = NULL;
if(loadstate_name) //如果你想从已有的配置文件中读取数据就定义loadstate_name中读取。
fs=cvOpenFileStorage(loadstate_name,NULL,CV_STORAGE_READ);
if(fs)
{
printf("Load states for modules...\n");
if(param.pBT)
{
CvFileNode* fn = cvGetFileNodeByName(fs,NULL,"BlobTracker");//读取邋BlobTracker的值,
param.pBT->LoadState(fs,fn);//
} if(param.pBTA)
{
CvFileNode* fn = cvGetFileNodeByName(fs,NULL,"BlobTrackAnalyser");
param.pBTA->LoadState(fs,fn);
} if(pTracker)
{
CvFileNode* fn = cvGetFileNodeByName(fs,NULL,"BlobTrackerAuto");
pTracker->LoadState(fs,fn);
} cvReleaseFileStorage(&fs);
printf("... Modules states loaded\n");
}
}/* load states of each module */ {/* print modules parameters */
struct DefMMM
{
CvVSModule* pM;
char* name;
} Modules[] = {
{(CvVSModule*)param.pFG,"FGdetector"},
{(CvVSModule*)param.pBD,"BlobDetector"},
{(CvVSModule*)param.pBT,"BlobTracker"},
{(CvVSModule*)param.pBTGen,"TrackGen"},
{(CvVSModule*)param.pBTPP,"PostProcessing"},
{(CvVSModule*)param.pBTA,"TrackAnalysis"},
{NULL,NULL}
};
int i;
for(i=0;Modules[i].name;++i)//打各个模块的信息,这时候邋nick_name起了作用了。
{
if(Modules[i].pM)
print_params(Modules[i].pM,Modules[i].name,log_name);
}
}/* print modules parameters */ /* run pipeline *///开始流水线。流水线退出,意味着程序结束,
RunBlobTrackingAuto( pCap, pTracker, fgavi_name, btavi_name ); {/* save state and release modules *///释放内存,摄像头句柄,保存文件等。
CvFileStorage* fs = NULL;
if(savestate_name)
{
fs=cvOpenFileStorage(savestate_name,NULL,CV_STORAGE_WRITE);
}
if(fs)
{
cvStartWriteStruct(fs,"BlobTracker",CV_NODE_MAP);
if(param.pBT)param.pBT->SaveState(fs);
cvEndWriteStruct(fs);
cvStartWriteStruct(fs,"BlobTrackerAuto",CV_NODE_MAP);
if(pTracker)pTracker->SaveState(fs);
cvEndWriteStruct(fs);
cvStartWriteStruct(fs,"BlobTrackAnalyser",CV_NODE_MAP);
if(param.pBTA)param.pBTA->SaveState(fs);
cvEndWriteStruct(fs);
cvReleaseFileStorage(&fs);
}
if(param.pBT)cvReleaseBlobTracker(¶m.pBT);
if(param.pBD)cvReleaseBlobDetector(¶m.pBD);
if(param.pBTGen)cvReleaseBlobTrackGen(¶m.pBTGen);
if(param.pBTA)cvReleaseBlobTrackAnalysis(¶m.pBTA);
if(param.pFG)cvReleaseFGDetector(¶m.pFG);
if(pTracker)cvReleaseBlobTrackerAuto(&pTracker);
}/* save state and release modules*/ if(pCap)
cvReleaseCapture(&pCap);
//getchar();
return 0;
}/* main */

opencv中的vs框架中的Blob Tracking Tests的中文注释。的更多相关文章

  1. vs2015重新安装后,项目属性中的目标框架中没有framework4.6.1

    vs2015重新安装后,安装完后 项目属性中的目标框架中没有framework4.6.1,  控制面板的程序和功能中存在该安装包. 原因: NDP461-DevPack-KB3105179-CHS.e ...

  2. 在vue中使用 layui框架中的form.render()无效解决办法

    下面简单介绍在vue中使用 layui框架中的form.render()无效解决办法. 原文地址:小时刻个人技术博客 > http://small.aiweimeng.top/index.php ...

  3. Python中的Django框架中prefetch_related()函数对数据库查询的优化

    实例的背景说明 假定一个个人信息系统,需要记录系统中各个人的故乡.居住地.以及到过的城市.数据库设计如下: Models.py 内容如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 1 ...

  4. Python 中 unittest 单元测试框架中需要知识点

    现在正在使用 unittest 框架,我们来记录下这个框架的知识点: unittest 框架:我们在写接口用例的时候,会继承 unittest 当中的 TestCase 的类和方法,私有方法除外,来识 ...

  5. 在Maven项目中关于SSM框架中邮箱验证登陆

    1.你如果要在maven项目中进行邮箱邮箱验证,你首先要先到pom.xml文件中配置mail.jar,activation.jar包 <dependency> <groupId> ...

  6. vue中对element-ui框架中el-table的列的每一项数据进行操作

    vue中使用element table,表格参数格式化formatter 后台返回对应的数字, 那肯定不能直接显示数字,这时候就要对 表格进行数据操作 如图: 代码: methods: { //状态改 ...

  7. 请求在Struts2框架中的处理步骤

    上图来源于Struts2官方站点,是Struts 2 的整体结构. 一个请求在Struts2框架中的处理大概分为以下几个步骤 1 客户端初始化一个指向Servlet容器(例如Tomcat)的请求 2 ...

  8. (转载)OC学习篇之---Foundation框架中的NSObject对象

    前一篇文章讲到了OC中的代理模式,而且前几篇文章就介绍了OC中的类相关知识,从这篇文章开始我们开始介绍Foundation框架. OC中的Foundation框架是系统提供了,他就相当于是系统的一套a ...

  9. python3+request接口自动化框架中自动发送邮件

    在上一篇中的自动化框架中没有放上自动发送测试结果到邮箱的功能,在这篇文章中在补一下,哈哈 1.上一篇的代码就不在一一介绍了,本篇只介绍发送邮件的功能代码 2.在public common 文件夹中创建 ...

随机推荐

  1. 【Linux】Vim编辑器-批量注释与反注释

    [-] vim编辑器---批量注释与反注释 方法一 块选择模式 插入注释 取消注释 方法二 替换命令 批量注释 取消注释 实例演示   vim编辑器---批量注释与反注释 在使用vim编写代码的时候, ...

  2. monkey命令详解

    标准的monkey 命令 adb shell monkey [options] <eventcount> 例如: adb shell monkey -v    产生500次随机事件,作用在 ...

  3. 从头开始学JavaScript (三)——数据类型

    原文:从头开始学JavaScript (三)--数据类型 一.分类 基本数据类型:undefined.null.string.Boolean.number 复杂数据类型:object object的属 ...

  4. Swift构造函数(Initializer)和析构函数(Deinitializer)

    要初始化结构和类和其他类型的实例的属性. 默认的构造函数 struct Fahrenheit { var temperature: Doubleinit(){ temperature = 32.0 } ...

  5. google code 上源码的下载方法

    SVN全称是Subversion,是Apache的一个子项目 ,具体能够到SVN中文站(http://www.subversion.org.cn/)去了解下.Google Code是Google的一个 ...

  6. android详细信息java.util.ConcurrentModificationException变态

    在今天做android当项目,我遇到了这个异常,好吧.其实最不寻常遇到异常IllegalstateException.它们与我们的硬件连接SDK抛出,我想折磨学生阿玉啊.扯远了. 今天,我想回到这个异 ...

  7. SSH六部曲

    <strong> 一共有6步(文章底部附有源码下载地址,刚学完ssh的可以借鉴)</strong> 1 写一个Hibernate应用,完成用户的增加 1) User实体 2)U ...

  8. APP-随身听

    简单到复杂听你的专属音响界,听金融.听物业,听新闻和其他节目专辑,简要介绍了新的音频应用,给你不一样的聆听体验.还记得老歌做?这里有.您留声机的一部分!很简单的音频应用,随时随地与此应用程序来听你的私 ...

  9. openwrt路由器更换了Flash之后需要修改的源码

    假如我使用的是WR703N,改为8M内存: 1 修改openwrt/target/linux/ar71xx/image/Makefile文件 $(eval $(call SingleProfile,T ...

  10. [译]Java中的继承 VS 组合

    (文章翻译自Inheritance vs. Composition in Java) 这篇文章阐述了Java中继承和组合的概念.它首先给出了一个继承的例子然后指出怎么通过组合来提高继承的设计.最后总结 ...