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
48 #include "precomp.hpp"
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)
209 IplImage* pFG = pMask;
211 /* Bump frame counter: */
216 static int64 TickCount = cvGetTickCount();
217 static double TimeSum = 0;
218 static int Count = 0;
226 char* stime = ctime( <ime );
228 /* WINCE does not have above POSIX functions (time,ctime) */
229 const char* stime = " wince ";
231 FILE* out = fopen(m_TimesFile,"at");
233 TickCount = cvGetTickCount()-TickCount;
234 Time = TickCount/FREQ;
236 if(out){fprintf(out,"- %sFrame: %d ALL_TIME - %f\n",stime,Count,TimeSum/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);
270 m_pBT->Process(pImg, pFG);
272 for(int i=m_BlobList.GetBlobNum(); i>0; --i)
273 { /* Update data of tracked blob list: */
274 CvBlob* pB = m_BlobList.GetBlob(i-1);
275 int BlobID = CV_BLOB_ID(pB);
276 int idx = m_pBT->GetBlobIndexByID(BlobID);
277 m_pBT->ProcessBlob(idx, pB, pImg, pFG);
280 CurBlobNum = m_pBT->GetBlobNum();
282 TIME_END("BlobTracker",CurBlobNum)
284 /* This part should be removed: */
285 if(m_BTReal && m_pBT)
286 { /* Update blob list (detect new blob for real blob tracker): */
287 for(int i=m_pBT->GetBlobNum(); i>0; --i)
288 { /* Update data of tracked blob list: */
289 CvBlob* pB = m_pBT->GetBlob(i-1);
290 if(pB && m_BlobList.GetBlobByID(CV_BLOB_ID(pB)) == NULL )
292 CvBlobTrackAuto NewB;
295 m_BlobList.AddBlob((CvBlob*)&NewB);
300 for(int i=m_BlobList.GetBlobNum(); i>0; --i)
301 { /* Update tracked-blob list: */
302 CvBlob* pB = m_BlobList.GetBlob(i-1);
303 if(pB && m_pBT->GetBlobByID(CV_BLOB_ID(pB)) == NULL )
305 m_BlobList.DelBlob(i-1);
308 } /* Update bloblist. */
313 { /* Post-processing module: */
314 for(int i=m_BlobList.GetBlobNum(); i>0; --i)
315 { /* Update tracked-blob list: */
316 CvBlob* pB = m_BlobList.GetBlob(i-1);
317 m_pBTPostProc->AddBlob(pB);
319 m_pBTPostProc->Process();
321 for(int i=m_BlobList.GetBlobNum(); i>0; --i)
322 { /* Update tracked-blob list: */
323 CvBlob* pB = m_BlobList.GetBlob(i-1);
324 int BlobID = CV_BLOB_ID(pB);
325 CvBlob* pBN = m_pBTPostProc->GetBlobByID(BlobID);
327 if(pBN && m_UsePPData && pBN->w >= CV_BLOB_MINW && pBN->h >= CV_BLOB_MINH)
328 { /* Set new data for tracker: */
329 m_pBT->SetBlobByID(BlobID, pBN );
333 { /* Update blob list with results from postprocessing: */
337 } /* Post-processing module. */
339 TIME_END("PostProcessing",CurBlobNum)
341 /* Blob deleter (experimental and simple): */
344 { /* Blob deleter: */
346 if(!m_BTReal)for(i=m_BlobList.GetBlobNum();i>0;--i)
347 { /* Check all blobs on list: */
348 CvBlobTrackAuto* pB = (CvBlobTrackAuto*)(m_BlobList.GetBlob(i-1));
352 CvRect r = CV_BLOB_RECT(pB);
355 double area = CV_BLOB_WX(pB)*CV_BLOB_WY(pB);
356 if(r.x < 0){r.width += r.x;r.x = 0;}
357 if(r.y < 0){r.height += r.y;r.y = 0;}
358 if(r.x+r.width>=w){r.width = w-r.x-1;}
359 if(r.y+r.height>=h){r.height = h-r.y-1;}
361 if(r.width > 4 && r.height > 4 && r.x < w && r.y < h &&
362 r.x >=0 && r.y >=0 &&
363 r.x+r.width < w && r.y+r.height < h && area > 0)
365 aver = cvSum(cvGetSubRect(pFG,&mat,r)).val[0] / area;
366 /* if mask in blob area exists then its blob OK*/
367 if(aver > 0.1*255)Good = 1;
384 /* Check error count: */
385 for(i=0; i<m_BlobList.GetBlobNum(); ++i)
387 CvBlobTrackAuto* pB = (CvBlobTrackAuto*)m_BlobList.GetBlob(i);
390 { /* Delete such objects */
391 /* from tracker... */
392 m_pBT->DelBlobByID(CV_BLOB_ID(pB));
394 /* ... and from local list: */
395 m_BlobList.DelBlob(i);
398 } /* Check error count for next blob. */
399 } /* Blob deleter. */
401 TIME_END("BlobDeleter",m_BlobList.GetBlobNum())
406 m_pBT->Update(pImg, pFG);
407 TIME_END("BlobTrackerUpdate",CurBlobNum)
409 /* Detect new blob: */
411 if(!m_BTReal && m_pBD && pFG && (m_FrameCount > m_FGTrainFrames) )
412 { /* Detect new blob: */
413 static CvBlobSeq NewBlobList;
414 CvBlobTrackAuto NewB;
418 if(m_pBD->DetectNewBlob(pImg, pFG, &NewBlobList, &m_BlobList))
419 { /* Add new blob to tracker and blob list: */
421 IplImage* pmask = pFG;
423 /*if(0)if(NewBlobList.GetBlobNum()>0 && pFG )
424 {// erode FG mask (only for FG_0 and MS1||MS2)
425 pmask = cvCloneImage(pFG);
426 cvErode(pFG,pmask,NULL,2);
429 for(i=0; i<NewBlobList.GetBlobNum(); ++i)
431 CvBlob* pBN = NewBlobList.GetBlob(i);
433 if(pBN && pBN->w >= CV_BLOB_MINW && pBN->h >= CV_BLOB_MINH)
435 pBN->ID = m_NextBlobID;
437 CvBlob* pB = m_pBT->AddBlob(pBN, pImg, pmask );
442 m_BlobList.AddBlob((CvBlob*)&NewB);
446 } /* Add next blob from list of detected blob. */
448 if(pmask != pFG) cvReleaseImage(&pmask);
450 } /* Create and add new blobs and trackers. */
452 } /* Detect new blob. */
454 TIME_END("BlobDetector",-1)
458 { /* Run track generator: */
459 for(int i=m_BlobList.GetBlobNum(); i>0; --i)
460 { /* Update data of tracked blob list: */
461 CvBlob* pB = m_BlobList.GetBlob(i-1);
462 m_pBTGen->AddBlob(pB);
464 m_pBTGen->Process(pImg, pFG);
465 } /* Run track generator: */
466 TIME_END("TrajectoryGeneration",-1)
470 { /* Trajectory analysis module: */
472 for(i=m_BlobList.GetBlobNum(); i>0; i--)
473 m_pBTA->AddBlob(m_BlobList.GetBlob(i-1));
475 m_pBTA->Process(pImg, pFG);
477 } /* Trajectory analysis module. */
479 TIME_END("TrackAnalysis",m_BlobList.GetBlobNum())
481 } /* CvBlobTrackerAuto1::Process */