zoukankan      html  css  js  c++  java
  • opencv中的vs框架中的Blob Tracking Tests的中文注释。

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

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

    代码注释为本人原创,转载请注明原为地址: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<opencvcvaux.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,'
    ');
                                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
    ",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:
    ",module,pM->GetNickName());
        if(log)
            fprintf(log,"%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)
            {
                printf("  %s: %s
    ",param,str);
                if(log)
                    fprintf(log,"  %s: %s
    ",param,str);
            }
            else
            {
                printf("  %s: %g
    ",param,pM->GetParam(param));
                if(log)
                    fprintf(log,"  %s: %g
    ",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>]
    "
                "          [bt=<bt_name>] [btpp=<btpp_name>]
    "
                "          [bta=<bta_name>
    "
                "          [bta_data=<bta_data_name>
    "
                "          [bt_corr=<bt_corr_way>]
    "
                "          [btgen=<btgen_name>]
    "
                "          [track=<track_file_name>]
    "
                "          [scale=<scale val>] [noise=<noise_name>] [IVar=<IVar_name>]
    "
                "          [FGTrainFrames=<FGTrainFrames>]
    "
                "          [btavi=<avi output>] [fgavi=<avi output on FG>]
    "
                "          <avi_file>
    ");
            printf("  <bt_corr_way> is way of blob position corrrection for "Blob Tracking" module
    "
                "     <bt_corr_way>=none,PostProcRes
    "
                "  <FGTrainFrames> is number of frames for FG training
    "
                "  <track_file_name> is file name for save tracked trajectories
    "
                "  <bta_data> is file name for data base of trajectory analysis module
    "
                "  <avi_file> is file name of avi to process by BlobTrackerAuto
    ");
    
            puts("
    Modules:");
    #define PR(_name,_m,_mt)
            printf("<%s> is "%s" module name and can be:
    ",_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("
    ");
            }
    
            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
    ",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,"
    === Blob Tracking pipline in processing mode===
    ");
                if(avi_name)
                {
                    fprintf(log,"AVIFile: %s
    ",avi_name);
                }
                fprintf(log,"FGDetector:   %s
    ", pFGModule->nickname);
                fprintf(log,"BlobDetector: %s
    ", pBDModule->nickname);
                fprintf(log,"BlobTracker:  %s
    ", pBTModule->nickname);
                fprintf(log,"BlobTrackPostProc:  %s
    ", pBTPostProcModule->nickname);
                fprintf(log,"BlobCorrection:  %s
    ", bt_corr);
                fprintf(log,"Blob Trajectory Generator:  %s (%s)
    ",
                    pBTGenModule?pBTGenModule->nickname:"None",
                    track_name?track_name:"none");
                fprintf(log,"BlobTrackAnalysis:  %s
    ", pBTAnalysisModule->nickname);
                fclose(log);
            }
    
            printf("
    === Blob Tracking pipline in %s mode===
    ","processing");
            if(yml_name)//如果定义了yml_name 那么就读取配置文件。
            {
                printf("ConfigFile: %s
    ",yml_name);
                printf("BG: %s
    ",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("
    ");
            }
            if(avi_name)//这个判断是多余的,前面已经判断了很多遍了。
            {
                printf("AVIFile: %s
    ",avi_name);
            }
            printf("FGDetector:   %s
    ", pFGModule->nickname);//输出各个模块的邋nick_name
            printf("BlobDetector: %s
    ", pBDModule->nickname);
            printf("BlobTracker:  %s
    ", pBTModule->nickname);
            printf("BlobTrackPostProc:  %s
    ", pBTPostProcModule->nickname);
            printf("BlobCorrection:  %s
    ", bt_corr);
            printf("Blob Trajectory Generator:  %s (%s)
    ",
                pBTGenModule?pBTGenModule->nickname:"None",
                track_name?track_name:"none");
            printf("BlobTrackAnalysis:  %s
    ", 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...
    ");
                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
    ");
            }
        }/* 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 */
    
    
    


  • 相关阅读:
    lombok @Builder注解使用的例子、反编译之后的代码详解
    InfluxDB时序数据库应用场景
    阿里巴巴为什么不用 ZooKeeper 做服务发现?
    使用RestTemplate调用接口上传文件
    当try-catch-finally代码块遇上return,代码执行流程是怎样
    Spring Boot 中application.yml与bootstrap.yml的区别
    Java文件上传:Restful接口接收上传文件,缓存在本地
    线程执行synchronized同步代码块时再次重入该锁过程中抛异常,是否会释放锁
    AMQP协议详解与RabbitMQ,MQ消息队列的应用场景,如何避免消息丢失等消息队列常见问题
    数据库:内联接,外联接,空值和联接
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3221705.html
Copyright © 2011-2022 走看看