1 #include "opencv2/video/background_segm.hpp"
2 #include "opencv2/legacy/blobtrack.hpp"
3 #include "opencv2/legacy/legacy.hpp"
4 #include <opencv2/highgui/highgui_c.h>
5 #include <opencv2/imgproc/imgproc_c.h>
9 /* Select appropriate case insensitive string comparison function: */
10 #if defined WIN32 || defined _MSC_VER
11 # define MY_STRNICMP _strnicmp
12 # define MY_STRICMP _stricmp
13 # define MY_STRDUP _strdup
15 # define MY_STRNICMP strncasecmp
16 # define MY_STRICMP strcasecmp
17 # define MY_STRDUP strdup
20 /* List of foreground (FG) DETECTION modules: */
21 static CvFGDetector* cvCreateFGDetector0 () { return cvCreateFGDetectorBase(CV_BG_MODEL_FGD, NULL); }
22 static CvFGDetector* cvCreateFGDetector0Simple() { return cvCreateFGDetectorBase(CV_BG_MODEL_FGD_SIMPLE, NULL); }
23 static CvFGDetector* cvCreateFGDetector1 () { return cvCreateFGDetectorBase(CV_BG_MODEL_MOG, NULL); }
25 typedef struct DefModule_FGDetector
27 CvFGDetector* (*create)();
29 const char* description;
30 } DefModule_FGDetector;
32 DefModule_FGDetector FGDetector_Modules[] =
34 {cvCreateFGDetector0,"FG_0","Foreground Object Detection from Videos Containing Complex Background. ACM MM2003."},
35 {cvCreateFGDetector0Simple,"FG_0S","Simplified version of FG_0"},
36 {cvCreateFGDetector1,"FG_1","Adaptive background mixture models for real-time tracking. CVPR1999"},
40 /* List of BLOB DETECTION modules: */
41 typedef struct DefModule_BlobDetector
43 CvBlobDetector* (*create)();
45 const char* description;
46 } DefModule_BlobDetector;
48 DefModule_BlobDetector BlobDetector_Modules[] =
50 {cvCreateBlobDetectorCC,"BD_CC","Detect new blob by tracking CC of FG mask"},
51 {cvCreateBlobDetectorSimple,"BD_Simple","Detect new blob by uniform moving of connected components of FG mask"},
55 /* List of BLOB TRACKING modules: */
56 typedef struct DefModule_BlobTracker
58 CvBlobTracker* (*create)();
60 const char* description;
61 } DefModule_BlobTracker;
63 DefModule_BlobTracker BlobTracker_Modules[] =
65 {cvCreateBlobTrackerCCMSPF,"CCMSPF","connected component tracking and MSPF resolver for collision"},
66 {cvCreateBlobTrackerCC,"CC","Simple connected component tracking"},
67 {cvCreateBlobTrackerMS,"MS","Mean shift algorithm "},
68 {cvCreateBlobTrackerMSFG,"MSFG","Mean shift algorithm with FG mask using"},
69 {cvCreateBlobTrackerMSPF,"MSPF","Particle filtering based on MS weight"},
73 /* List of BLOB TRAJECTORY GENERATION modules: */
74 typedef struct DefModule_BlobTrackGen
76 CvBlobTrackGen* (*create)();
78 const char* description;
79 } DefModule_BlobTrackGen;
81 DefModule_BlobTrackGen BlobTrackGen_Modules[] =
83 {cvCreateModuleBlobTrackGenYML,"YML","Generate track record in YML format as synthetic video data"},
84 {cvCreateModuleBlobTrackGen1,"RawTracks","Generate raw track record (x,y,sx,sy),()... in each line"},
88 /* List of BLOB TRAJECTORY POST PROCESSING modules: */
89 typedef struct DefModule_BlobTrackPostProc
91 CvBlobTrackPostProc* (*create)();
93 const char* description;
94 } DefModule_BlobTrackPostProc;
96 DefModule_BlobTrackPostProc BlobTrackPostProc_Modules[] =
98 {cvCreateModuleBlobTrackPostProcKalman,"Kalman","Kalman filtering of blob position and size"},
99 {NULL,"None","No post processing filter"},
100 // {cvCreateModuleBlobTrackPostProcTimeAverRect,"TimeAverRect","Average by time using rectangle window"},
101 // {cvCreateModuleBlobTrackPostProcTimeAverExp,"TimeAverExp","Average by time using exponential window"},
105 /* List of BLOB TRAJECTORY ANALYSIS modules: */
106 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisDetector();
108 typedef struct DefModule_BlobTrackAnalysis
110 CvBlobTrackAnalysis* (*create)();
111 const char* nickname;
112 const char* description;
113 } DefModule_BlobTrackAnalysis;
115 DefModule_BlobTrackAnalysis BlobTrackAnalysis_Modules[] =
117 {cvCreateModuleBlobTrackAnalysisHistPVS,"HistPVS","Histogram of 5D feature vector analysis (x,y,vx,vy,state)"},
118 {NULL,"None","No trajectory analiser"},
119 {cvCreateModuleBlobTrackAnalysisHistP,"HistP","Histogram of 2D feature vector analysis (x,y)"},
120 {cvCreateModuleBlobTrackAnalysisHistPV,"HistPV","Histogram of 4D feature vector analysis (x,y,vx,vy)"},
121 {cvCreateModuleBlobTrackAnalysisHistSS,"HistSS","Histogram of 4D feature vector analysis (startpos,endpos)"},
122 {cvCreateModuleBlobTrackAnalysisTrackDist,"TrackDist","Compare tracks directly"},
123 {cvCreateModuleBlobTrackAnalysisIOR,"IOR","Integrator (by OR operation) of several analysers "},
127 /* List of Blob Trajectory ANALYSIS modules: */
128 /*================= END MODULES DECRIPTION ===================================*/
130 /* Run pipeline on all frames: */
131 static int RunBlobTrackingAuto( CvCapture* pCap, CvBlobTrackerAuto* pTracker,char* fgavi_name = NULL, char* btavi_name = NULL )
133 int OneFrameProcess = 0;
136 CvVideoWriter* pFGAvi = NULL;
137 CvVideoWriter* pBTAvi = NULL;
139 //cvNamedWindow( "FG", 0 );
142 for( FrameNum=0; pCap && (key=cvWaitKey(OneFrameProcess?0:1))!=27;
145 IplImage* pImg = NULL;
146 IplImage* pMask = NULL;
151 if(key=='r')OneFrameProcess = 0;
154 pImg = cvQueryFrame(pCap);
155 if(pImg == NULL) break;
159 pTracker->Process(pImg, pMask);
162 if(pTracker->GetFGMask())
164 IplImage* pFG = pTracker->GetFGMask();
165 CvSize S = cvSize(pFG->width,pFG->height);
166 static IplImage* pI = NULL;
168 if(pI==NULL)pI = cvCreateImage(S,pFG->depth,3);
169 cvCvtColor( pFG, pI, CV_GRAY2BGR );
172 { /* Save fg to avi file: */
175 pFGAvi=cvCreateVideoWriter(
177 CV_FOURCC('x','v','i','d'),
181 cvWriteFrame( pFGAvi, pI );
184 if(pTracker->GetBlobNum()>0)
185 { /* Draw detected blobs: */
187 for(i=pTracker->GetBlobNum();i>0;i--)
189 CvBlob* pB = pTracker->GetBlob(i-1);
190 CvPoint p = cvPointFrom32f(CV_BLOB_CENTER(pB));
191 CvSize s = cvSize(MAX(1,cvRound(CV_BLOB_RX(pB))), MAX(1,cvRound(CV_BLOB_RY(pB))));
192 int c = cvRound(255*pTracker->GetState(CV_BLOB_ID(pB)));
197 CV_RGB(c,255-c,0), cvRound(1+(3*c)/255) );
201 cvNamedWindow( "FG",0);
202 cvShowImage( "FG",pI);
206 /* Draw debug info: */
208 { /* Draw all information about test sequence: */
210 int line_type = CV_AA; // Change it to 8 to see non-antialiased graphics.
213 IplImage* pI = cvCloneImage(pImg);
215 cvInitFont( &font, CV_FONT_HERSHEY_PLAIN, 0.7, 0.7, 0, 1, line_type );
217 for(i=pTracker->GetBlobNum(); i>0; i--)
220 CvBlob* pB = pTracker->GetBlob(i-1);
221 CvPoint p = cvPoint(cvRound(pB->x*256),cvRound(pB->y*256));
222 CvSize s = cvSize(MAX(1,cvRound(CV_BLOB_RX(pB)*256)), MAX(1,cvRound(CV_BLOB_RY(pB)*256)));
223 int c = cvRound(255*pTracker->GetState(CV_BLOB_ID(pB)));
229 CV_RGB(c,255-c,0), cvRound(1+(3*0)/255), CV_AA, 8 );
235 sprintf(str,"%03d",CV_BLOB_ID(pB));
236 cvGetTextSize( str, &font, &TextSize, NULL );
238 cvPutText( pI, str, p, &font, CV_RGB(0,255,255));
240 const char* pS = pTracker->GetStateDesc(CV_BLOB_ID(pB));
244 char* pStr = MY_STRDUP(pS);
245 char* pStrFree = pStr;
247 while (pStr && strlen(pStr) > 0)
249 char* str_next = strchr(pStr,'\n');
257 p.y += TextSize.height+1;
258 cvPutText( pI, pStr, p, &font, CV_RGB(0,255,255));
267 cvNamedWindow( "Tracking", 0);
268 cvShowImage( "Tracking",pI );
271 { /* Save to avi file: */
272 CvSize S = cvSize(pI->width,pI->height);
275 pBTAvi=cvCreateVideoWriter(
277 CV_FOURCC('x','v','i','d'),
281 cvWriteFrame( pBTAvi, pI );
285 } /* Draw all information about test sequence. */
288 if(pFGAvi)cvReleaseVideoWriter( &pFGAvi );
289 if(pBTAvi)cvReleaseVideoWriter( &pBTAvi );
291 } /* RunBlobTrackingAuto */
293 /* Read parameters from command line
294 * and transfer to specified module:
296 static void set_params(int argc, char* argv[], CvVSModule* pM, const char* prefix, const char* module)
298 int prefix_len = (int)strlen(prefix);
300 for(i=0; i<argc; ++i)
306 if(MY_STRNICMP(prefix,cmd,prefix_len)!=0) continue;
308 if(cmd[0]!=':')continue;
311 ptr_eq = strchr(cmd,'=');
313 cmd_param_len = (int)(ptr_eq-cmd);
318 const char* param = pM->GetParamName(j);
319 if(param==NULL) break;
320 param_len = (int)strlen(param);
321 if(cmd_param_len!=param_len) continue;
322 if(MY_STRNICMP(param,cmd,param_len)!=0) continue;
324 if(cmd[0]!='=')continue;
326 pM->SetParamStr(param,cmd);
327 printf("%s:%s param set to %g\n",module,param,pM->GetParam(param));
335 /* Print all parameter values for given module: */
336 static void print_params(CvVSModule* pM, const char* module, const char* log_name)
338 FILE* log = log_name?fopen(log_name,"at"):NULL;
340 if(pM->GetParamName(0) == NULL ) return;
343 printf("%s(%s) module parameters:\n",module,pM->GetNickName());
345 fprintf(log,"%s(%s) module parameters:\n",module,pM->GetNickName());
349 const char* param = pM->GetParamName(i);
350 const char* str = param?pM->GetParamStr(param):NULL;
351 if(param == NULL)break;
354 printf(" %s: %s\n",param,str);
356 fprintf(log," %s: %s\n",param,str);
360 printf(" %s: %g\n",param,pM->GetParam(param));
362 fprintf(log," %s: %g\n",param,pM->GetParam(param));
370 int main(int argc, char* argv[])
371 { /* Main function: */
372 CvCapture* pCap = NULL;
373 CvBlobTrackerAutoParam1 param = {0,0,0,0,0,0,0,0};
374 CvBlobTrackerAuto* pTracker = NULL;
377 const char* scale_name = NULL;
378 char* yml_name = NULL;
379 char** yml_video_names = NULL;
380 int yml_video_num = 0;
381 char* avi_name = NULL;
382 const char* fg_name = NULL;
383 char* fgavi_name = NULL;
384 char* btavi_name = NULL;
385 const char* bd_name = NULL;
386 const char* bt_name = NULL;
387 const char* btgen_name = NULL;
388 const char* btpp_name = NULL;
389 const char* bta_name = NULL;
390 char* bta_data_name = NULL;
391 char* track_name = NULL;
392 //char* comment_name = NULL;
393 char* FGTrainFrames = NULL;
394 char* log_name = NULL;
395 char* savestate_name = NULL;
396 char* loadstate_name = NULL;
397 const char* bt_corr = NULL;
398 DefModule_FGDetector* pFGModule = NULL;
399 DefModule_BlobDetector* pBDModule = NULL;
400 DefModule_BlobTracker* pBTModule = NULL;
401 DefModule_BlobTrackPostProc* pBTPostProcModule = NULL;
402 DefModule_BlobTrackGen* pBTGenModule = NULL;
403 DefModule_BlobTrackAnalysis* pBTAnalysisModule = NULL;
405 cvInitSystem(argc, argv);
410 printf("blobtrack [fg=<fg_name>] [bd=<bd_name>]\n"
411 " [bt=<bt_name>] [btpp=<btpp_name>]\n"
413 " [bta_data=<bta_data_name>\n"
414 " [bt_corr=<bt_corr_way>]\n"
415 " [btgen=<btgen_name>]\n"
416 " [track=<track_file_name>]\n"
417 " [scale=<scale val>] [noise=<noise_name>] [IVar=<IVar_name>]\n"
418 " [FGTrainFrames=<FGTrainFrames>]\n"
419 " [btavi=<avi output>] [fgavi=<avi output on FG>]\n"
422 printf(" <bt_corr_way> is the method of blob position correction for the \"Blob Tracking\" module\n"
423 " <bt_corr_way>=none,PostProcRes\n"
424 " <FGTrainFrames> is number of frames for FG training\n"
425 " <track_file_name> is file name for save tracked trajectories\n"
426 " <bta_data> is file name for data base of trajectory analysis module\n"
427 " <avi_file> is file name of avi to process by BlobTrackerAuto\n");
430 #define PR(_name,_m,_mt)\
431 printf("<%s> is \"%s\" module name and can be:\n",_name,_mt);\
432 for(i=0; _m[i].nickname; ++i)\
434 printf(" %d. %s",i+1,_m[i].nickname);\
435 if(_m[i].description)printf(" - %s",_m[i].description);\
439 PR("fg_name",FGDetector_Modules,"FG/BG Detection");
440 PR("bd_name",BlobDetector_Modules,"Blob Entrance Detection");
441 PR("bt_name",BlobTracker_Modules,"Blob Tracking");
442 PR("btpp_name",BlobTrackPostProc_Modules, "Blob Trajectory Post Processing");
443 PR("btgen_name",BlobTrackGen_Modules, "Blob Trajectory Generation");
444 PR("bta_name",BlobTrackAnalysis_Modules, "Blob Trajectory Analysis");
449 { /* Parse arguments: */
451 for(i=1; i<argc; ++i)
454 size_t len = strlen(argv[i]);
455 #define RO(_n1,_n2) if(strncmp(argv[i],_n1,strlen(_n1))==0) {_n2 = argv[i]+strlen(_n1);bParsed=1;};
457 RO("fgavi=",fgavi_name);
458 RO("btavi=",btavi_name);
461 RO("bt_corr=",bt_corr);
462 RO("btpp=",btpp_name);
464 RO("bta_data=",bta_data_name);
465 RO("btgen=",btgen_name);
466 RO("track=",track_name);
467 //RO("comment=",comment_name);
468 RO("FGTrainFrames=",FGTrainFrames);
470 RO("savestate=",savestate_name);
471 RO("loadstate=",loadstate_name);
474 char* ext = argv[i] + len-4;
475 if( strrchr(argv[i],'=') == NULL &&
477 (len>3 && (MY_STRICMP(ext,".avi") == 0 )))
482 } /* Next argument. */
484 } /* Parse arguments. */
487 { /* Set Trajectory Generator module: */
489 if(!btgen_name)btgen_name=BlobTrackGen_Modules[0].nickname;
491 for(i=0; BlobTrackGen_Modules[i].nickname; ++i)
493 if(MY_STRICMP(BlobTrackGen_Modules[i].nickname,btgen_name)==0)
494 pBTGenModule = BlobTrackGen_Modules + i;
496 } /* Set Trajectory Generato module. */
498 /* Initialize postprocessing module if tracker
499 * correction by postprocessing is required.
501 if(bt_corr && MY_STRICMP(bt_corr,"PostProcRes")!=0 && !btpp_name)
504 if(MY_STRICMP(btpp_name,"none")!=0)bt_corr = "PostProcRes";
507 { /* Set default parameters for one processing: */
508 if(!bt_corr) bt_corr = "none";
509 if(!fg_name) fg_name = FGDetector_Modules[0].nickname;
510 if(!bd_name) bd_name = BlobDetector_Modules[0].nickname;
511 if(!bt_name) bt_name = BlobTracker_Modules[0].nickname;
512 if(!btpp_name) btpp_name = BlobTrackPostProc_Modules[0].nickname;
513 if(!bta_name) bta_name = BlobTrackAnalysis_Modules[0].nickname;
514 if(!scale_name) scale_name = "1";
518 // scale = (float)atof(scale_name);
520 for(pFGModule=FGDetector_Modules; pFGModule->nickname; ++pFGModule)
521 if( fg_name && MY_STRICMP(fg_name,pFGModule->nickname)==0 ) break;
523 for(pBDModule=BlobDetector_Modules; pBDModule->nickname; ++pBDModule)
524 if( bd_name && MY_STRICMP(bd_name,pBDModule->nickname)==0 ) break;
526 for(pBTModule=BlobTracker_Modules; pBTModule->nickname; ++pBTModule)
527 if( bt_name && MY_STRICMP(bt_name,pBTModule->nickname)==0 ) break;
529 for(pBTPostProcModule=BlobTrackPostProc_Modules; pBTPostProcModule->nickname; ++pBTPostProcModule)
530 if( btpp_name && MY_STRICMP(btpp_name,pBTPostProcModule->nickname)==0 ) break;
532 for(pBTAnalysisModule=BlobTrackAnalysis_Modules; pBTAnalysisModule->nickname; ++pBTAnalysisModule)
533 if( bta_name && MY_STRICMP(bta_name,pBTAnalysisModule->nickname)==0 ) break;
535 /* Create source video: */
537 pCap = cvCaptureFromFile(avi_name);
541 printf("Can't open %s file\n",avi_name);
546 { /* Display parameters: */
548 FILE* log = log_name?fopen(log_name,"at"):NULL;
550 { /* Print to log file: */
551 fprintf(log,"\n=== Blob Tracking pipline in processing mode===\n");
554 fprintf(log,"AVIFile: %s\n",avi_name);
556 fprintf(log,"FGDetector: %s\n", pFGModule->nickname);
557 fprintf(log,"BlobDetector: %s\n", pBDModule->nickname);
558 fprintf(log,"BlobTracker: %s\n", pBTModule->nickname);
559 fprintf(log,"BlobTrackPostProc: %s\n", pBTPostProcModule->nickname);
560 fprintf(log,"BlobCorrection: %s\n", bt_corr);
562 fprintf(log,"Blob Trajectory Generator: %s (%s)\n",
563 pBTGenModule?pBTGenModule->nickname:"None",
564 track_name?track_name:"none");
566 fprintf(log,"BlobTrackAnalysis: %s\n", pBTAnalysisModule->nickname);
570 printf("\n=== Blob Tracking pipline in %s mode===\n","processing");
573 printf("ConfigFile: %s\n",yml_name);
574 printf("BG: %s\n",yml_video_names[0]);
576 for(i=1;i<(yml_video_num);++i){printf("%s",yml_video_names[i]);if((i+1)<yml_video_num)printf("|");};
581 printf("AVIFile: %s\n",avi_name);
583 printf("FGDetector: %s\n", pFGModule->nickname);
584 printf("BlobDetector: %s\n", pBDModule->nickname);
585 printf("BlobTracker: %s\n", pBTModule->nickname);
586 printf("BlobTrackPostProc: %s\n", pBTPostProcModule->nickname);
587 printf("BlobCorrection: %s\n", bt_corr);
589 printf("Blob Trajectory Generator: %s (%s)\n",
590 pBTGenModule?pBTGenModule->nickname:"None",
591 track_name?track_name:"none");
593 printf("BlobTrackAnalysis: %s\n", pBTAnalysisModule->nickname);
595 } /* Display parameters. */
597 { /* Create autotracker module and its components: */
598 param.FGTrainFrames = FGTrainFrames?atoi(FGTrainFrames):0;
600 /* Create FG Detection module: */
601 param.pFG = pFGModule->create();
603 puts("Can not create FGDetector module");
604 param.pFG->SetNickName(pFGModule->nickname);
605 set_params(argc, argv, param.pFG, "fg", pFGModule->nickname);
607 /* Create Blob Entrance Detection module: */
608 param.pBD = pBDModule->create();
610 puts("Can not create BlobDetector module");
611 param.pBD->SetNickName(pBDModule->nickname);
612 set_params(argc, argv, param.pBD, "bd", pBDModule->nickname);
614 /* Create blob tracker module: */
615 param.pBT = pBTModule->create();
617 puts("Can not create BlobTracker module");
618 param.pBT->SetNickName(pBTModule->nickname);
619 set_params(argc, argv, param.pBT, "bt", pBTModule->nickname);
621 /* Create blob trajectory generation module: */
623 if(pBTGenModule && track_name && pBTGenModule->create)
625 param.pBTGen = pBTGenModule->create();
626 param.pBTGen->SetFileName(track_name);
630 param.pBTGen->SetNickName(pBTGenModule->nickname);
631 set_params(argc, argv, param.pBTGen, "btgen", pBTGenModule->nickname);
634 /* Create blob trajectory post processing module: */
636 if(pBTPostProcModule && pBTPostProcModule->create)
638 param.pBTPP = pBTPostProcModule->create();
642 param.pBTPP->SetNickName(pBTPostProcModule->nickname);
643 set_params(argc, argv, param.pBTPP, "btpp", pBTPostProcModule->nickname);
646 param.UsePPData = (bt_corr && MY_STRICMP(bt_corr,"PostProcRes")==0);
648 /* Create blob trajectory analysis module: */
650 if(pBTAnalysisModule && pBTAnalysisModule->create)
652 param.pBTA = pBTAnalysisModule->create();
653 param.pBTA->SetFileName(bta_data_name);
657 param.pBTA->SetNickName(pBTAnalysisModule->nickname);
658 set_params(argc, argv, param.pBTA, "bta", pBTAnalysisModule->nickname);
661 /* Create whole pipline: */
662 pTracker = cvCreateBlobTrackerAuto1(¶m);
664 puts("Can not create BlobTrackerAuto");
667 { /* Load states of each module from state file: */
668 CvFileStorage* fs = NULL;
670 fs=cvOpenFileStorage(loadstate_name,NULL,CV_STORAGE_READ);
673 printf("Load states for modules...\n");
676 CvFileNode* fn = cvGetFileNodeByName(fs,NULL,"BlobTracker");
677 param.pBT->LoadState(fs,fn);
682 CvFileNode* fn = cvGetFileNodeByName(fs,NULL,"BlobTrackAnalyser");
683 param.pBTA->LoadState(fs,fn);
688 CvFileNode* fn = cvGetFileNodeByName(fs,NULL,"BlobTrackerAuto");
689 pTracker->LoadState(fs,fn);
692 cvReleaseFileStorage(&fs);
693 printf("... Modules states loaded\n");
695 } /* Load states of each module. */
697 { /* Print module parameters: */
703 {(CvVSModule*)param.pFG,"FGdetector"},
704 {(CvVSModule*)param.pBD,"BlobDetector"},
705 {(CvVSModule*)param.pBT,"BlobTracker"},
706 {(CvVSModule*)param.pBTGen,"TrackGen"},
707 {(CvVSModule*)param.pBTPP,"PostProcessing"},
708 {(CvVSModule*)param.pBTA,"TrackAnalysis"},
712 for(i=0; Modules[i].name; ++i)
715 print_params(Modules[i].pM,Modules[i].name,log_name);
717 } /* Print module parameters. */
720 RunBlobTrackingAuto( pCap, pTracker, fgavi_name, btavi_name );
722 { /* Save state and release modules: */
723 CvFileStorage* fs = NULL;
726 fs=cvOpenFileStorage(savestate_name,NULL,CV_STORAGE_WRITE);
730 cvStartWriteStruct(fs,"BlobTracker",CV_NODE_MAP);
731 if(param.pBT)param.pBT->SaveState(fs);
732 cvEndWriteStruct(fs);
733 cvStartWriteStruct(fs,"BlobTrackerAuto",CV_NODE_MAP);
734 if(pTracker)pTracker->SaveState(fs);
735 cvEndWriteStruct(fs);
736 cvStartWriteStruct(fs,"BlobTrackAnalyser",CV_NODE_MAP);
737 if(param.pBTA)param.pBTA->SaveState(fs);
738 cvEndWriteStruct(fs);
739 cvReleaseFileStorage(&fs);
741 if(param.pBT)cvReleaseBlobTracker(¶m.pBT);
742 if(param.pBD)cvReleaseBlobDetector(¶m.pBD);
743 if(param.pBTGen)cvReleaseBlobTrackGen(¶m.pBTGen);
744 if(param.pBTA)cvReleaseBlobTrackAnalysis(¶m.pBTA);
745 if(param.pFG)cvReleaseFGDetector(¶m.pFG);
746 if(pTracker)cvReleaseBlobTrackerAuto(&pTracker);
748 } /* Save state and release modules. */
751 cvReleaseCapture(&pCap);