1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
10 // Intel License Agreement
12 // Copyright (C) 2000, Intel Corporation, rights reserved.
13 // Third party copyrights are property of their respective owners.
15 // Redistribution and use in source and binary forms, with or without modification,
16 // are permitted provided that the following conditions are met:
18 // * Redistribution's of source code must retain the above copyright notice,
19 // this list of conditions and the following disclaimer.
21 // * Redistribution's in binary form must reproduce the above copyright notice,
22 // this list of conditions and the following disclaimer in the documentation
23 // and/or other materials provided with the distribution.
25 // * The name of Intel Corporation may not be used to endorse or promote products
26 // derived from this software without specific prior written permission.
28 // This software is provided by the copyright holders and contributors "as is" and
29 // any express or implied warranties, including, but not limited to, the implied
30 // warranties of merchantability and fitness for a particular purpose are disclaimed.
31 // In no event shall the Intel Corporation or contributors be liable for any direct,
32 // indirect, incidental, special, exemplary, or consequential damages
33 // (including, but not limited to, procurement of substitute goods or services;
34 // loss of use, data, or profits; or business interruption) however caused
35 // and on any theory of liability, whether in contract, strict liability,
36 // or tort (including negligence or otherwise) arising in any way out of
37 // the use of this software, even if advised of the possibility of such damage.
42 This file contain simple implementation of BlobTrackerAuto virtual interface
43 This module just connected other low level 3 modules
44 (foreground estimator + BlobDetector + BlobTracker)
45 and some simple code to detect "lost tracking"
46 The track is lost when integral of foreground mask image by blob area has low value
51 /* list of Blob Detection modules */
52 CvBlobDetector* cvCreateBlobDetectorSimple();
54 /* Get frequency for each module time working estimation: */
55 static double FREQ = 1000*cvGetTickFrequency();
59 #define TIME_BEGIN() \
61 static double _TimeSum = 0;\
62 static int _Count = 0;\
63 static int _CountBlob = 0;\
64 int64 _TickCount = cvGetTickCount();\
66 #define TIME_END(_name_,_BlobNum_) \
68 _CountBlob+=_BlobNum_;\
69 _TimeSum += (cvGetTickCount()-_TickCount)/FREQ;\
70 if(m_TimesFile)if(_Count%COUNTNUM==0)\
72 FILE* out = fopen(m_TimesFile,"at");\
75 fprintf(out,"ForFrame Frame: %d %s %f on %f blobs\n",_Count,_name_, _TimeSum/COUNTNUM,((float)_CountBlob)/COUNTNUM);\
76 if(_CountBlob>0)fprintf(out,"ForBlob Frame: %d %s - %f\n",_Count,_name_, _TimeSum/_CountBlob);\
85 #define TIME_END(_name_)
88 /* Special extended blob structure for auto blob tracking: */
89 typedef struct CvBlobTrackAuto
95 class CvBlobTrackerAuto1: public CvBlobTrackerAuto
98 CvBlobTrackerAuto1(CvBlobTrackerAutoParam1* param);
99 ~CvBlobTrackerAuto1();
100 CvBlob* GetBlob(int index){return m_BlobList.GetBlob(index);};
101 CvBlob* GetBlobByID(int ID){return m_BlobList.GetBlobByID(ID);};
102 int GetBlobNum(){return m_BlobList.GetBlobNum();};
103 virtual IplImage* GetFGMask(){return m_pFGMask;};
104 float GetState(int BlobID){return m_pBTA?m_pBTA->GetState(BlobID):0;};
105 const char* GetStateDesc(int BlobID){return m_pBTA?m_pBTA->GetStateDesc(BlobID):NULL;};
106 /* Return 0 if trajectory is normal;
107 return >0 if trajectory abnormal. */
108 void Process(IplImage* pImg, IplImage* pMask = NULL);
109 void Release(){delete this;};
114 CvFGDetector* m_pFG; /* Pointer to foreground mask detector module. */
115 CvBlobTracker* m_pBT; /* Pointer to Blob tracker module. */
118 CvBlobDetector* m_pBD; /* Pointer to Blob detector module. */
120 CvBlobTrackGen* m_pBTGen;
121 CvBlobTrackPostProc* m_pBTPostProc;
123 CvBlobTrackAnalysis* m_pBTA; /* Blob trajectory analyser. */
124 CvBlobSeq m_BlobList;
127 const char* m_TimesFile;
130 virtual void SaveState(CvFileStorage* fs)
132 cvWriteInt(fs,"FrameCount",m_FrameCount);
133 cvWriteInt(fs,"NextBlobID",m_NextBlobID);
134 m_BlobList.Write(fs,"BlobList");
137 virtual void LoadState(CvFileStorage* fs, CvFileNode* node)
139 CvFileNode* BlobListNode = cvGetFileNodeByName(fs,node,"BlobList");
140 m_FrameCount = cvReadIntByName(fs,node, "FrameCount", m_FrameCount);
141 m_NextBlobID = cvReadIntByName(fs,node, "NextBlobID", m_NextBlobID);
144 m_BlobList.Load(fs,BlobListNode);
149 /* Auto Blob tracker creater (sole interface function for this file) */
150 CvBlobTrackerAuto* cvCreateBlobTrackerAuto1(CvBlobTrackerAutoParam1* param)
152 return (CvBlobTrackerAuto*)new CvBlobTrackerAuto1(param);
155 /* Constructor of auto blob tracker: */
156 CvBlobTrackerAuto1::CvBlobTrackerAuto1(CvBlobTrackerAutoParam1* param):m_BlobList(sizeof(CvBlobTrackAuto))
158 m_BlobList.AddFormat("i");
160 AddParam("TimesFile",&m_TimesFile);
166 m_FGTrainFrames = param?param->FGTrainFrames:0;
167 m_pFG = param?param->pFG:0;
170 m_pBD = param?param->pBD:NULL;
172 m_pBT = param?param->pBT:NULL;;
173 m_BTReal = m_pBT?m_pBT->IsModuleName("BlobTrackerReal"):0;
175 m_pBTGen = param?param->pBTGen:NULL;
177 m_pBTA = param?param->pBTA:NULL;
179 m_pBTPostProc = param?param->pBTPP:NULL;
180 m_UsePPData = param?param->UsePPData:0;
182 /* Create default submodules: */
185 m_pBD = cvCreateBlobDetectorSimple();
191 m_pBT = cvCreateBlobTrackerMS();
195 SetModuleName("Auto1");
197 } /* CvBlobTrackerAuto1::CvBlobTrackerAuto1 */
199 /* Destructor for auto blob tracker: */
200 CvBlobTrackerAuto1::~CvBlobTrackerAuto1()
202 if(m_BDDel)m_pBD->Release();
203 if(m_BTDel)m_pBT->Release();
206 void CvBlobTrackerAuto1::Process(IplImage* pImg, IplImage* pMask)
210 IplImage* pFG = pMask;
212 /* Bump frame counter: */
217 static int64 TickCount = cvGetTickCount();
218 static double TimeSum = 0;
219 static int Count = 0;
227 char* stime = ctime( <ime );
229 /* WINCE does not have above POSIX functions (time,ctime) */
230 const char* stime = " wince ";
232 FILE* out = fopen(m_TimesFile,"at");
234 TickCount = cvGetTickCount()-TickCount;
235 Time = TickCount/FREQ;
236 if(out){fprintf(out,"- %sFrame: %d ALL_TIME - %f\n",stime,Count,Time/1000);fclose(out);}
239 TickCount = cvGetTickCount();
243 /* Update BG model: */
247 { /* If FG detector is needed: */
248 m_pFG->Process(pImg);
249 pFG = m_pFG->GetMask();
250 } /* If FG detector is needed. */
252 TIME_END("FGDetector",-1)
254 m_pFGMask = pFG; /* For external use. */
256 /*if(m_pFG && m_pFG->GetParam("DebugWnd") == 1)
257 {// debug foreground result
258 IplImage *pFG = m_pFG->GetMask();
261 cvNamedWindow("FG",0);
262 cvShowImage("FG", pFG);
271 m_pBT->Process(pImg, pFG);
273 for(i=m_BlobList.GetBlobNum(); i>0; --i)
274 { /* Update data of tracked blob list: */
275 CvBlob* pB = m_BlobList.GetBlob(i-1);
276 int BlobID = CV_BLOB_ID(pB);
277 int i = m_pBT->GetBlobIndexByID(BlobID);
278 m_pBT->ProcessBlob(i, pB, pImg, pFG);
281 CurBlobNum = m_pBT->GetBlobNum();
283 TIME_END("BlobTracker",CurBlobNum)
285 /* This part should be removed: */
286 if(m_BTReal && m_pBT)
287 { /* Update blob list (detect new blob for real blob tracker): */
290 for(i=m_pBT->GetBlobNum(); i>0; --i)
291 { /* Update data of tracked blob list: */
292 CvBlob* pB = m_pBT->GetBlob(i-1);
293 if(pB && m_BlobList.GetBlobByID(CV_BLOB_ID(pB)) == NULL )
295 CvBlobTrackAuto NewB;
298 m_BlobList.AddBlob((CvBlob*)&NewB);
303 for(i=m_BlobList.GetBlobNum(); i>0; --i)
304 { /* Update tracked-blob list: */
305 CvBlob* pB = m_BlobList.GetBlob(i-1);
306 if(pB && m_pBT->GetBlobByID(CV_BLOB_ID(pB)) == NULL )
308 m_BlobList.DelBlob(i-1);
311 } /* Update bloblist. */
316 { /* Post-processing module: */
318 for(i=m_BlobList.GetBlobNum(); i>0; --i)
319 { /* Update tracked-blob list: */
320 CvBlob* pB = m_BlobList.GetBlob(i-1);
321 m_pBTPostProc->AddBlob(pB);
323 m_pBTPostProc->Process();
325 for(i=m_BlobList.GetBlobNum(); i>0; --i)
326 { /* Update tracked-blob list: */
327 CvBlob* pB = m_BlobList.GetBlob(i-1);
328 int BlobID = CV_BLOB_ID(pB);
329 CvBlob* pBN = m_pBTPostProc->GetBlobByID(BlobID);
331 if(pBN && m_UsePPData && pBN->w >= CV_BLOB_MINW && pBN->h >= CV_BLOB_MINH)
332 { /* Set new data for tracker: */
333 m_pBT->SetBlobByID(BlobID, pBN );
337 { /* Update blob list with results from postprocessing: */
341 } /* Post-processing module. */
343 TIME_END("PostProcessing",CurBlobNum)
345 /* Blob deleter (experimental and simple): */
348 { /* Blob deleter: */
350 if(!m_BTReal)for(i=m_BlobList.GetBlobNum();i>0;--i)
351 { /* Check all blobs on list: */
352 CvBlobTrackAuto* pB = (CvBlobTrackAuto*)(m_BlobList.GetBlob(i-1));
356 CvRect r = CV_BLOB_RECT(pB);
359 double area = CV_BLOB_WX(pB)*CV_BLOB_WY(pB);
360 if(r.x < 0){r.width += r.x;r.x = 0;}
361 if(r.y < 0){r.height += r.y;r.y = 0;}
362 if(r.x+r.width>=w){r.width = w-r.x-1;}
363 if(r.y+r.height>=h){r.height = h-r.y-1;}
365 if(r.width > 4 && r.height > 4 && r.x < w && r.y < h &&
366 r.x >=0 && r.y >=0 &&
367 r.x+r.width < w && r.y+r.height < h && area > 0)
369 aver = cvSum(cvGetSubRect(pFG,&mat,r)).val[0] / area;
370 /* if mask in blob area exists then its blob OK*/
371 if(aver > 0.1*255)Good = 1;
388 /* Check error count: */
389 for(i=0; i<m_BlobList.GetBlobNum(); ++i)
391 CvBlobTrackAuto* pB = (CvBlobTrackAuto*)m_BlobList.GetBlob(i);
394 { /* Delete such objects */
395 /* from tracker... */
396 m_pBT->DelBlobByID(CV_BLOB_ID(pB));
398 /* ... and from local list: */
399 m_BlobList.DelBlob(i);
402 } /* Check error count for next blob. */
403 } /* Blob deleter. */
405 TIME_END("BlobDeleter",m_BlobList.GetBlobNum())
410 m_pBT->Update(pImg, pFG);
411 TIME_END("BlobTrackerUpdate",CurBlobNum)
413 /* Detect new blob: */
415 if(!m_BTReal && m_pBD && pFG && (m_FrameCount > m_FGTrainFrames) )
416 { /* Detect new blob: */
417 static CvBlobSeq NewBlobList;
418 CvBlobTrackAuto NewB;
422 if(m_pBD->DetectNewBlob(pImg, pFG, &NewBlobList, &m_BlobList))
423 { /* Add new blob to tracker and blob list: */
425 IplImage* pMask = pFG;
427 /*if(0)if(NewBlobList.GetBlobNum()>0 && pFG )
428 {// erode FG mask (only for FG_0 and MS1||MS2)
429 pMask = cvCloneImage(pFG);
430 cvErode(pFG,pMask,NULL,2);
433 for(i=0; i<NewBlobList.GetBlobNum(); ++i)
435 CvBlob* pBN = NewBlobList.GetBlob(i);
436 pBN->ID = m_NextBlobID;
438 if(pBN && pBN->w >= CV_BLOB_MINW && pBN->h >= CV_BLOB_MINH)
440 CvBlob* pB = m_pBT->AddBlob(pBN, pImg, pMask );
445 m_BlobList.AddBlob((CvBlob*)&NewB);
449 } /* Add next blob from list of detected blob. */
451 if(pMask != pFG) cvReleaseImage(&pMask);
453 } /* Create and add new blobs and trackers. */
455 } /* Detect new blob. */
457 TIME_END("BlobDetector",-1)
461 { /* Run track generator: */
462 for(i=m_BlobList.GetBlobNum(); i>0; --i)
463 { /* Update data of tracked blob list: */
464 CvBlob* pB = m_BlobList.GetBlob(i-1);
465 m_pBTGen->AddBlob(pB);
467 m_pBTGen->Process(pImg, pFG);
468 } /* Run track generator: */
469 TIME_END("TrajectoryGeneration",-1)
473 { /* Trajectory analysis module: */
475 for(i=m_BlobList.GetBlobNum(); i>0; i--)
476 m_pBTA->AddBlob(m_BlobList.GetBlob(i-1));
478 m_pBTA->Process(pImg, pFG);
480 } /* Trajectory analysis module. */
482 TIME_END("TrackAnalysis",m_BlobList.GetBlobNum())
484 } /* CvBlobTrackerAuto1::Process */