opencv中的vs框架中的Blob Tracking Tests的中文註釋。

通過2天的努力終於算是大概弄清楚了opencv中的vs框架是大概是如何工做的了,下面貼一下我本身寫的代碼註釋。很是詳細。對初學者有幫助。尤爲詳細分析了RunBlobTrackingAuto()函數,在看註釋以前應該首先大概瞭解一下算法

Blob Tracking Tests和Blob Tracking Modules的說明文檔。這樣比較容易理解。說明文檔的位置在  opencv的安裝位置的opencv\doc\vidsurv

代碼註釋爲本人原創,轉載請註明原爲地址:http://blog.csdn.net/jia_zhengshen/article/details/9499103
程序的大致流程是:首先main函數讀取一大堆參數,而後與預約的命令比較,比較完後給相應的參數賦值。而後給param這位二神賦值,而後經過param這個參數把pTRacker初始化,而後程序進入RunBlobTrackingAuto函數這個主循環,循環完後退出程序。流程圖以下:

 

 

//#include "cvaux.h"
//#include "highgui.h"
#include<opencv/cv.h>//因爲使用了source insight來寫註釋,因此偶爾會有亂碼。
#include<opencv/highgui.h>
#include<opencv\cvaux.h>
#include <stdio.h>

/* select the correct function for doing case insensitive string comparaison */
#ifdef WIN32
  #define MY_STRNICMP strnicmp
  #define MY_STRICMP stricmp
#else
  #define MY_STRNICMP strncasecmp
  #define MY_STRICMP strcasecmp
#endif

/* list of FG DETECTION modules */
static CvFGDetector* cvCreateFGDetector0(){return cvCreateFGDetectorBase(CV_BG_MODEL_FGD, NULL);}
static CvFGDetector* cvCreateFGDetector0Simple(){return cvCreateFGDetectorBase(CV_BG_MODEL_FGD_SIMPLE, NULL);}
static CvFGDetector* cvCreateFGDetector1(){return cvCreateFGDetectorBase(CV_BG_MODEL_MOG, NULL);}
typedef struct DefModule_FGDetector
{
    CvFGDetector* (*create)();//指向函數的指針。使用這種寫法,可使c語言具備面向對象的特性。
    char* nickname;//這個FGDETECTOR的別名。Nickname至關於小名。
    char* description;//這個邋fgDetector的簡單描述。
} DefModule_FGDetector;
DefModule_FGDetector FGDetector_Modules[] =//這是個數組。
{
    {cvCreateFGDetector0,"FG_0","Foreground Object Detection from Videos Containing Complex Background. ACM MM2003."},
    {cvCreateFGDetector0Simple,"FG_0S","Simplyfied version of FG_0"},
    {cvCreateFGDetector1,"FG_1","Adaptive background mixture models for real-time tracking. CVPR1999"},
    {NULL,NULL,NULL}//所有爲空,這裏有的null有很大的做用,來指示這是這個數組的最後一個,增長其餘的算法。在main函數使用這個數組時會使用到這一點。
};

/* list of BLOB DETECTION modules */
typedef struct DefModule_BlobDetector
{
    CvBlobDetector* (*create)();//這個BlobDetector的做用是檢驗新的blob
    char* nickname;
    char* description;
} DefModule_BlobDetector;
DefModule_BlobDetector BlobDetector_Modules[] =//這裏定義了3個blobDetector 來檢驗新的blob
{
    {cvCreateBlobDetectorCC,"BD_CC","Detect new blob by tracking CC of FG mask"},
    {cvCreateBlobDetectorSimple,"BD_Simple","Detect new blob by uniform moving of connected components of FG mask"},
    {NULL,NULL,NULL}
};

/* list of BLOB TRACKING modules */
typedef struct DefModule_BlobTracker
{
    CvBlobTracker* (*create)();//做用是找到blob的位置,大小,id
    char* nickname;
    char* description;
} DefModule_BlobTracker;
DefModule_BlobTracker BlobTracker_Modules[] =//定義了5個錌lobtracker
{
    {cvCreateBlobTrackerCCMSPF,"CCMSPF","connected component tracking and MSPF resolver for collision"},
    {cvCreateBlobTrackerCC,"CC","Simple connected component tracking"},
    {cvCreateBlobTrackerMS,"MS","Mean shift algorithm "},
    {cvCreateBlobTrackerMSFG,"MSFG","Mean shift algorithm with FG mask using"},
    {cvCreateBlobTrackerMSPF,"MSPF","Particle filtering based on MS weight"},
    {NULL,NULL,NULL}
};

/* list of BLOB TRAJECTORY GENERATION modules */
typedef struct DefModule_BlobTrackGen
{
    CvBlobTrackGen* (*create)();//軌跡產生器(Trajectory Generator)主要做用是用於把軌跡存到一個文件中。
    char* nickname;
    char* description;
} DefModule_BlobTrackGen;
DefModule_BlobTrackGen BlobTrackGen_Modules[] =//定義了2個軌跡生成器。
{
    {cvCreateModuleBlobTrackGenYML,"YML","Generate track record in YML format as synthetic video data"},
    {cvCreateModuleBlobTrackGen1,"RawTracks","Generate raw track record (x,y,sx,sy),()... in each line"},
    {NULL,NULL,NULL}
};

/* list of BLOB TRAJECTORY POST PROCESSING modules */
typedef struct DefModule_BlobTrackPostProc//軌跡的後續處理程序。
{
    CvBlobTrackPostProc* (*create)();
    char* nickname;
    char* description;
} DefModule_BlobTrackPostProc;
DefModule_BlobTrackPostProc BlobTrackPostProc_Modules[] =
{
    {cvCreateModuleBlobTrackPostProcKalman,"Kalman","Kalman filtering of blob position and size"},
    {NULL,"None","No post processing filter"},
//    {cvCreateModuleBlobTrackPostProcTimeAverRect,"TimeAverRect","Average by time using rectangle window"},
//    {cvCreateModuleBlobTrackPostProcTimeAverExp,"TimeAverExp","Average by time using exponential window"},
    {NULL,NULL,NULL}
};

/* list of BLOB TRAJECTORY ANALYSIS modules */
CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisDetector();

typedef struct DefModule_BlobTrackAnalysis
{
    CvBlobTrackAnalysis* (*create)();
    char* nickname;
    char* description;
} DefModule_BlobTrackAnalysis;
DefModule_BlobTrackAnalysis BlobTrackAnalysis_Modules[] =
{
    {cvCreateModuleBlobTrackAnalysisHistPVS,"HistPVS","Histogramm of 5D feture vector analysis (x,y,vx,vy,state)"},
    {NULL,"None","No trajectory analiser"},
    {cvCreateModuleBlobTrackAnalysisHistP,"HistP","Histogramm of 2D feture vector analysis (x,y)"},
    {cvCreateModuleBlobTrackAnalysisHistPV,"HistPV","Histogramm of 4D feture vector analysis (x,y,vx,vy)"},
    {cvCreateModuleBlobTrackAnalysisHistSS,"HistSS","Histogramm of 4D feture vector analysis (startpos,endpos)"},
    {cvCreateModuleBlobTrackAnalysisTrackDist,"TrackDist","Compare tracks directly"},
    {cvCreateModuleBlobTrackAnalysisIOR,"IOR","Integrator (by OR operation) of several analysers "},
    {NULL,NULL,NULL}
};
/* list of Blob Trajectory ANALYSIS modules */
/*================= END MODULES DECRIPTION ===================================*/

/* run pipeline on all frames */
static int RunBlobTrackingAuto( CvCapture* pCap, CvBlobTrackerAuto* pTracker,char* fgavi_name = NULL, char* btavi_name = NULL )
{
    int                     OneFrameProcess = 0;
    int                     key;
    int                     FrameNum = 0;
    CvVideoWriter*          pFGAvi = NULL;
    CvVideoWriter*          pBTAvi = NULL;

    //cvNamedWindow( "FG", 0 );

    /* main cicle */
    for( FrameNum=0; pCap && (key=cvWaitKey(OneFrameProcess?0:2))!=27;//按下esc鍵整個程序結束。
         FrameNum++)
    {/* main cicle */// 整個程序的主循環。這個循環終止,意味着這個程序結束。
        IplImage*   pImg = NULL;
        IplImage*   pMask = NULL;

        if(key!=-1)//這個我還不知道是什麼意思。
        {
            OneFrameProcess = 1;
            if(key=='r')OneFrameProcess = 0;
        }

        pImg = cvQueryFrame(pCap);///從視頻流中獲得一幀圖像pImg是這幀圖像的指針。
        if(pImg == NULL) break;


        /* Process */
        pTracker->Process(pImg, pMask);//處理圖像。這個函數應該執行完了全部的處理過程。

        if(fgavi_name)//若是fgavi_name不爲空。則執行下面的程序,若是傳給 RunBlobTrackingAuto是空,則不執行。
        if(pTracker->GetFGMask())//前景的圖像的mask存在的話,執行下面的程序。
        {/* debug FG */
            IplImage*           pFG = pTracker->GetFGMask();//獲得前景的圖像的mask,
			cvShowImage("賈增申",pFG);//這裏顯示一下,我本身寫的。
            CvSize              S = cvSize(pFG->width,pFG->height);
            static IplImage*    pI = NULL;

            if(pI==NULL)pI = cvCreateImage(S,pFG->depth,3);//建立一下,防止內存不存在。
            cvCvtColor( pFG, pI, CV_GRAY2BGR );//因爲建立的mask是一個gray圖,因此爲了下面顯示方便,轉換成bgr格式的。、、實際工程中應該能夠不用這個功能。,但調試的時候頗有用。

            if(fgavi_name)//傳過來的avi名字不爲空,意思就是說,你想存一下。
            {/* save fg to avi file */
                if(pFGAvi==NULL)//第一次使用這個pFgAvi這個變量應該建立一下。
                {
                    pFGAvi=cvCreateVideoWriter(
                        fgavi_name,
                        CV_FOURCC('x','v','i','d'),
                        25,
                        S );
                }
                cvWriteFrame( pFGAvi, pI );//寫入video
            }

            if(pTracker->GetBlobNum()>0)//pTracker找到了blob
            {/* draw detected blobs */
                int i;
                for(i=pTracker->GetBlobNum();i>0;i--)//找到 了GetBlobNum() 個。
                {
                    CvBlob* pB = pTracker->GetBlob(i-1);//獲得第i-1個blob
                    CvPoint p = cvPointFrom32f(CV_BLOB_CENTER(pB));//經過看源代碼,太牛逼了,這個宏居然是個強制轉換得來的。見下行。
                    //////////////////////////////////////////////////#define CV_BLOB_CENTER(pB) cvPoint2D32f(((CvBlob*)(pB))->x,((CvBlob*)(pB))->y)
                    CvSize  s = cvSize(MAX(1,cvRound(CV_BLOB_RX(pB))), MAX(1,cvRound(CV_BLOB_RY(pB))));
                    int c = cvRound(255*pTracker->GetState(CV_BLOB_ID(pB)));
                    cvEllipse( pI,//在那個座標附近話個橢圓唄 。
                        p,
                        s,
                        0, 0, 360,
                        CV_RGB(c,255-c,0), cvRound(1+(3*c)/255) );
                }/* next blob */;
            }

            cvNamedWindow( "FG",0);///顯示出來。
            cvShowImage( "FG",pI);
        }/* debug FG*/


        /* draw debug info */
        if(pImg)//原始的每幀圖像。
        {/* draw all inforamtion about tets sequence */
            char        str[1024];
            int         line_type = CV_AA; // change it to 8 to see non-antialiased graphics
            CvFont      font;
            int         i;
            IplImage*   pI = cvCloneImage(pImg);

            cvInitFont( &font, CV_FONT_HERSHEY_PLAIN, 0.7, 0.7, 0, 1, line_type );

            for(i=pTracker->GetBlobNum();i>0;i--)//獲得了GetBlobNum個blob
            {//下面的代碼能夠參看上十幾行的註釋,這些代碼幾乎同樣。
                CvSize  TextSize;
                CvBlob* pB = pTracker->GetBlob(i-1);
                CvPoint p = cvPoint(cvRound(pB->x*256),cvRound(pB->y*256));
                CvSize  s = cvSize(MAX(1,cvRound(CV_BLOB_RX(pB)*256)), MAX(1,cvRound(CV_BLOB_RY(pB)*256)));
                int c = cvRound(255*pTracker->GetState(CV_BLOB_ID(pB)));

                cvEllipse( pI,
                    p,
                    s,
                    0, 0, 360,
                    CV_RGB(c,255-c,0), cvRound(1+(3*0)/255), CV_AA, 8 );
                p.x >>= 8;//下面代碼的大概意思就是在找到的blob附近寫下id。再也不註釋。
                p.y >>= 8;
                s.width >>= 8;
                s.height >>= 8;
                sprintf(str,"%03d",CV_BLOB_ID(pB));
                cvGetTextSize( str, &font, &TextSize, NULL );
                p.y -= s.height;
                cvPutText( pI, str, p, &font, CV_RGB(0,255,255));
                {
                    const char* pS = pTracker->GetStateDesc(CV_BLOB_ID(pB));
                    if(pS)
                    {
                        char* pStr = strdup(pS);
                        char* pStrFree = pStr;
                        for(;pStr && strlen(pStr)>0;)
                        {
                            char* str_next = strchr(pStr,'\n');
                            if(str_next)
                            {
                                str_next[0] = 0;
                                str_next++;
                            }
                            p.y += TextSize.height+1;
                            cvPutText( pI, pStr, p, &font, CV_RGB(0,255,255));
                            pStr = str_next;
                        }
                        free(pStrFree);
                    }
                }

            }/* next blob */;
            
            cvNamedWindow( "Tracking", 0);//顯示出畫出橢圓的幀
            cvShowImage( "Tracking",pI );

            if(btavi_name && pI)//若是這一幀存在且,你想把圖像存起來,就是傳過來的參數不爲空例如  btavi_name=「我日.avi"   就能存起來了。
            {/* save to avi file */
                CvSize      S = cvSize(pI->width,pI->height);//下面的代碼相似於fg的圖像的存儲代碼,請參看上面的代碼註釋。
                if(pBTAvi==NULL)
                {
                    pBTAvi=cvCreateVideoWriter(
                        btavi_name,
                        CV_FOURCC('x','v','i','d'),
                        25,
                        S );
                }
                cvWriteFrame( pBTAvi, pI );
            }

            cvReleaseImage(&pI);//釋放掉這一幀
        }/* draw all inforamtion about tets sequence */
    }/* main cicle */

    if(pFGAvi)cvReleaseVideoWriter( &pFGAvi );//把fg的圖像存到硬盤上。
    if(pBTAvi)cvReleaseVideoWriter( &pBTAvi );//把每幀圖像存到硬盤上,同時釋放資源。
    return 0;//執行到這裏的時候實際上已經退出了。我想若是不考慮內存泄露的話,能夠改成exit(0) ,可是不建議,由於有內存泄露存在。仍是返回到main函數比較好。
}/* RunBlobTrackingAuto */

/* read parameters from command line and transfer to specified module */
static void set_params(int argc, char* argv[], CvVSModule* pM, char* prefix, char* module)
{
    int prefix_len = strlen(prefix);
    int i;
    for(i=0;i<argc;++i)
    {
        int j;
        char* ptr_eq = NULL;
        int   cmd_param_len=0;
        char* cmd = argv[i];
        if(MY_STRNICMP(prefix,cmd,prefix_len)!=0) continue;
        cmd += prefix_len;
        if(cmd[0]!=':')continue;
        cmd++;

        ptr_eq = strchr(cmd,'=');
        if(ptr_eq)cmd_param_len = ptr_eq-cmd;
        for(j=0;;++j)
        {
            int     param_len;
            const char*   param = pM->GetParamName(j);
            if(param==NULL) break;
            param_len = strlen(param);
            if(cmd_param_len!=param_len) continue;
            if(MY_STRNICMP(param,cmd,param_len)!=0) continue;
            cmd+=param_len;
            if(cmd[0]!='=')continue;
            cmd++;
            pM->SetParamStr(param,cmd);
            printf("%s:%s param set to %g\n",module,param,pM->GetParam(param));
        }
    }
    pM->ParamUpdate();
}/* set_params */

/* print all parameters value for given module */
static void print_params(CvVSModule* pM, char* module, char* log_name)
{
    FILE* log = log_name?fopen(log_name,"at"):NULL;
    int i;
    if(pM->GetParamName(0) == NULL ) return;


    printf("%s(%s) module parameters:\n",module,pM->GetNickName());
    if(log)
        fprintf(log,"%s(%s) module parameters:\n",module,pM->GetNickName());
    for(i=0;;++i)
    {
        const char*   param = pM->GetParamName(i);
        const char*   str = param?pM->GetParamStr(param):NULL;
        if(param == NULL)break;
        if(str)
        {
            printf("  %s: %s\n",param,str);
            if(log)
                fprintf(log,"  %s: %s\n",param,str);
        }
        else
        {
            printf("  %s: %g\n",param,pM->GetParam(param));
            if(log)
                fprintf(log,"  %s: %g\n",param,pM->GetParam(param));
        }
    }
    if(log)fclose(log);
}/* print_params */
//本人認爲,雖然這種命令行的形式可使一個程序能夠驗證多種算法,可是命令行無能否認,太難用了。
int main(int argc, char* argv[])
{/* main function */
    CvCapture*                  pCap = NULL;
    CvBlobTrackerAutoParam1     param = {0};
    CvBlobTrackerAuto*          pTracker = NULL;

    float       scale = 1;
    char*       scale_name = NULL;
    char*       yml_name = NULL;
    char**      yml_video_names = NULL;
    int         yml_video_num = 0;
    char*       avi_name = NULL;
    char*       fg_name = NULL;
    char*       fgavi_name = NULL;
    char*       btavi_name = NULL;
    char*       bd_name = NULL;
    char*       bt_name = NULL;
    char*       btgen_name = NULL;
    char*       btpp_name = NULL;
    char*       bta_name = NULL;
    char*       bta_data_name = NULL;
    char*       track_name = NULL;
    char*       comment_name = NULL;
    char*       FGTrainFrames = NULL;
    char*       log_name = NULL;
    char*       savestate_name = NULL;
    char*       loadstate_name = NULL;
    char*       bt_corr = NULL;
    DefModule_FGDetector*           pFGModule = NULL;
    DefModule_BlobDetector*         pBDModule = NULL;
    DefModule_BlobTracker*          pBTModule = NULL;
    DefModule_BlobTrackPostProc*    pBTPostProcModule = NULL;
    DefModule_BlobTrackGen*         pBTGenModule = NULL;
    DefModule_BlobTrackAnalysis*    pBTAnalysisModule = NULL;

    cvInitSystem(argc, argv);

    if(argc < 2)//若是你的參數連2個都沒有就打印出幫助來。
    {/* print help */
        int i;
        printf("blobtrack [fg=<fg_name>] [bd=<bd_name>]\n"
            "          [bt=<bt_name>] [btpp=<btpp_name>]\n"
            "          [bta=<bta_name>\n"
            "          [bta_data=<bta_data_name>\n"
            "          [bt_corr=<bt_corr_way>]\n"
            "          [btgen=<btgen_name>]\n"
            "          [track=<track_file_name>]\n"
            "          [scale=<scale val>] [noise=<noise_name>] [IVar=<IVar_name>]\n"
            "          [FGTrainFrames=<FGTrainFrames>]\n"
            "          [btavi=<avi output>] [fgavi=<avi output on FG>]\n"
            "          <avi_file>\n");
        printf("  <bt_corr_way> is way of blob position corrrection for \"Blob Tracking\" module\n"
            "     <bt_corr_way>=none,PostProcRes\n"
            "  <FGTrainFrames> is number of frames for FG training\n"
            "  <track_file_name> is file name for save tracked trajectories\n"
            "  <bta_data> is file name for data base of trajectory analysis module\n"
            "  <avi_file> is file name of avi to process by BlobTrackerAuto\n");

        puts("\nModules:");
#define PR(_name,_m,_mt)\
        printf("<%s> is \"%s\" module name and can be:\n",_name,_mt);\
        for(i=0;_m[i].nickname;++i)\
        {\
            printf("  %d. %s",i+1,_m[i].nickname);\
            if(_m[i].description)printf(" - %s",_m[i].description);\
            printf("\n");\
        }

        PR("fg_name",FGDetector_Modules,"FG/BG Detection");
        PR("bd_name",BlobDetector_Modules,"Blob Entrance Detection");
        PR("bt_name",BlobTracker_Modules,"Blob Tracking");
        PR("btpp_name",BlobTrackPostProc_Modules, "Blob Trajectory Post Processing");
        PR("btgen_name",BlobTrackGen_Modules, "Blob Trajectory Generation");
        PR("bta_name",BlobTrackAnalysis_Modules, "Blob Trajectory Analysis");
#undef PR
		getchar();
        return 0;
    }/* print help */

    {/* parse arguments */
        int i;
        for(i=1;i<argc;++i)//下面的是參數初始化。
        {
            int bParsed = 0;
            size_t len = strlen(argv[i]);
#define RO(_n1,_n2) if(strncmp(argv[i],_n1,strlen(_n1))==0) {_n2 = argv[i]+strlen(_n1);bParsed=1;};
            RO("fg=",fg_name);//着重分析這個宏,若是argv【i】等於"fg="這個字符串。
            					//咱們就認爲是給邋fg_name這個變量賦值。如下宏相同。
            RO("fgavi=",fgavi_name);
            RO("btavi=",btavi_name);
            RO("bd=",bd_name);
            RO("bt=",bt_name);
            RO("bt_corr=",bt_corr);
            RO("btpp=",btpp_name);
            RO("bta=",bta_name);
            RO("bta_data=",bta_data_name);
            RO("btgen=",btgen_name);
            RO("track=",track_name);
            RO("comment=",comment_name);
            RO("FGTrainFrames=",FGTrainFrames);
            RO("log=",log_name);
            RO("savestate=",savestate_name);
            RO("loadstate=",loadstate_name);
#undef RO
            {
                char* ext = argv[i] + len-4;
                if( strrchr(argv[i],'=') == NULL &&
                    !bParsed &&
                    (len>3 && (MY_STRICMP(ext,".avi") == 0 )))
                {
                    avi_name = argv[i];//知足上面的if條件就給avi_name賦值,就是要打開的視頻文件名稱。
                    break;
                }
            }/* next argument */
        }
    }/* parse arguments */

    if(track_name)//若是定義了軌跡存儲的文件,就執行下面的程序。
    {/* set Trajectory Generator module */
        int i;
        if(!btgen_name)btgen_name=BlobTrackGen_Modules[0].nickname;
        for(i=0;BlobTrackGen_Modules[i].nickname;++i)//從最初這個數組的定義能夠看到,最後的一個元素是null,能夠根據這個條件來判斷是否結束。
        {
            if(MY_STRICMP(BlobTrackGen_Modules[i].nickname,btgen_name)==0)
                pBTGenModule = BlobTrackGen_Modules + i;
        }
    }/* set Trajectory Generator modulke */

    /* init postprocessing module if tracker correction by postporcessing is reqierd *///後續處理,這個我沒有使用,沒有深究它
    if(bt_corr && MY_STRICMP(bt_corr,"PostProcRes")!=0 && !btpp_name)
    {
        btpp_name = bt_corr;
        if(MY_STRICMP(btpp_name,"none")!=0)bt_corr = "PostProcRes";
    }

    {/* set default parameters for one processing */
        if(!bt_corr) bt_corr = "none";
        if(!fg_name) fg_name = FGDetector_Modules[0].nickname;//若是從main傳過來的參數的邋fg_name爲空,則將這個數組的第0個附給邋fg_name。
        if(!bd_name) bd_name = BlobDetector_Modules[0].nickname;//同上。
        if(!bt_name) bt_name = BlobTracker_Modules[0].nickname;
        if(!btpp_name) btpp_name = BlobTrackPostProc_Modules[0].nickname;
        if(!bta_name) bta_name = BlobTrackAnalysis_Modules[0].nickname;
        if(!scale_name) scale_name = "1";
    }

    if(scale_name) //scale這個參數在這個程序中沒有使用。
        scale = (float)atof(scale_name);
    for(pFGModule=FGDetector_Modules;pFGModule->nickname;++pFGModule)//給邋邋邋pFGModule賦值。注意到文件最開頭的幾個數組的最後都是null結尾的。
        if( fg_name && MY_STRICMP(fg_name,pFGModule->nickname)==0 ) break;//null是結束的標誌。
    for(pBDModule=BlobDetector_Modules;pBDModule->nickname;++pBDModule)
        if( bd_name && MY_STRICMP(bd_name,pBDModule->nickname)==0 ) break;
    for(pBTModule=BlobTracker_Modules;pBTModule->nickname;++pBTModule)
        if( bt_name && MY_STRICMP(bt_name,pBTModule->nickname)==0 ) break;
    for(pBTPostProcModule=BlobTrackPostProc_Modules;pBTPostProcModule->nickname;++pBTPostProcModule)
        if( btpp_name && MY_STRICMP(btpp_name,pBTPostProcModule->nickname)==0 ) break;
    for(pBTAnalysisModule=BlobTrackAnalysis_Modules;pBTAnalysisModule->nickname;++pBTAnalysisModule)
        if( bta_name && MY_STRICMP(bta_name,pBTAnalysisModule->nickname)==0 ) break;

    /* create source video */
    if(avi_name) //定義視頻的來源。
      pCap = cvCaptureFromFile(avi_name);//從邋avi_name的視頻中讀取數據。
      //pCap = cvCreateCameraCapture(-1);//從攝像頭中讀取數據。

    if(pCap==NULL)
    {
        printf("Can't open %s file\n",avi_name);
        return -1;
    }


    {/* display parameters */
        int i;
        FILE* log = log_name?fopen(log_name,"at"):NULL;
        if(log)//rug若是定義了log的name那麼就給你輸出到一個log文件中。
        {/* print to log file *///下面的大概意思是輸出log的格式,沒有深刻分析。有興趣能夠本身分析。
            fprintf(log,"\n=== Blob Tracking pipline in processing mode===\n");
            if(avi_name)
            {
                fprintf(log,"AVIFile: %s\n",avi_name);
            }
            fprintf(log,"FGDetector:   %s\n", pFGModule->nickname);
            fprintf(log,"BlobDetector: %s\n", pBDModule->nickname);
            fprintf(log,"BlobTracker:  %s\n", pBTModule->nickname);
            fprintf(log,"BlobTrackPostProc:  %s\n", pBTPostProcModule->nickname);
            fprintf(log,"BlobCorrection:  %s\n", bt_corr);
            fprintf(log,"Blob Trajectory Generator:  %s (%s)\n",
                pBTGenModule?pBTGenModule->nickname:"None",
                track_name?track_name:"none");
            fprintf(log,"BlobTrackAnalysis:  %s\n", pBTAnalysisModule->nickname);
            fclose(log);
        }

        printf("\n=== Blob Tracking pipline in %s mode===\n","processing");
        if(yml_name)//若是定義了yml_name 那麼就讀取配置文件。
        {
            printf("ConfigFile: %s\n",yml_name);
            printf("BG: %s\n",yml_video_names[0]);
            printf("FG: ");
            for(i=1;i<(yml_video_num);++i){printf(yml_video_names[i]);if((i+1)<yml_video_num)printf("|");};
            printf("\n");
        }
        if(avi_name)//這個判斷是多餘的,前面已經判斷了不少遍了。
        {
            printf("AVIFile: %s\n",avi_name);
        }
        printf("FGDetector:   %s\n", pFGModule->nickname);//輸出各個模塊的邋nick_name
        printf("BlobDetector: %s\n", pBDModule->nickname);
        printf("BlobTracker:  %s\n", pBTModule->nickname);
        printf("BlobTrackPostProc:  %s\n", pBTPostProcModule->nickname);
        printf("BlobCorrection:  %s\n", bt_corr);
        printf("Blob Trajectory Generator:  %s (%s)\n",
            pBTGenModule?pBTGenModule->nickname:"None",
            track_name?track_name:"none");
        printf("BlobTrackAnalysis:  %s\n", pBTAnalysisModule->nickname);
    }/* display parameters */

    {   /* create autotracker module and its components*///
        param.FGTrainFrames = FGTrainFrames?atoi(FGTrainFrames):0;
		//param二神出現了。。。爲何說是二神呢?由於大神還在後面。二神是爲大神服務的。
		//param的主要做用是param內部的指向各個模塊的指針
		//上面的FgTrainFrames 是int類型,,指示當前的訓練的幀數。
        /* Create FG Detection module */
        param.pFG = pFGModule->create();//pFg的做用是指向CvFGDetector模塊的地址。
        if(!param.pFG)//若是沒有成功,打印錯誤向屏幕。通常不會出現這種狀況。
            puts("Can not create FGDetector module");
        param.pFG->SetNickName(pFGModule->nickname);//定義這個模塊的暱稱,原來寫opencv的那羣人也很浪漫,什麼也得加個Nickname,比方說「小甜甜」,
        set_params(argc, argv, param.pFG, "fg", pFGModule->nickname);//不太清楚這個函數是作什麼的。

        /* Create Blob Entrance Detection module */
        param.pBD = pBDModule->create();//指向CvBlobDetector模塊。
        if(!param.pBD)
            puts("Can not create BlobDetector module");
        param.pBD->SetNickName(pBDModule->nickname);
        set_params(argc, argv, param.pBD, "bd", pBDModule->nickname);

        /* Create blob tracker module */
        param.pBT = pBTModule->create();//指向CvBlobTracker模塊
        if(!param.pBT)
            puts("Can not create BlobTracker module");
        param.pBT->SetNickName(pBTModule->nickname);
        set_params(argc, argv, param.pBT, "bt", pBTModule->nickname);

        /* create blob trajectory generation module */
        param.pBTGen = NULL;//指向CvBlobTrackGen模塊
        if(pBTGenModule && track_name && pBTGenModule->create)
        {
            param.pBTGen = pBTGenModule->create();
            param.pBTGen->SetFileName(track_name);
        }
        if(param.pBTGen)
        {
            param.pBTGen->SetNickName(pBTGenModule->nickname);
            set_params(argc, argv, param.pBTGen, "btgen", pBTGenModule->nickname);
        }

        /* create blob trajectory post processing module *///你應該能看懂這句。
        param.pBTPP = NULL;
        if(pBTPostProcModule && pBTPostProcModule->create)
        {
            param.pBTPP = pBTPostProcModule->create();
        }
        if(param.pBTPP)
        {
            param.pBTPP->SetNickName(pBTPostProcModule->nickname);
            set_params(argc, argv, param.pBTPP, "btpp", pBTPostProcModule->nickname);
        }

        param.UsePPData = (bt_corr && MY_STRICMP(bt_corr,"PostProcRes")==0);

        /* create blob trajectory analysis module *///你應該能看懂這句。

        param.pBTA = NULL;
        if(pBTAnalysisModule && pBTAnalysisModule->create)
        {
            param.pBTA = pBTAnalysisModule->create();
            param.pBTA->SetFileName(bta_data_name);
        }
        if(param.pBTA)
        {
            param.pBTA->SetNickName(pBTAnalysisModule->nickname);
            set_params(argc, argv, param.pBTA, "bta", pBTAnalysisModule->nickname);
        }

        /* create whole pipline *///pTracker大神終於出現了,原來上面全是param的初始化。經過param來初始化pTracker
        pTracker = cvCreateBlobTrackerAuto1(¶m);
        if(!pTracker)
            puts("Can not create BlobTrackerAuto");
    }
    
    { /* load states of each module from state file */
        CvFileStorage* fs = NULL;
        if(loadstate_name) //若是你想從已有的配置文件中讀取數據就定義loadstate_name中讀取。
            fs=cvOpenFileStorage(loadstate_name,NULL,CV_STORAGE_READ);
        if(fs)
        {
            printf("Load states for modules...\n");
            if(param.pBT)
            {
                CvFileNode* fn = cvGetFileNodeByName(fs,NULL,"BlobTracker");//讀取邋BlobTracker的值,
                param.pBT->LoadState(fs,fn);//
            }
            
            if(param.pBTA)
            {
                CvFileNode* fn = cvGetFileNodeByName(fs,NULL,"BlobTrackAnalyser");
                param.pBTA->LoadState(fs,fn);
            }

            if(pTracker)
            {
                CvFileNode* fn = cvGetFileNodeByName(fs,NULL,"BlobTrackerAuto");
                pTracker->LoadState(fs,fn);
            }

            cvReleaseFileStorage(&fs);
            printf("... Modules states loaded\n");
        }
    }/* load states of each module */

    {/* print modules parameters */
        struct DefMMM
        {
            CvVSModule* pM;
            char* name;
        } Modules[] = {
            {(CvVSModule*)param.pFG,"FGdetector"},
            {(CvVSModule*)param.pBD,"BlobDetector"},
            {(CvVSModule*)param.pBT,"BlobTracker"},
            {(CvVSModule*)param.pBTGen,"TrackGen"},
            {(CvVSModule*)param.pBTPP,"PostProcessing"},
            {(CvVSModule*)param.pBTA,"TrackAnalysis"},
            {NULL,NULL}
        };
        int     i;
        for(i=0;Modules[i].name;++i)//打各個模塊的信息,這時候邋nick_name起了做用了。
        {
            if(Modules[i].pM)
                print_params(Modules[i].pM,Modules[i].name,log_name);
        }
    }/* print modules parameters */

    /* run pipeline *///開始流水線。流水線退出,意味着程序結束,
    RunBlobTrackingAuto( pCap, pTracker, fgavi_name, btavi_name );
        
    {/* save state and release modules *///釋放內存,攝像頭句柄,保存文件等。
        CvFileStorage* fs = NULL;
        if(savestate_name)
        {
            fs=cvOpenFileStorage(savestate_name,NULL,CV_STORAGE_WRITE);
        }
        if(fs)
        {
            cvStartWriteStruct(fs,"BlobTracker",CV_NODE_MAP);
            if(param.pBT)param.pBT->SaveState(fs);
            cvEndWriteStruct(fs);
            cvStartWriteStruct(fs,"BlobTrackerAuto",CV_NODE_MAP);
            if(pTracker)pTracker->SaveState(fs);
            cvEndWriteStruct(fs);
            cvStartWriteStruct(fs,"BlobTrackAnalyser",CV_NODE_MAP);
            if(param.pBTA)param.pBTA->SaveState(fs);
            cvEndWriteStruct(fs);
            cvReleaseFileStorage(&fs);
        }
        if(param.pBT)cvReleaseBlobTracker(¶m.pBT);
        if(param.pBD)cvReleaseBlobDetector(¶m.pBD);
        if(param.pBTGen)cvReleaseBlobTrackGen(¶m.pBTGen);
        if(param.pBTA)cvReleaseBlobTrackAnalysis(¶m.pBTA);
        if(param.pFG)cvReleaseFGDetector(¶m.pFG);
        if(pTracker)cvReleaseBlobTrackerAuto(&pTracker);
    }/* save state and release modules*/

    if(pCap)
        cvReleaseCapture(&pCap);
	//getchar();
    return 0;
}/* main */


相關文章
相關標籤/搜索