通過2天的努力終於算是大概弄清楚了opencv中的vs框架是大概是如何工做的了,下面貼一下我本身寫的代碼註釋。很是詳細。對初學者有幫助。尤爲詳細分析了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 */