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 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;
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 } /* CvBlobTrackerAuto1::CvBlobTrackerAuto1 */
197 /* Destructor for auto blob tracker: */
198 CvBlobTrackerAuto1::~CvBlobTrackerAuto1()
200 if(m_BDDel)m_pBD->Release();
201 if(m_BTDel)m_pBT->Release();
204 void CvBlobTrackerAuto1::Process(IplImage* pImg, IplImage* pMask)
208 IplImage* pFG = pMask;
210 /* Bump frame counter: */
215 static int64 TickCount = cvGetTickCount();
216 static double TimeSum = 0;
217 static int Count = 0;
224 FILE* out = fopen(m_TimesFile,"at");
226 TickCount = cvGetTickCount()-TickCount;
227 Time = TickCount/FREQ;
228 if(out){fprintf(out,"- %sFrame: %d ALL_TIME - %f\n",ctime( <ime ),Count,Time/1000);fclose(out);}
231 TickCount = cvGetTickCount();
235 /* Update BG model: */
239 { /* If FG detector is needed: */
240 m_pFG->Process(pImg);
241 pFG = m_pFG->GetMask();
242 } /* If FG detector is needed. */
244 TIME_END("FGDetector",-1)
246 m_pFGMask = pFG; /* For external use. */
248 /*if(m_pFG && m_pFG->GetParam("DebugWnd") == 1)
249 {// debug foreground result
250 IplImage *pFG = m_pFG->GetMask();
253 cvNamedWindow("FG",0);
254 cvShowImage("FG", pFG);
263 m_pBT->Process(pImg, pFG);
265 for(i=m_BlobList.GetBlobNum(); i>0; --i)
266 { /* Update data of tracked blob list: */
267 CvBlob* pB = m_BlobList.GetBlob(i-1);
268 int BlobID = CV_BLOB_ID(pB);
269 int i = m_pBT->GetBlobIndexByID(BlobID);
270 m_pBT->ProcessBlob(i, pB, pImg, pFG);
273 CurBlobNum = m_pBT->GetBlobNum();
275 TIME_END("BlobTracker",CurBlobNum)
277 /* This part should be removed: */
278 if(m_BTReal && m_pBT)
279 { /* Update blob list (detect new blob for real blob tracker): */
282 for(i=m_pBT->GetBlobNum(); i>0; --i)
283 { /* Update data of tracked blob list: */
284 CvBlob* pB = m_pBT->GetBlob(i-1);
285 if(pB && m_BlobList.GetBlobByID(CV_BLOB_ID(pB)) == NULL )
287 CvBlobTrackAuto NewB;
290 m_BlobList.AddBlob((CvBlob*)&NewB);
295 for(i=m_BlobList.GetBlobNum(); i>0; --i)
296 { /* Update tracked-blob list: */
297 CvBlob* pB = m_BlobList.GetBlob(i-1);
298 if(pB && m_pBT->GetBlobByID(CV_BLOB_ID(pB)) == NULL )
300 m_BlobList.DelBlob(i-1);
303 } /* Update bloblist. */
308 { /* Post-processing module: */
310 for(i=m_BlobList.GetBlobNum(); i>0; --i)
311 { /* Update tracked-blob list: */
312 CvBlob* pB = m_BlobList.GetBlob(i-1);
313 m_pBTPostProc->AddBlob(pB);
315 m_pBTPostProc->Process();
317 for(i=m_BlobList.GetBlobNum(); i>0; --i)
318 { /* Update tracked-blob list: */
319 CvBlob* pB = m_BlobList.GetBlob(i-1);
320 int BlobID = CV_BLOB_ID(pB);
321 CvBlob* pBN = m_pBTPostProc->GetBlobByID(BlobID);
323 if(pBN && m_UsePPData && pBN->w >= CV_BLOB_MINW && pBN->h >= CV_BLOB_MINH)
324 { /* Set new data for tracker: */
325 m_pBT->SetBlobByID(BlobID, pBN );
329 { /* Update blob list with results from postprocessing: */
333 } /* Post-processing module. */
335 TIME_END("PostProcessing",CurBlobNum)
337 /* Blob deleter (experimental and simple): */
340 { /* Blob deleter: */
342 if(!m_BTReal)for(i=m_BlobList.GetBlobNum();i>0;--i)
343 { /* Check all blobs on list: */
344 CvBlobTrackAuto* pB = (CvBlobTrackAuto*)(m_BlobList.GetBlob(i-1));
348 CvRect r = CV_BLOB_RECT(pB);
351 double area = CV_BLOB_WX(pB)*CV_BLOB_WY(pB);
352 if(r.x < 0){r.width += r.x;r.x = 0;}
353 if(r.y < 0){r.height += r.y;r.y = 0;}
354 if(r.x+r.width>=w){r.width = w-r.x-1;}
355 if(r.y+r.height>=h){r.height = h-r.y-1;}
357 if(r.width > 4 && r.height > 4 && r.x < w && r.y < h &&
358 r.x >=0 && r.y >=0 &&
359 r.x+r.width < w && r.y+r.height < h && area > 0)
361 aver = cvSum(cvGetSubRect(pFG,&mat,r)).val[0] / area;
362 /* if mask in blob area exists then its blob OK*/
363 if(aver > 0.1*255)Good = 1;
380 /* Check error count: */
381 for(i=0; i<m_BlobList.GetBlobNum(); ++i)
383 CvBlobTrackAuto* pB = (CvBlobTrackAuto*)m_BlobList.GetBlob(i);
386 { /* Delete such objects */
387 /* from tracker... */
388 m_pBT->DelBlobByID(CV_BLOB_ID(pB));
390 /* ... and from local list: */
391 m_BlobList.DelBlob(i);
394 } /* Check error count for next blob. */
395 } /* Blob deleter. */
397 TIME_END("BlobDeleter",m_BlobList.GetBlobNum())
402 m_pBT->Update(pImg, pFG);
403 TIME_END("BlobTrackerUpdate",CurBlobNum)
405 /* Detect new blob: */
407 if(!m_BTReal && m_pBD && pFG && (m_FrameCount > m_FGTrainFrames) )
408 { /* Detect new blob: */
409 static CvBlobSeq NewBlobList;
410 CvBlobTrackAuto NewB;
414 if(m_pBD->DetectNewBlob(pImg, pFG, &NewBlobList, &m_BlobList))
415 { /* Add new blob to tracker and blob list: */
417 IplImage* pMask = pFG;
419 /*if(0)if(NewBlobList.GetBlobNum()>0 && pFG )
420 {// erode FG mask (only for FG_0 and MS1||MS2)
421 pMask = cvCloneImage(pFG);
422 cvErode(pFG,pMask,NULL,2);
425 for(i=0; i<NewBlobList.GetBlobNum(); ++i)
427 CvBlob* pBN = NewBlobList.GetBlob(i);
428 pBN->ID = m_NextBlobID;
430 if(pBN && pBN->w >= CV_BLOB_MINW && pBN->h >= CV_BLOB_MINH)
432 CvBlob* pB = m_pBT->AddBlob(pBN, pImg, pMask );
437 m_BlobList.AddBlob((CvBlob*)&NewB);
441 } /* Add next blob from list of detected blob. */
443 if(pMask != pFG) cvReleaseImage(&pMask);
445 } /* Create and add new blobs and trackers. */
447 } /* Detect new blob. */
449 TIME_END("BlobDetector",-1)
453 { /* Run track generator: */
454 for(i=m_BlobList.GetBlobNum(); i>0; --i)
455 { /* Update data of tracked blob list: */
456 CvBlob* pB = m_BlobList.GetBlob(i-1);
457 m_pBTGen->AddBlob(pB);
459 m_pBTGen->Process(pImg, pFG);
460 } /* Run track generator: */
461 TIME_END("TrajectoryGeneration",-1)
465 { /* Trajectory analysis module: */
467 for(i=m_BlobList.GetBlobNum(); i>0; i--)
468 m_pBTA->AddBlob(m_BlobList.GetBlob(i-1));
470 m_pBTA->Process(pImg, pFG);
472 } /* Trajectory analysis module. */
474 TIME_END("TrackAnalysis",m_BlobList.GetBlobNum())
476 } /* CvBlobTrackerAuto1::Process */