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, all 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.
43 /*============== BLOB TRACKERCC CLASS DECLARATION =============== */
44 typedef struct DefBlobTrackerCR
47 CvBlobTrackPredictor* pPredictor;
52 CvBlobTrackerOne* pResolver;
54 void cvFindBlobsByCCClasters(IplImage* pFG, CvBlobSeq* pBlobs, CvMemStorage* storage);
55 class CvBlobTrackerCCCR : public CvBlobTracker
61 CvBlobSeq m_BlobListNew;
63 CvBlobTrackerOne* (*m_CreateCR)();
64 char m_ModuleName[1024];
68 CvBlobTrackerCCCR(CvBlobTrackerOne* (*CreateCR)(), char* CRName):m_BlobList(sizeof(DefBlobTrackerCR))
70 m_CreateCR = CreateCR;
71 m_pMem = cvCreateMemStorage();
73 m_Collision = 1; /* if 1 then collistion will be detected and processed */
76 AddParam("AlphaSize",&m_AlphaSize);
77 CommentParam("AlphaSize", "Size update speed (0..1)");
79 strcpy(m_ModuleName, "CC");
80 if(CRName)strcat(m_ModuleName,CRName);
81 SetModuleName(m_ModuleName);
84 CvBlobTrackerOne* pM = m_CreateCR();
85 TransferParamsFromChild(pM,NULL);
88 SetParam("SizeVar",0);
92 if(m_pMem)cvReleaseMemStorage(&m_pMem);
96 virtual int GetBlobNum() {return m_BlobList.GetBlobNum();};
97 virtual CvBlob* GetBlob(int BlobIndex){return m_BlobList.GetBlob(BlobIndex);};
98 virtual void SetBlob(int BlobIndex, CvBlob* pBlob)
100 CvBlob* pB = m_BlobList.GetBlob(BlobIndex);
101 if(pB) pB[0] = pBlob[0];
103 virtual CvBlob* GetBlobByID(int BlobID){return m_BlobList.GetBlobByID(BlobID);};
104 virtual void DelBlob(int BlobIndex)
106 DefBlobTrackerCR* pBT = (DefBlobTrackerCR*)m_BlobList.GetBlob(BlobIndex);
107 if(pBT->pResolver)pBT->pResolver->Release();
108 if(pBT->pPredictor)pBT->pPredictor->Release();
109 delete pBT->pBlobHyp;
110 m_BlobList.DelBlob(BlobIndex);
112 virtual void DelBlobByID(int BlobID)
114 DefBlobTrackerCR* pBT = (DefBlobTrackerCR*)m_BlobList.GetBlobByID(BlobID);
115 if(pBT->pResolver)pBT->pResolver->Release();
116 if(pBT->pPredictor)pBT->pPredictor->Release();
117 delete pBT->pBlobHyp;
118 m_BlobList.DelBlobByID(BlobID);
120 virtual void Release(){delete this;};
122 /* Add new blob to track it and assign to this blob personal ID */
123 /* pBlob - pinter to structure with blob parameters (ID is ignored)*/
124 /* pImg - current image */
125 /* pImgFG - current foreground mask */
126 /* return pointer to new added blob */
127 virtual CvBlob* AddBlob(CvBlob* pB, IplImage* pImg, IplImage* pImgFG = NULL )
129 DefBlobTrackerCR NewB;
131 NewB.pBlobHyp = new CvBlobSeq;
132 NewB.pPredictor = cvCreateModuleBlobTrackPredictKalman(); /* module for predict position */
133 NewB.pPredictor->SetParam("DataNoisePos",0.001);
134 NewB.pPredictor->ParamUpdate();
135 NewB.pResolver = NULL;
138 NewB.pResolver = m_CreateCR();
139 TransferParamsToChild(NewB.pResolver,NULL);
140 NewB.pResolver->Init(pB, pImg, pImgFG);
142 m_BlobList.AddBlob((CvBlob*)&NewB);
143 return m_BlobList.GetBlob(m_BlobList.GetBlobNum()-1);
145 virtual void Process(IplImage* pImg, IplImage* pImgFG = NULL)
152 if(m_BlobList.GetBlobNum() <= 0 ) return;
154 /* clear blob list for new blobs */
155 m_BlobListNew.Clear();
158 cvClearMemStorage(m_pMem);
161 {/* one contour - one blob */
162 IplImage* pBin = cvCloneImage(pImgFG);
164 cvThreshold(pBin,pBin,128,255,CV_THRESH_BINARY);
165 cvFindContours(pBin, m_pMem, &cnts, sizeof(CvContour), CV_RETR_EXTERNAL);
166 /* process each contours*/
167 for(cnt = cnts;cnt;cnt=cnt->h_next)
171 double M00,X,Y,XX,YY;
173 CvRect r = ((CvContour*)cnt)->rect;
175 if(r.height < 3 || r.width < 3) continue;
176 cvMoments( cvGetSubRect(pImgFG,&mat,r), &m, 0 );
177 M00 = cvGetSpatialMoment( &m, 0, 0 );
178 if(M00 <= 0 ) continue;
179 X = cvGetSpatialMoment( &m, 1, 0 )/M00;
180 Y = cvGetSpatialMoment( &m, 0, 1 )/M00;
181 XX = (cvGetSpatialMoment( &m, 2, 0 )/M00) - X*X;
182 YY = (cvGetSpatialMoment( &m, 0, 2 )/M00) - Y*Y;
183 NewBlob = cvBlob(r.x+(float)X,r.y+(float)Y,(float)(4*sqrt(XX)),(float)(4*sqrt(YY)));
184 m_BlobListNew.AddBlob(&NewBlob);
186 cvReleaseImage(&pBin);
189 for(i=m_BlobList.GetBlobNum();i>0;--i)
190 {/* predict new blob position */
192 DefBlobTrackerCR* pBT = (DefBlobTrackerCR*)m_BlobList.GetBlob(i-1);
193 /*update predictor */
194 pBT->pPredictor->Update(&(pBT->blob));
195 pB = pBT->pPredictor->Predict();
198 pBT->BlobPredict = pB[0];
200 pBT->BlobPrev = pBT->blob;
201 }/* predict new blob position */
204 if(m_BlobList.GetBlobNum()>0 && m_BlobListNew.GetBlobNum()>0)
205 {/* resolve new blob to old */
207 int NOld = m_BlobList.GetBlobNum();
208 int NNew = m_BlobListNew.GetBlobNum();
211 {/* set 0 collision and clear all hyp */
212 DefBlobTrackerCR* pF = (DefBlobTrackerCR*)m_BlobList.GetBlob(i);
214 pF->pBlobHyp->Clear();
215 }/* set 0 collision */
217 /* create correspondance records */
220 CvBlob* pB1 = m_BlobListNew.GetBlob(j);
221 DefBlobTrackerCR* pFLast = NULL;
224 {/* check intersection */
225 int Intersection = 0;
226 DefBlobTrackerCR* pF = (DefBlobTrackerCR*)m_BlobList.GetBlob(i);
227 CvBlob* pB2 = &(pF->BlobPredict);
228 if( fabs(pB1->x-pB2->x)<0.5*(pB1->w+pB2->w) &&
229 fabs(pB1->y-pB2->y)<0.5*(pB1->h+pB2->h) ) Intersection = 1;
234 pF->Collision = pFLast->Collision = 1;
237 pF->pBlobHyp->AddBlob(pB1);
239 }/* check intersection */
240 }/* check next new blob */
241 }/* resolve new blob to old */
243 for(i=m_BlobList.GetBlobNum();i>0;--i)
244 {/* track each blob */
245 CvBlob* pB = m_BlobList.GetBlob(i-1);
246 DefBlobTrackerCR* pBT = (DefBlobTrackerCR*)pB;
247 int BlobID = CV_BLOB_ID(pB);
248 //CvBlob* pBBest = NULL;
249 //double DistBest = -1;
254 pBT->pResolver->SetCollision(pBT->Collision);
258 {/* tracking in collision */
261 pB[0] = pBT->pResolver->Process(&(pBT->BlobPredict),pImg, pImgFG)[0];
263 }/* tracking in collision */
265 {/* not collision tracking */
266 CvBlob NewCC = pBT->BlobPredict;
267 if(pBT->pBlobHyp->GetBlobNum()==1)
268 {/* one blob to one CC */
269 NewCC = pBT->pBlobHyp->GetBlob(0)[0];
272 {/* one blob several CC */
273 CvBlob* pBBest = NULL;
274 double DistBest = -1;
276 for(j=pBT->pBlobHyp->GetBlobNum();j>0;--j)
278 CvBlob* pBNew = pBT->pBlobHyp->GetBlob(j-1);
280 {/* choose CC by confidence */
281 // double dx = fabs(CV_BLOB_X(pB)-CV_BLOB_X(pBNew));
282 // double dy = fabs(CV_BLOB_Y(pB)-CV_BLOB_Y(pBNew));
283 double C = pBT->pResolver->GetConfidence(pBNew,pImg, pImgFG);
284 if(C > CMax || pBBest == NULL)
291 { /* chose CC by distance */
292 double dx = fabs(CV_BLOB_X(pB)-CV_BLOB_X(pBNew));
293 double dy = fabs(CV_BLOB_Y(pB)-CV_BLOB_Y(pBNew));
294 double Dist = sqrt(dx*dx+dy*dy);
295 if(Dist < DistBest || pBBest == NULL)
304 }/* one blob several CC */
307 pB->w = (m_AlphaSize)*NewCC.w+(1-m_AlphaSize)*pB->w;
308 pB->h = (m_AlphaSize)*NewCC.h+(1-m_AlphaSize)*pB->h;
309 pBT->pResolver->SkipProcess(&(pBT->BlobPredict),pImg, pImgFG);
310 }/* not collision tracking */
312 pBT->pResolver->Update(pB, pImg, pImgFG);
314 CV_BLOB_ID(pB)=BlobID;
316 }/* track next blob */
320 IplImage* pI = cvCloneImage(pImg);
322 for(i=m_BlobListNew.GetBlobNum();i>0;--i)
323 {/* draw each new CC */
324 CvBlob* pB = m_BlobListNew.GetBlob(i-1);
325 CvPoint p = cvPointFrom32f(CV_BLOB_CENTER(pB));
326 int x = cvRound(CV_BLOB_RX(pB)), y = cvRound(CV_BLOB_RY(pB));
327 CvSize s = cvSize(MAX(1,x), MAX(1,y));
333 CV_RGB(255,255,0), 1 );
336 for(i=m_BlobList.GetBlobNum();i>0;--i)
337 {/* draw each new CC */
338 DefBlobTrackerCR* pF = (DefBlobTrackerCR*)m_BlobList.GetBlob(i-1);
339 CvBlob* pB = &(pF->BlobPredict);
340 CvPoint p = cvPointFrom32f(CV_BLOB_CENTER(pB));
341 int x = cvRound(CV_BLOB_RX(pB)), y = cvRound(CV_BLOB_RY(pB));
342 CvSize s = cvSize(MAX(1,x), MAX(1,y));
347 CV_RGB(0,0,255), 1 );
350 p = cvPointFrom32f(CV_BLOB_CENTER(pB));
351 x = cvRound(CV_BLOB_RX(pB)); y = cvRound(CV_BLOB_RY(pB));
352 s = cvSize(MAX(1,x), MAX(1,y));
357 CV_RGB(0,255,0), 1 );
360 //cvNamedWindow("CCwithCR",0);
361 //cvShowImage("CCwithCR",pI);
366 virtual void SaveState(CvFileStorage* fs)
368 int b,bN = m_BlobList.GetBlobNum();
369 cvWriteInt(fs,"BlobNum",m_BlobList.GetBlobNum());
370 cvStartWriteStruct(fs,"BlobList",CV_NODE_SEQ);
373 DefBlobTrackerCR* pF = (DefBlobTrackerCR*)m_BlobList.GetBlob(b);
374 cvStartWriteStruct(fs,NULL,CV_NODE_MAP);
375 cvWriteInt(fs,"ID",CV_BLOB_ID(pF));
376 cvStartWriteStruct(fs,"Blob",CV_NODE_SEQ|CV_NODE_FLOW);
377 cvWriteRawData(fs,&(pF->blob),1,"ffffi");
378 cvEndWriteStruct(fs);
379 cvStartWriteStruct(fs,"BlobPredict",CV_NODE_SEQ|CV_NODE_FLOW);
380 cvWriteRawData(fs,&(pF->BlobPredict),1,"ffffi");
381 cvEndWriteStruct(fs);
382 cvStartWriteStruct(fs,"BlobPrev",CV_NODE_SEQ|CV_NODE_FLOW);
383 cvWriteRawData(fs,&(pF->BlobPrev),1,"ffffi");
384 cvEndWriteStruct(fs);
385 pF->pBlobHyp->Write(fs,"BlobHyp");
386 cvWriteInt(fs,"Collision",pF->Collision);
388 cvStartWriteStruct(fs,"Predictor",CV_NODE_MAP);
389 pF->pPredictor->SaveState(fs);
390 cvEndWriteStruct(fs);
392 cvStartWriteStruct(fs,"Resolver",CV_NODE_MAP);
393 pF->pResolver->SaveState(fs);
394 cvEndWriteStruct(fs);
395 cvEndWriteStruct(fs);
397 cvEndWriteStruct(fs);
400 virtual void LoadState(CvFileStorage* fs, CvFileNode* node)
402 int b,bN = cvReadIntByName(fs,node,"BlobNum",0);
403 CvFileNode* pBlobListNode = cvGetFileNodeByName(fs,node,"BlobList");
404 if(!CV_NODE_IS_SEQ(pBlobListNode->tag)) return;
405 bN = pBlobListNode->data.seq->total;
408 DefBlobTrackerCR* pF = NULL;
410 CvFileNode* pSeqNode = NULL;
411 CvFileNode* pBlobNode = (CvFileNode*)cvGetSeqElem(pBlobListNode->data.seq,b);
414 Blob.ID = cvReadIntByName(fs,pBlobNode,"ID",0);
416 pSeqNode = cvGetFileNodeByName(fs, pBlobNode, "Blob");
417 if(CV_NODE_IS_SEQ(pSeqNode->tag))
418 cvReadRawData( fs, pSeqNode, &Blob, "ffffi" );
420 AddBlob(&Blob,NULL,NULL);
421 pF = (DefBlobTrackerCR*)m_BlobList.GetBlobByID(Blob.ID);
423 pSeqNode = cvGetFileNodeByName(fs, pBlobNode, "BlobPredict");
424 if(CV_NODE_IS_SEQ(pSeqNode->tag))
425 cvReadRawData( fs, pSeqNode, &pF->BlobPredict, "ffffi" );
426 pSeqNode = cvGetFileNodeByName(fs, pBlobNode, "BlobPrev");
427 if(CV_NODE_IS_SEQ(pSeqNode->tag))
428 cvReadRawData( fs, pSeqNode, &pF->BlobPrev, "ffffi" );
429 pSeqNode = cvGetFileNodeByName(fs, pBlobNode, "BlobHyp");
431 pF->pBlobHyp->Load(fs,pSeqNode);
432 pF->Collision = cvReadIntByName(fs, pBlobNode,"Collision",pF->Collision);
434 pSeqNode = cvGetFileNodeByName(fs, pBlobNode, "Predictor");
436 pF->pPredictor->LoadState(fs,pSeqNode);
437 pSeqNode = cvGetFileNodeByName(fs, pBlobNode, "Resolver");
439 pF->pResolver->LoadState(fs,pSeqNode);
440 }/* read next blob */
441 }/* CCwithCR LoadState */
443 //void SetCollision(int Collision){m_Collision = Collision;};
446 CvBlobTrackerOne* cvCreateBlobTrackerOneMSPF();
447 CvBlobTracker* cvCreateBlobTrackerCCMSPF()
449 return (CvBlobTracker*) new CvBlobTrackerCCCR(cvCreateBlobTrackerOneMSPF,"MSPF");
451 /*============== BLOB TRACKERCC CLASS DECLARATION =============== */