From 56d169c81a42f3f473b8ce53b514798685c7ea9c Mon Sep 17 00:00:00 2001 From: Antoine Villeret Date: Sat, 22 Sep 2012 15:06:16 +0000 Subject: add a blobtracker svn path=/trunk/externals/pix_opencv/; revision=16264 --- blobtrack.cpp | 643 +++++++++++++++++++++++++++++++++++++++++++ blobtrack.h | 130 +++++++++ pix_opencv_blobtrack-help.pd | 219 +++++++++++++++ pix_opencv_blobtrack.cpp | 556 +++++++++++++++++++++++++++++++++++++ pix_opencv_blobtrack.h | 104 +++++++ 5 files changed, 1652 insertions(+) create mode 100644 blobtrack.cpp create mode 100644 blobtrack.h create mode 100644 pix_opencv_blobtrack-help.pd create mode 100644 pix_opencv_blobtrack.cpp create mode 100644 pix_opencv_blobtrack.h diff --git a/blobtrack.cpp b/blobtrack.cpp new file mode 100644 index 0000000..431476e --- /dev/null +++ b/blobtrack.cpp @@ -0,0 +1,643 @@ +/* + * OpenCV 2.3 - blobtrack_sample.cpp ported to Gem by Antoine Villeret - 2012 +*/ + +#include "blobtrack.h" +#include "opencv2/video/background_segm.hpp" +#include "opencv2/legacy/blobtrack.hpp" +#include "opencv2/highgui/highgui.hpp" +#include + +#include + +/* List of Blob Trajectory ANALYSIS modules: */ +/*================= END MODULES DECRIPTION ===================================*/ + +/* Run pipeline on all frames: */ +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 loop: */ + for( FrameNum=0; pCap && (key=cvWaitKey(OneFrameProcess?0:1))!=27; + FrameNum++) + { /* Main loop: */ + IplImage* pImg = NULL; + IplImage* pMask = NULL; + + if(key!=-1) + { + OneFrameProcess = 1; + if(key=='r')OneFrameProcess = 0; + } + + pImg = cvQueryFrame(pCap); + if(pImg == NULL) break; + + + /* Process: */ + pTracker->Process(pImg, pMask); + + if(fgavi_name) + if(pTracker->GetFGMask()) + { /* Debug FG: */ + IplImage* pFG = pTracker->GetFGMask(); + 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 ); + + if(fgavi_name) + { /* Save fg to avi file: */ + if(pFGAvi==NULL) + { + pFGAvi=cvCreateVideoWriter( + fgavi_name, + CV_FOURCC('x','v','i','d'), + 25, + S ); + } + cvWriteFrame( pFGAvi, pI ); + } + + if(pTracker->GetBlobNum()>0) + { /* Draw detected blobs: */ + int i; + for(i=pTracker->GetBlobNum();i>0;i--) + { + CvBlob* pB = pTracker->GetBlob(i-1); + CvPoint p = cvPointFrom32f(CV_BLOB_CENTER(pB)); + 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 information about test 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--) + { + 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; + 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; + + while (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) + { /* Save to avi file: */ + CvSize S = cvSize(pI->width,pI->height); + if(pBTAvi==NULL) + { + pBTAvi=cvCreateVideoWriter( + btavi_name, + CV_FOURCC('x','v','i','d'), + 25, + S ); + } + cvWriteFrame( pBTAvi, pI ); + } + + cvReleaseImage(&pI); + } /* Draw all information about test sequence. */ + } /* Main loop. */ + + if(pFGAvi)cvReleaseVideoWriter( &pFGAvi ); + if(pBTAvi)cvReleaseVideoWriter( &pBTAvi ); + return 0; +} /* RunBlobTrackingAuto */ + +/* Read parameters from command line + * and transfer to specified module: + */ +void set_params(int argc, char* argv[], CvVSModule* pM, const char* prefix, const char* module) +{ + int prefix_len = strlen(prefix); + int i; + for(i=0; iGetParamName(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 parameter values for given module: */ +void print_params(CvVSModule* pM, const char* module, const 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}; // TODO need more params + CvBlobTrackerAuto* pTracker = NULL; + + float scale = 1; + const char* scale_name = NULL; + char* yml_name = NULL; + char** yml_video_names = NULL; + int yml_video_num = 0; + char* avi_name = NULL; + const char* fg_name = NULL; + char* fgavi_name = NULL; + char* btavi_name = NULL; + const char* bd_name = NULL; + const char* bt_name = NULL; + const char* btgen_name = NULL; + const char* btpp_name = NULL; + const 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; + const 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) + { /* Print help: */ + int i; + printf("blobtrack [fg=] [bd=]\n" + " [bt=] [btpp=]\n" + " [bta=\n" + " [bta_data=\n" + " [bt_corr=]\n" + " [btgen=]\n" + " [track=]\n" + " [scale=] [noise=] [IVar=]\n" + " [FGTrainFrames=]\n" + " [btavi=] [fgavi=]\n" + " \n"); + + printf(" is the method of blob position correction for the \"Blob Tracking\" module\n" + " =none,PostProcRes\n" + " is number of frames for FG training\n" + " is file name for save tracked trajectories\n" + " is file name for data base of trajectory analysis module\n" + " 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 + return 0; + } /* Print help. */ + + { /* Parse arguments: */ + int i; + for(i=1; inickname; ++pFGModule) + if( fg_name && MY_STRICMP(fg_name,pFGModule->nickname)==0 ) break; + + 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); + + 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) + { /* Print to log file: */ + 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) + { + 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("%s",yml_video_names[i]);if((i+1)nickname); + 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; + + /* Create FG Detection module: */ + param.pFG = pFGModule->create(); + if(!param.pFG) + puts("Can not create FGDetector module"); + param.pFG->SetNickName(pFGModule->nickname); + set_params(argc, argv, param.pFG, "fg", pFGModule->nickname); + + /* Create Blob Entrance Detection module: */ + param.pBD = pBDModule->create(); + 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(); + 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; + 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 = cvCreateBlobTrackerAuto1(¶m); + if(!pTracker) + puts("Can not create BlobTrackerAuto"); + } + + { /* Load states of each module from state file: */ + CvFileStorage* fs = NULL; + if(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"); + 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 module parameters: */ + struct DefMMM + { + CvVSModule* pM; + const 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) + { + if(Modules[i].pM) + print_params(Modules[i].pM,Modules[i].name,log_name); + } + } /* Print module 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); + + return 0; + +} /* main() */ + + +q diff --git a/blobtrack.h b/blobtrack.h new file mode 100644 index 0000000..14c5df7 --- /dev/null +++ b/blobtrack.h @@ -0,0 +1,130 @@ +#include "opencv2/video/background_segm.hpp" +#include "opencv2/legacy/blobtrack.hpp" +#include "opencv2/highgui/highgui.hpp" +#include + +#include + +/* Select appropriate case insensitive string comparison function: */ +#if defined WIN32 || defined _MSC_VER + #define MY_STRNICMP strnicmp + #define MY_STRICMP stricmp +#else + #define MY_STRNICMP strncasecmp + #define MY_STRICMP strcasecmp +#endif + +/* List of foreground (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)(); + const char* nickname; + const char* description; +} DefModule_FGDetector; + +DefModule_FGDetector FGDetector_Modules[] = +{ + {cvCreateFGDetector0,"FG_0","Foreground Object Detection from Videos Containing Complex Background. ACM MM2003."}, + {cvCreateFGDetector0Simple,"FG_0S","Simplified version of FG_0"}, + {cvCreateFGDetector1,"FG_1","Adaptive background mixture models for real-time tracking. CVPR1999"}, + {NULL,NULL,NULL} +}; + +/* List of BLOB DETECTION modules: */ +typedef struct DefModule_BlobDetector +{ + CvBlobDetector* (*create)(); + const char* nickname; + const char* description; +} DefModule_BlobDetector; + +DefModule_BlobDetector BlobDetector_Modules[] = +{ + {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)(); + const char* nickname; + const char* description; +} DefModule_BlobTracker; + +DefModule_BlobTracker BlobTracker_Modules[] = +{ + {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)(); + const char* nickname; + const char* description; +} DefModule_BlobTrackGen; + +DefModule_BlobTrackGen BlobTrackGen_Modules[] = +{ + {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)(); + const char* nickname; + const 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)(); + const char* nickname; + const char* description; +} DefModule_BlobTrackAnalysis; + +DefModule_BlobTrackAnalysis BlobTrackAnalysis_Modules[] = +{ + {cvCreateModuleBlobTrackAnalysisHistPVS,"HistPVS","Histogram of 5D feature vector analysis (x,y,vx,vy,state)"}, + {NULL,"None","No trajectory analiser"}, + {cvCreateModuleBlobTrackAnalysisHistP,"HistP","Histogram of 2D feature vector analysis (x,y)"}, + {cvCreateModuleBlobTrackAnalysisHistPV,"HistPV","Histogram of 4D feature vector analysis (x,y,vx,vy)"}, + {cvCreateModuleBlobTrackAnalysisHistSS,"HistSS","Histogram of 4D feature vector analysis (startpos,endpos)"}, + {cvCreateModuleBlobTrackAnalysisTrackDist,"TrackDist","Compare tracks directly"}, + {cvCreateModuleBlobTrackAnalysisIOR,"IOR","Integrator (by OR operation) of several analysers "}, + {NULL,NULL,NULL} +}; + +/* +class blobtracker { + int RunBlobTrackingAuto( CvCapture* pCap, CvBlobTrackerAuto* pTracker,char* fgavi_name = NULL, char* btavi_name = NULL ); + void print_params(CvVSModule* pM, const char* module, const char* log_name); + void set_params(int argc, char* argv[], CvVSModule* pM, const char* prefix, const char* module); +}; +*/ diff --git a/pix_opencv_blobtrack-help.pd b/pix_opencv_blobtrack-help.pd new file mode 100644 index 0000000..331c272 --- /dev/null +++ b/pix_opencv_blobtrack-help.pd @@ -0,0 +1,219 @@ +#N canvas 259 343 818 435 10; +#X obj 7 200 cnv 15 430 230 empty empty empty 20 12 0 14 -233017 -66577 +0; +#X obj 7 156 cnv 15 430 40 empty empty empty 20 12 0 14 -195568 -66577 +0; +#X text 16 160 Arguments:; +#X obj 7 60 cnv 15 430 90 empty empty empty 20 12 0 14 -233017 -66577 +0; +#X obj 443 10 cnv 15 320 420 empty empty empty 20 12 0 14 -228992 -66577 +0; +#X text 50 19 Synopsis: [pix_opencv_blobtrack]; +#X text 71 38 Class: pix_opencv; +#X text 17 63 Description: all-in-one blobtracker; +#X text 28 86 [pix_opencv_blobtrack] implements a blobtracking pipeline. +This is made by a foreground detector \, a blob detector \, a blob +tracker and a trajectory post processor.; +#X text 30 173 none; +#X obj 450 216 cnv 15 250 120 empty empty empty 20 12 0 14 -4034 -66577 +0; +#X obj 656 363 cnv 15 100 60 empty empty empty 20 12 0 14 -195568 -66577 +0; +#N canvas 1 98 450 300 gemwin 0; +#X obj 132 136 gemwin; +#X obj 67 89 outlet; +#X obj 67 10 inlet; +#X obj 67 41 route create; +#X msg 67 70 set destroy; +#X msg 142 68 set create; +#X msg 132 112 create \, 1; +#X msg 198 112 destroy; +#X msg 234 221 dimen 500 500; +#X obj 295 164 loadbang; +#X msg 279 190 dimen 640 480; +#X connect 2 0 3 0; +#X connect 3 0 4 0; +#X connect 3 0 6 0; +#X connect 3 1 5 0; +#X connect 3 1 7 0; +#X connect 4 0 1 0; +#X connect 5 0 1 0; +#X connect 6 0 0 0; +#X connect 7 0 0 0; +#X connect 8 0 0 0; +#X connect 9 0 10 0; +#X connect 10 0 0 0; +#X restore 661 402 pd gemwin; +#X msg 661 383 destroy; +#X text 657 362 Create window:; +#X obj 454 364 pix_texture; +#X obj 454 30 gemhead; +#X msg 520 45 auto 1; +#X obj 520 18 loadbang; +#X obj 606 295 print dumpout; +#X floatatom 501 293 5 0 0 0 - - -; +#X obj 501 274 route blobnum blob; +#N canvas 1087 211 709 722 showblob 0; +#X obj 187 13 inlet blobinformation; +#X obj 279 316 gemlist; +#X obj 279 296 t b a; +#X obj 291 50 gemhead 70; +#X obj 129 258 list append; +#X obj 124 140 list split 2; +#X obj 124 114 list append; +#X obj 291 73 t b a; +#X obj 158 232 t b a; +#X obj 279 506 translateXYZ; +#X msg 420 349 \$2; +#X obj 279 356 alpha 1; +#X obj 279 466 translateXYZ -0.5 -0.5 0; +#X obj 279 530 scaleXYZ 0.125 0.25 0; +#X msg 459 349 \$3; +#X msg 420 499 \$4; +#X msg 459 499 \$5; +#X obj 463 328 t a a; +#X obj 279 576 circle 0.5; +#X obj 279 426 color 1 0 0 0.2; +#X obj 279 336 separator; +#X msg 499 499 \$1; +#X obj 279 676 text2d; +#X obj 279 616 color 1 1 0 1; +#X obj 158 198 list split 6; +#X msg 124 167 \$2; +#X obj 366 622 loadbang; +#X msg 366 641 12; +#X msg 521 377 \$6; +#X obj 521 399 > 0; +#X obj 521 420 sel 1 0; +#X msg 520 441 1 0 0 0.2; +#X msg 540 461 0 1 0 0.2; +#X obj 279 596 translateXYZ 0.2 0.2 0; +#X obj 279 446 scaleXYZ 10.666 -8 0; +#X text 336 194 here is an example on how to display blobs with Gem +; +#X connect 0 0 6 1; +#X connect 1 0 20 0; +#X connect 2 0 1 0; +#X connect 2 1 17 0; +#X connect 3 0 7 0; +#X connect 4 0 24 0; +#X connect 5 0 25 0; +#X connect 5 1 24 0; +#X connect 6 0 5 0; +#X connect 7 0 6 0; +#X connect 7 1 1 1; +#X connect 8 0 4 0; +#X connect 8 1 2 0; +#X connect 9 0 13 0; +#X connect 10 0 9 1; +#X connect 11 0 19 0; +#X connect 12 0 9 0; +#X connect 13 0 18 0; +#X connect 14 0 9 2; +#X connect 15 0 13 1; +#X connect 16 0 13 2; +#X connect 17 0 14 0; +#X connect 17 0 10 0; +#X connect 17 1 16 0; +#X connect 17 1 15 0; +#X connect 17 1 21 0; +#X connect 17 1 28 0; +#X connect 18 0 33 0; +#X connect 19 0 34 0; +#X connect 20 0 11 0; +#X connect 21 0 22 0; +#X connect 23 0 22 0; +#X connect 24 0 8 0; +#X connect 24 1 4 1; +#X connect 25 0 24 1; +#X connect 26 0 27 0; +#X connect 27 0 22 1; +#X connect 28 0 29 0; +#X connect 29 0 30 0; +#X connect 30 0 31 0; +#X connect 30 1 32 0; +#X connect 31 0 19 1; +#X connect 32 0 19 1; +#X connect 33 0 23 0; +#X connect 34 0 12 0; +#X restore 553 315 pd showblob; +#X obj 454 395 rectangle 5.333 4; +#X obj 454 124 pix_resize 320 240; +#X obj 454 255 pix_opencv_blobtrack; +#X obj 454 173 pix_rgba; +#X obj 471 227 r \$0-properties; +#X text 464 153 input format : rgba or grey; +#N canvas 699 185 544 482 properties 0; +#X msg 290 314 monitorStage \$1; +#X msg 4 21 getModule; +#X msg 4 41 getModule fg; +#X msg 4 61 getModule bd; +#X msg 4 81 getModule bt; +#X msg 4 101 getModule btpp; +#X obj 12 142 loadbang; +#X msg 260 194 setModule bd BD_CC; +#X msg 27 194 setModule fg FG_0S; +#X msg 147 194 setModule fg FG_1; +#X text 289 249 monitoring stage :; +#X obj 290 266 vradio 15 1 0 3 empty empty empty 0 -8 0 10 -262144 +-1 -1 0; +#X text 308 265 input image; +#X text 307 281 foreground mask; +#X text 307 296 diplsay blobs; +#X obj -35 433 s \$0-properties; +#X obj -35 353 t a; +#X msg 287 380 fgTrainFrames \$1; +#X floatatom 287 353 5 0 0 0 - - -; +#X text 72 20 post all accessibles modules and their nickname; +#X text 108 56 post information of specific module and get the avaiblable +variant to load; +#X msg 12 160 setModule fg FG_1 \, setModule bd BD_Simple \, setModule +bt CC \, setModule btpp none \, setModule bta none; +#X connect 0 0 15 0; +#X connect 1 0 16 0; +#X connect 2 0 16 0; +#X connect 3 0 16 0; +#X connect 4 0 16 0; +#X connect 5 0 16 0; +#X connect 6 0 21 0; +#X connect 7 0 16 0; +#X connect 8 0 16 0; +#X connect 9 0 16 0; +#X connect 11 0 0 0; +#X connect 16 0 15 0; +#X connect 17 0 15 0; +#X connect 18 0 17 0; +#X connect 21 0 16 0; +#X restore 610 222 pd properties; +#X obj 454 70 pix_film; +#X text 459 96 the bigger the image is \, the more CPU expensive the +algo will be; +#X text 16 202 Inlet 1 accepts a lot of messages \, here are the most +usefull ones \, see [pd properties] for details.; +#X text 26 232 getModule : get information about loaded modules.; +#X text 26 252 setModule : set algorythm to use in each module.; +#X text 26 272 monitoringStage : set the location where output image +is taken (input \, foreground mask or input with tracking information) +; +#X obj 580 51 openpanel; +#X obj 583 24 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 +-1; +#X msg 580 72 open \$1; +#X connect 12 0 13 0; +#X connect 13 0 12 0; +#X connect 15 0 23 0; +#X connect 16 0 30 0; +#X connect 17 0 30 0; +#X connect 18 0 17 0; +#X connect 21 0 20 0; +#X connect 21 1 22 0; +#X connect 21 2 19 0; +#X connect 24 0 26 0; +#X connect 25 0 15 0; +#X connect 25 1 21 0; +#X connect 26 0 25 0; +#X connect 27 0 25 0; +#X connect 30 0 24 0; +#X connect 36 0 38 0; +#X connect 37 0 36 0; +#X connect 38 0 30 0; diff --git a/pix_opencv_blobtrack.cpp b/pix_opencv_blobtrack.cpp new file mode 100644 index 0000000..d2ed9ed --- /dev/null +++ b/pix_opencv_blobtrack.cpp @@ -0,0 +1,556 @@ +//////////////////////////////////////////////////////// +// +// GEM - Graphics Environment for Multimedia +// +// zmoelnig@iem.kug.ac.at +// +// Implementation file +// +// Copyright (c) 1997-2000 Mark Danks. +// Copyright (c) Günther Geiger. +// Copyright (c) 2001-2002 IOhannes m zmoelnig. forum::für::umläute. IEM +// Copyright (c) 2002 James Tittle & Chris Clepper +// For information on usage and redistribution, and for a DISCLAIMER OF ALL +// WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution. +// +///////////////////////////////////////////////////////// +// based on code written by Lluis Gomez i Bigorda ( lluisgomez _at_ hangar _dot_ org ) (pix_opencv) +// mainly copy and paste from blobtracker_sample.cpp provided by OpenCV 2.3 SVN rev7875 + +#include "pix_opencv_blobtrack.h" +#include +#include + + +CPPEXTERN_NEW(pix_opencv_blobtrack) + +///////////////////////////////////////////////////////// +// +// pix_opencv_blobtrack +// +///////////////////////////////////////////////////////// +// Constructor +// +///////////////////////////////////////////////////////// + +pix_opencv_blobtrack :: pix_opencv_blobtrack() : m_fg_name(FGDetector_Modules[0].nickname), \ + m_bd_name(BlobDetector_Modules[0].nickname), \ + m_bt_name(BlobTracker_Modules[0].nickname), \ + m_btpp_name(BlobTrackPostProc_Modules[0].nickname), \ + m_bta_name(BlobTrackAnalysis_Modules[0].nickname), \ + m_bt_corr("none"), \ + m_FGTrainFrames(6), \ + m_monitoring_stage(0), \ + m_tracker(NULL) +{ + m_param.pBT=NULL; + m_param.pBD=NULL; + m_param.pBTGen=NULL; + m_param.pBTA=NULL; + m_param.pFG=NULL; + m_dataout = outlet_new(this->x_obj, 0); + setupModules(); + createModules(); + printParamsMess(); +} + +///////////////////////////////////////////////////////// +// Destructor +// +///////////////////////////////////////////////////////// +pix_opencv_blobtrack :: ~pix_opencv_blobtrack() +{ + releaseModules(); +} + +///////////////////////////////////////////////////////// +// processImage +// +///////////////////////////////////////////////////////// +void pix_opencv_blobtrack :: processRGBAImage(imageStruct &image) +{ + cv::Mat imgMat( image.ysize, image.xsize, CV_8UC4, image.data, image.csize*image.xsize); // just transform imageStruct to IplImage without copying data + IplImage img = imgMat; // convert cv::Mat to IplImage + RunBlobTrackingAuto( &img ); +} + +void pix_opencv_blobtrack :: processRGBImage(imageStruct &image) { + cv::Mat imgMat( image.ysize, image.xsize, CV_8UC3, image.data, image.csize*image.xsize); // just transform imageStruct to IplImage without copying data + IplImage img = imgMat; + RunBlobTrackingAuto( &img ); +} + +void pix_opencv_blobtrack :: processYUVImage(imageStruct &image) { + + error("YVU format not supported"); +} + +void pix_opencv_blobtrack :: processGrayImage(imageStruct &image) +{ + cv::Mat imgMat( image.ysize, image.xsize, CV_8UC1, image.data, image.csize*image.xsize); // convert imageStruct to cv::Mat without copying data + IplImage img = imgMat; // convert cv::Mat to IplImage + RunBlobTrackingAuto( &img ); +} + +void pix_opencv_blobtrack :: RunBlobTrackingAuto( IplImage* img ) +{ + IplImage* pMask = NULL; + IplImage* imgRGB = NULL; + + if ( x_size != img->width || y_size != img->height ){ + releaseModules(); + createModules(); + x_size = img->width; + y_size = img->height; + } + + imgRGB = cvCreateImage(cvSize(img->width,img->height),img->depth,3); + switch (img->nChannels){ + case 1: + cvCvtColor(img, imgRGB, CV_GRAY2RGB); + break; + case 4: + cvCvtColor(img, imgRGB, CV_RGBA2RGB); + break; + } + + /* Process: */ + m_tracker->Process(imgRGB, pMask); + + //~ t_atom blob_num; + //~ SETFLOAT(&blob_num, m_tracker->GetBlobNum()); + //~ outlet_anything(m_dataout, gensym("blobnum"), 1, &blob_num); + + int blob_atom_size = 2+m_tracker->GetBlobNum()*6; + + t_atom* blob_atom = new t_atom[blob_atom_size]; + SETFLOAT(&blob_atom[0], m_tracker->GetBlobNum()); + SETFLOAT(&blob_atom[1], 6); + + for(int i=0; iGetBlobNum(); i++){ + CvBlob* blob = m_tracker->GetBlob(i); + SETFLOAT(&blob_atom[2+i*6], blob->ID); + SETFLOAT(&blob_atom[3+i*6], blob->x/img->width); + SETFLOAT(&blob_atom[4+i*6], blob->y/img->height); + SETFLOAT(&blob_atom[5+i*6], blob->w/img->width); + SETFLOAT(&blob_atom[6+i*6], blob->h/img->height); + SETFLOAT(&blob_atom[7+i*6], m_tracker->GetState(blob->ID)); + //~ t_atom *ap=blob_atom+2+6*i; + //~ SETFLOAT(ap++, blob->ID); + //~ SETFLOAT(ap++, blob->x/img->width); + //~ SETFLOAT(ap++, blob->y/img->height); + //~ SETFLOAT(ap++, blob->w/img->width); + //~ SETFLOAT(ap++, blob->h/img->height); + //~ SETFLOAT(ap++, m_tracker->GetState(blob->ID)); + } + + outlet_anything(m_dataout, gensym("blob"), blob_atom_size, blob_atom); + + if(blob_atom) delete blob_atom; + blob_atom = NULL; + + if ( m_monitoring_stage == 1 ) { // show foreground + IplImage* fg = m_tracker->GetFGMask(); + switch (img->nChannels){ + case 1: + cvCopy(fg, img); + break; + case 4: + cvCvtColor(fg, img, CV_GRAY2RGBA); + break; + } + } + + if ( m_monitoring_stage == 2 ) { + /* Draw all information about test sequence: */ + char str[1024]; + int line_type = CV_AA; // Change it to 8 to see non-antialiased graphics. + CvFont font; + int i; + + cvInitFont( &font, CV_FONT_HERSHEY_PLAIN, 0.7, 0.7, 0, 1, line_type ); + + for(i=m_tracker->GetBlobNum(); i>0; i--) + { + CvSize TextSize; + CvBlob* pB = m_tracker->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*m_tracker->GetState(CV_BLOB_ID(pB))); + + cvEllipse( imgRGB, + p, + s, + 0, 0, 360, + CV_RGB(c,255-c,0), cvRound(1+(3*0)/255), CV_AA, 8 ); + + p.x >>= 8; + 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( imgRGB, str, p, &font, CV_RGB(0,255,255)); + { + const char* pS = m_tracker->GetStateDesc(CV_BLOB_ID(pB)); + + if(pS) + { + char* pStr = strdup(pS); + char* pStrFree = pStr; + + while (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( imgRGB, pStr, p, &font, CV_RGB(0,255,255)); + pStr = str_next; + } + free(pStrFree); + } + } + + } /* Next blob. */; + switch (img->nChannels){ + case 1: + cvCvtColor(imgRGB, img, CV_RGB2GRAY); + break; + case 4: + cvCvtColor(imgRGB, img, CV_RGB2RGBA); + break; + } + + }/* Draw all information about test sequence. */ + cvReleaseImage(&imgRGB); + imgRGB = NULL; + +} /* RunBlobTrackingAuto */ + +///////////////////////////////////////////////////////// +// static member function +// +///////////////////////////////////////////////////////// +void pix_opencv_blobtrack :: obj_setupCallback(t_class *classPtr) +{ + CPPEXTERN_MSG1(classPtr, "monitorStage", monitorStageMess, int); + CPPEXTERN_MSG1(classPtr, "fgTrainFrames", fgTrainFramesMess, int); + CPPEXTERN_MSG (classPtr, "getParam", getParamMess); + CPPEXTERN_MSG (classPtr, "setParam", setParamMess); + CPPEXTERN_MSG (classPtr, "getModule", getModuleMess); + CPPEXTERN_MSG (classPtr, "setModule", setModuleMess); +} + +///////////////////////////////////////////////////////// +// private function +// +///////////////////////////////////////////////////////// +void pix_opencv_blobtrack :: setupModules() +{ + const char* fg_name = m_fg_name.c_str(); + const char* bd_name = m_bd_name.c_str(); + const char* bt_name = m_bt_name.c_str(); + const char* btpp_name = m_btpp_name.c_str(); + const char* bta_name = m_bta_name.c_str(); + + for(m_FGModule=FGDetector_Modules; m_FGModule->nickname; ++m_FGModule) + if( fg_name && MY_STRICMP(fg_name,m_FGModule->nickname)==0 ) break; + if ( m_FGModule->nickname == NULL ){ + error("FG Module %s doesn't exist, swith to default one", fg_name); + m_FGModule=FGDetector_Modules; + } + + for(m_BDModule=BlobDetector_Modules; m_BDModule->nickname; ++m_BDModule) + if( bd_name && MY_STRICMP(bd_name,m_BDModule->nickname)==0 ) break; + if ( m_BDModule->nickname == NULL ){ + error("BD Module %s doesn't exist, swith to default one", bd_name); + m_BDModule=BlobDetector_Modules; + } + + for(m_BTModule=BlobTracker_Modules; m_BTModule->nickname; ++m_BTModule) + if( bt_name && MY_STRICMP(bt_name,m_BTModule->nickname)==0 ) break; + if ( m_BTModule->nickname == NULL ){ + error("BT Module %s doesn't exist, swith to default one", bt_name); + m_BTModule=BlobTracker_Modules; + } + + for(m_BTPostProcModule=BlobTrackPostProc_Modules; m_BTPostProcModule->nickname; ++m_BTPostProcModule) + if( btpp_name && MY_STRICMP(btpp_name,m_BTPostProcModule->nickname)==0 ) break; + if ( m_BTPostProcModule->nickname == NULL ){ + error("BTPP Module %s doesn't exist, swith to default one", btpp_name); + m_BTPostProcModule=BlobTrackPostProc_Modules; + } + + for(m_BTAnalysisModule=BlobTrackAnalysis_Modules; m_BTAnalysisModule->nickname; ++m_BTAnalysisModule) + if( bta_name && MY_STRICMP(bta_name,m_BTAnalysisModule->nickname)==0 ) break; + if ( m_BTAnalysisModule->nickname == NULL ){ + error("BTA Module %s doesn't exist, swith to default one", bta_name); + m_BTAnalysisModule=BlobTrackAnalysis_Modules; + } +} /* setupModules */ + +void pix_opencv_blobtrack :: createModules() +{ /* Create autotracker module and its components: */ + + m_param.FGTrainFrames = m_FGTrainFrames; + /* Create FG Detection module: */ + m_param.pFG = m_FGModule->create(); + if(!m_param.pFG){ + error("Can not create FGDetector module"); + return; + } + m_param.pFG->SetNickName(m_FGModule->nickname); + //~ set_params(argc, argv, m_param.pFG, "fg", m_FGModule->nickname); + /* Create Blob Entrance Detection module: */ + m_param.pBD = m_BDModule->create(); + if(!m_param.pBD){ + error("Can not create BlobDetector module"); + return; + } + m_param.pBD->SetNickName(m_BDModule->nickname); + //~ set_params(argc, argv, m_param.pBD, "bd", m_BDModule->nickname); + + /* Create blob tracker module: */ + m_param.pBT = m_BTModule->create(); + if(!m_param.pBT){ + error("Can not create BlobTracker module"); + } + m_param.pBT->SetNickName(m_BTModule->nickname); + //~ set_params(argc, argv, m_param.pBT, "bt", m_BTModule->nickname); + + /* Create blob trajectory generation module: */ + /* + m_param.pBTGen = NULL; + if(m_BTGenModule && track_name && m_BTGenModule->create) + { + m_param.pBTGen = m_BTGenModule->create(); + m_param.pBTGen->SetFileName(track_name); + } + if(m_param.pBTGen) + { + m_param.pBTGen->SetNickName(m_BTGenModule->nickname); + //~ set_params(argc, argv, m_param.pBTGen, "btgen", m_BTGenModule->nickname); + } + */ + + /* Create blob trajectory post processing module: */ + m_param.pBTPP = NULL; + if(m_BTPostProcModule && m_BTPostProcModule->create) + { + m_param.pBTPP = m_BTPostProcModule->create(); + } + if(m_param.pBTPP) + { + m_param.pBTPP->SetNickName(m_BTPostProcModule->nickname); + //~ set_params(argc, argv, m_param.pBTPP, "btpp", pBTPostProcModule->nickname); + } + + const char * bt_corr = m_bt_corr.c_str(); + + m_param.UsePPData = (bt_corr && MY_STRICMP(bt_corr,"PostProcRes")==0); + + /* Create blob trajectory analysis module: */ + m_param.pBTA = NULL; + if(m_BTAnalysisModule && m_BTAnalysisModule->create) + { + m_param.pBTA = m_BTAnalysisModule->create(); + //~ m_param.pBTA->SetFileName(bta_data_name); + } + if(m_param.pBTA) + { + m_param.pBTA->SetNickName(m_BTAnalysisModule->nickname); + //~ set_params(argc, argv, m_param.pBTA, "bta", m_BTAnalysisModule->nickname); + } + + /* Create whole pipline: */ + m_tracker = cvCreateBlobTrackerAuto1(&m_param); + if(!m_tracker) + error("Can not create BlobTrackerAuto"); +} /* createModules */ + +void pix_opencv_blobtrack :: releaseModules(void) +{ + if(m_param.pBT)cvReleaseBlobTracker(&m_param.pBT); + if(m_param.pBD)cvReleaseBlobDetector(&m_param.pBD); + if(m_param.pBTGen)cvReleaseBlobTrackGen(&m_param.pBTGen); + if(m_param.pBTA)cvReleaseBlobTrackAnalysis(&m_param.pBTA); + if(m_param.pFG)cvReleaseFGDetector(&m_param.pFG); + if(m_tracker)cvReleaseBlobTrackerAuto(&m_tracker); +} /* releaseModules */ + +void pix_opencv_blobtrack :: print_params(CvVSModule* pM, const char* module) +{ + int i; + if(pM->GetParamName(0) == NULL ) return; + + + post("%s(%s) module parameters:",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) + { + post(" %s: %s",param,str); + } + else + { + post(" %s: %g",param,pM->GetParam(param)); + } + } +} /* print_params */ + +///////////////////////////////////////////////////////// +// messages handling +// +///////////////////////////////////////////////////////// +void pix_opencv_blobtrack :: monitorStageMess(int arg) +{ + m_monitoring_stage = int(arg); + t_atom data_out; + SETFLOAT(&data_out, m_monitoring_stage); + outlet_anything( m_dataout, gensym("monitorStage"), 1, &data_out); +} + +void pix_opencv_blobtrack :: fgTrainFramesMess(int arg) +{ + //~ m_FGTrainFrames = int(arg); + t_atom data_out; + SETFLOAT(&data_out, m_FGTrainFrames); + outlet_anything( m_dataout, gensym("FGTrainFrames"), 1, &data_out); +} + +void pix_opencv_blobtrack :: printParamsMess(void) +{ /* Print module parameters: */ + struct DefMMM + { + CvVSModule* pM; + const char* name; + } Modules[] = { + {(CvVSModule*)m_param.pFG,"FGdetector"}, + {(CvVSModule*)m_param.pBD,"BlobDetector"}, + {(CvVSModule*)m_param.pBT,"BlobTracker"}, + {(CvVSModule*)m_param.pBTGen,"TrackGen"}, + {(CvVSModule*)m_param.pBTPP,"PostProcessing"}, + {(CvVSModule*)m_param.pBTA,"TrackAnalysis"}, + {NULL,NULL} + }; + int i; + for(i=0; Modules[i].name; ++i) + { + if(Modules[i].pM) + print_params(Modules[i].pM,Modules[i].name); + } +} /* Print module parameters. */ + +void pix_opencv_blobtrack :: getParamMess(t_symbol*s, int argc, t_atom*argv) +{ + // TODO +} + +void pix_opencv_blobtrack :: setParamMess(t_symbol*s, int argc, t_atom*argv) +{ + // TODO +} + +void pix_opencv_blobtrack :: getModuleMess(t_symbol*s, int argc, t_atom*argv) +{ + if ( argc == 0 ){ // no args : print all modules in pipeline + post("avaible modules in pipeline :\n \ + fg : ForeGround detector\n \ + bd : Blob Detector\n \ + bt : Blob Tracker\n \ + btpp : Blob Tracker Post Processing\n \ + bta : Blob Tracker Analysis"); + + t_atom module_list[5]; + SETSYMBOL(&module_list[0], gensym("fg")); + SETSYMBOL(&module_list[1], gensym("bd")); + SETSYMBOL(&module_list[2], gensym("bt")); + SETSYMBOL(&module_list[3], gensym("btpp")); + SETSYMBOL(&module_list[4], gensym("bta")); + outlet_anything(m_dataout, gensym("modulelist"), 5, module_list); + + } else if ( argc == 1 ) { // one arg : print available algo for specified module + if ( argv[0].a_type == A_SYMBOL ) { + t_atom algo_list[512]; + int i; + if ( std::string(argv[0].a_w.w_symbol->s_name) == "fg" ){ + post("available foreground detector algo :"); + for (i = 0 ; FGDetector_Modules[i].nickname!=NULL ; i++){ + post("\t%s : %s", FGDetector_Modules[i].nickname, FGDetector_Modules[i].description); + SETSYMBOL(&algo_list[i],gensym(FGDetector_Modules[i].nickname)); + } + outlet_anything(m_dataout, gensym("fg_algo"), i, algo_list); + } else if ( std::string(argv[0].a_w.w_symbol->s_name) == "bd" ){ + post("available blob detector algo :"); + for (i = 0 ; BlobDetector_Modules[i].nickname!=NULL ; i++){ + post("\t%s : %s", BlobDetector_Modules[i].nickname, BlobDetector_Modules[i].description); + SETSYMBOL(&algo_list[i],gensym(BlobDetector_Modules[i].nickname)); + } + outlet_anything(m_dataout, gensym("bd_algo"), i, algo_list); + } else if ( std::string(argv[0].a_w.w_symbol->s_name) == "bt" ){ + post("available blob tracker algo :"); + for (i = 0 ; BlobTracker_Modules[i].nickname!=NULL ; i++){ + post("\t%s : %s", BlobTracker_Modules[i].nickname, BlobTracker_Modules[i].description); + SETSYMBOL(&algo_list[i],gensym(BlobTracker_Modules[i].nickname)); + } + outlet_anything(m_dataout, gensym("bt_algo"), i, algo_list); + } else if ( std::string(argv[0].a_w.w_symbol->s_name) == "btpp" ){ + post("available blob tracker post processing algo :"); + for (i = 0 ; BlobTrackPostProc_Modules[i].nickname!=NULL ; i++){ + post("\t%s : %s", BlobTrackPostProc_Modules[i].nickname, BlobTrackPostProc_Modules[i].description); + SETSYMBOL(&algo_list[i],gensym(BlobTrackPostProc_Modules[i].nickname)); + } + outlet_anything(m_dataout, gensym("btpp_algo"), i, algo_list); + } else if ( std::string(argv[0].a_w.w_symbol->s_name) == "bta" ){ + post("available blob tracker analysis algo :"); + for (i = 0 ; BlobTrackAnalysis_Modules[i].nickname!=NULL ; i++){ + post("\t%s : %s", BlobTrackAnalysis_Modules[i].nickname, BlobTrackAnalysis_Modules[i].description); + SETSYMBOL(&algo_list[i],gensym(BlobTrackAnalysis_Modules[i].nickname)); + } + outlet_anything(m_dataout, gensym("bd_algo"), i, algo_list); + } + } else error("getModules []"); + } else error("getModules [] : need 1 or 2 args"); +} + +void pix_opencv_blobtrack :: setModuleMess(t_symbol*s, int argc, t_atom*argv) +{ + if ( argc != 2 ){ + error("use : setModule "); + error("try getModule to get available module list"); + return; + } + + if ( argv[0].a_type == A_SYMBOL ) { + if (std::string(argv[0].a_w.w_symbol->s_name) == "fg") { + m_fg_name = argv[1].a_w.w_symbol->s_name; + } + else if (std::string(argv[0].a_w.w_symbol->s_name) == "bd") { + m_bd_name = argv[1].a_w.w_symbol->s_name; + } + else if (std::string(argv[0].a_w.w_symbol->s_name) == "bt") { + m_bt_name = argv[1].a_w.w_symbol->s_name; + } + else if (std::string(argv[0].a_w.w_symbol->s_name) == "btpp") { + m_btpp_name = argv[1].a_w.w_symbol->s_name; + } + else if (std::string(argv[0].a_w.w_symbol->s_name) == "bta") { + m_bta_name = argv[1].a_w.w_symbol->s_name; + } + releaseModules(); + setupModules(); + createModules(); + printParamsMess(); + } +} diff --git a/pix_opencv_blobtrack.h b/pix_opencv_blobtrack.h new file mode 100644 index 0000000..66c9d4f --- /dev/null +++ b/pix_opencv_blobtrack.h @@ -0,0 +1,104 @@ +/*----------------------------------------------------------------- +LOG + GEM - Graphics Environment for Multimedia + + Threshold filter + + Copyright (c) 1997-1999 Mark Danks. mark@danks.org + Copyright (c) Günther Geiger. geiger@epy.co.at + Copyright (c) 2001-2002 IOhannes m zmoelnig. forum::für::umläute. IEM. zmoelnig@iem.kug.ac.at + Copyright (c) 2002 James Tittle & Chris Clepper + For information on usage and redistribution, and for a DISCLAIMER OF ALL + WARRANTIES, see the file, "GEM.LICENSE.TERMS" in this distribution. + +-----------------------------------------------------------------*/ + +#ifndef INCLUDE_PIX_OPENCV_BLOBTRACK_H_ +#define INCLUDE_PIX_OPENCV_BLOBTRACK_H_ + +#ifndef _EiC +#include "opencv2/video/background_segm.hpp" +#include "opencv2/legacy/blobtrack.hpp" +#include "opencv2/highgui/highgui.hpp" +#include +#endif + +#include "blobtrack.h" + +#include "Base/GemPixObj.h" + +/*----------------------------------------------------------------- +------------------------------------------------------------------- +CLASS + pix_opencv_blobtrack + + square pattern detector + +KEYWORDS + pix + +DESCRIPTION + +-----------------------------------------------------------------*/ +class GEM_EXTERN pix_opencv_blobtrack : public GemPixObj +{ + CPPEXTERN_HEADER(pix_opencv_blobtrack, GemPixObj) + + public: + + ////////// + // Constructor + pix_opencv_blobtrack(); + + protected: + + ////////// + // Destructor + virtual ~pix_opencv_blobtrack(); + + ////////// + // Do the processing + virtual void processRGBAImage(imageStruct &image); + virtual void processRGBImage(imageStruct &image); + virtual void processYUVImage(imageStruct &image); + virtual void processGrayImage(imageStruct &image); + void RunBlobTrackingAuto( IplImage* img ); + + ////////// + // Messages handling + void monitorStageMess(int arg); + void fgTrainFramesMess(int arg); + void printParamsMess(void); + void getParamMess(t_symbol*s, int argc, t_atom*argv); // get available params or param value + void setParamMess(t_symbol*s, int argc, t_atom*argv); // set param + void getModuleMess(t_symbol*s, int argc, t_atom*argv); // list available and currently used modules + void setModuleMess(t_symbol*s, int argc, t_atom*argv); // set selected modules + + // Members + std::string m_fg_name, m_bd_name, m_bt_name, m_btgen_name, m_btpp_name, m_bta_name, m_bt_corr; + int m_FGTrainFrames; + int m_monitoring_stage; // 0 : input image, 1 : FG 3 : input with trackng info + int x_size, y_size; + + + CvBlobTrackerAuto* m_tracker; + CvBlobTrackerAutoParam1 m_param; + + DefModule_FGDetector* m_FGModule; + DefModule_BlobDetector* m_BDModule; + DefModule_BlobTracker* m_BTModule; + DefModule_BlobTrackPostProc* m_BTPostProcModule; + DefModule_BlobTrackGen* m_BTGenModule; + DefModule_BlobTrackAnalysis* m_BTAnalysisModule; + + + private: + + void setupModules(); + void createModules(); + void releaseModules(void); + void print_params(CvVSModule* pM, const char* module); + t_outlet *m_dataout; // info outlet + +}; +#endif // for header file -- cgit v1.2.1