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 static float CalcAverageMask(CvBlob* pBlob, IplImage* pImgFG )
44 {/* calc summ of mask */
45 double Area, Aver = 0;
49 if(pImgFG==NULL) return 0;
51 r.x = cvRound(pBlob->x - pBlob->w*0.5);
52 r.y = cvRound(pBlob->y - pBlob->h*0.5);
53 r.width = cvRound(pBlob->w);
54 r.height = cvRound(pBlob->h);
55 Area = r.width*r.height;
56 if(r.x<0){r.width += r.x;r.x = 0;}
57 if(r.y<0){r.height += r.y;r.y = 0;}
58 if((r.x+r.width)>=pImgFG->width){r.width=pImgFG->width-r.x-1;}
59 if((r.y+r.height)>=pImgFG->height){r.height=pImgFG->height-r.y-1;}
60 if(r.width>0 && r.height>0)
62 double Sum = cvSum(cvGetSubRect(pImgFG,&mat,r)).val[0]/255.0;
67 }/* calc summ of mask */
70 /*============== BLOB TRACKERCC CLASS DECLARATION =============== */
71 typedef struct DefBlobTracker
74 CvBlobTrackPredictor* pPredictor;
80 void cvFindBlobsByCCClasters(IplImage* pFG, CvBlobSeq* pBlobs, CvMemStorage* storage);
82 class CvBlobTrackerCC : public CvBlobTracker
90 char* m_ConfidenceTypeStr;
92 CvBlobSeq m_BlobListNew;
99 CvBlobTrackerCC():m_BlobList(sizeof(DefBlobTracker))
103 m_pMem = cvCreateMemStorage();
104 m_Collision = 1; /* if 1 then collistion will be detected and processed */
105 AddParam("Collision",&m_Collision);
106 CommentParam("Collision", "if 1 then collision cases are processed in special way");
109 AddParam("AlphaSize",&m_AlphaSize);
110 CommentParam("AlphaSize", "Size update speed (0..1)");
113 AddParam("AlphaPos",&m_AlphaPos);
114 CommentParam("AlphaPos", "Pos update speed (0..1)");
117 AddParam("Alpha", &m_Alpha);
118 CommentParam("Alpha","Coefficient for model histogramm updating (0 - hist is not upated)");
121 m_ConfidenceTypeStr = "NearestBlob";
122 AddParam("ConfidenceType", &m_ConfidenceTypeStr);
123 CommentParam("ConfidenceType","Type of calculated Confidence (NearestBlob, AverFG, BC)");
129 if(m_pMem)cvReleaseMemStorage(&m_pMem);
133 virtual int GetBlobNum() {return m_BlobList.GetBlobNum();};
134 virtual CvBlob* GetBlob(int BlobIndex){return m_BlobList.GetBlob(BlobIndex);};
135 virtual void SetBlob(int BlobIndex, CvBlob* pBlob)
137 CvBlob* pB = m_BlobList.GetBlob(BlobIndex);
138 if(pB) pB[0] = pBlob[0];
140 virtual CvBlob* GetBlobByID(int BlobID){return m_BlobList.GetBlobByID(BlobID);};
141 virtual void DelBlob(int BlobIndex)
143 DefBlobTracker* pBT = (DefBlobTracker*)m_BlobList.GetBlob(BlobIndex);
144 if(pBT==NULL) return;
147 pBT->pPredictor->Release();
151 printf("WARNING!!! Invalid Predictor in CC tracker");
153 delete pBT->pBlobHyp;
154 m_BlobList.DelBlob(BlobIndex);
157 virtual void DelBlobByID(int BlobID)
159 DefBlobTracker* pBT = (DefBlobTracker*)m_BlobList.GetBlobByID(BlobID);
160 pBT->pPredictor->Release();
161 delete pBT->pBlobHyp;
162 m_BlobList.DelBlobByID(BlobID);
165 virtual void Release(){delete this;};
167 /* Add new blob to track it and assign to this blob personal ID */
168 /* pBlob - pinter to structure with blob parameters (ID is ignored)*/
169 /* pImg - current image */
170 /* pImgFG - current foreground mask */
171 /* return pointer to new added blob */
172 virtual CvBlob* AddBlob(CvBlob* pB, IplImage* /*pImg*/, IplImage* pImgFG = NULL )
174 assert(pImgFG); /* this tracker use only foreground mask */
177 // CV_BLOB_ID(&NewB) = m_LastID;
178 NewB.pBlobHyp = new CvBlobSeq;
179 NewB.pPredictor = cvCreateModuleBlobTrackPredictKalman(); /* module for predict position */
180 NewB.pPredictor->Update(pB);
181 NewB.AverFG = pImgFG?CalcAverageMask(pB,pImgFG):0;
182 m_BlobList.AddBlob((CvBlob*)&NewB);
183 return m_BlobList.GetBlob(m_BlobList.GetBlobNum()-1);
185 virtual void Process(IplImage* pImg, IplImage* pImgFG = NULL)
194 if(m_BlobList.GetBlobNum() <= 0 ) return;
196 /* clear blob list for new blobs */
197 m_BlobListNew.Clear();
200 cvClearMemStorage(m_pMem);
206 {// by contur clastring
207 cvFindBlobsByCCClasters(pImgFG, &m_BlobListNew, m_pMem);
210 {/* one contour - one blob */
211 IplImage* pBin = cvCloneImage(pImgFG);
213 cvThreshold(pBin,pBin,128,255,CV_THRESH_BINARY);
214 cvFindContours(pBin, m_pMem, &cnts, sizeof(CvContour), CV_RETR_EXTERNAL);
215 /* process each contours*/
216 for(cnt = cnts;cnt;cnt=cnt->h_next)
220 double M00,X,Y,XX,YY;
222 CvRect r = ((CvContour*)cnt)->rect;
224 if(r.height < 3 || r.width < 3) continue;
225 cvMoments( cvGetSubRect(pImgFG,&mat,r), &m, 0 );
226 M00 = cvGetSpatialMoment( &m, 0, 0 );
227 if(M00 <= 0 ) continue;
228 X = cvGetSpatialMoment( &m, 1, 0 )/M00;
229 Y = cvGetSpatialMoment( &m, 0, 1 )/M00;
230 XX = (cvGetSpatialMoment( &m, 2, 0 )/M00) - X*X;
231 YY = (cvGetSpatialMoment( &m, 0, 2 )/M00) - Y*Y;
232 NewBlob = cvBlob(r.x+(float)X,r.y+(float)Y,(float)(4*sqrt(XX)),(float)(4*sqrt(YY)));
233 m_BlobListNew.AddBlob(&NewBlob);
235 cvReleaseImage(&pBin);
238 for(i=m_BlobList.GetBlobNum();i>0;--i)
239 {/* predict new blob position */
241 DefBlobTracker* pBT = (DefBlobTracker*)m_BlobList.GetBlob(i-1);
243 /* update predictor by previouse value of blob*/
244 pBT->pPredictor->Update(&(pBT->blob));
246 /* predict current position */
247 pB = pBT->pPredictor->Predict();
251 pBT->BlobPredict = pB[0];
255 pBT->BlobPredict = pBT->blob;
257 }/* predict new blob position */
260 for(i=m_BlobList.GetBlobNum();i>0;--i)
261 {/* predict collision */
264 DefBlobTracker* pF = (DefBlobTracker*)m_BlobList.GetBlob(i-1);
265 for(j=m_BlobList.GetBlobNum();j>0;--j)
266 {/* predict collision */
269 DefBlobTracker* pF2 = (DefBlobTracker*)m_BlobList.GetBlob(j-1);
271 pB1 = &pF->BlobPredict;
272 pB2 = &pF2->BlobPredict;
273 if( fabs(pB1->x-pB2->x)<0.6*(pB1->w+pB2->w) &&
274 fabs(pB1->y-pB2->y)<0.6*(pB1->h+pB2->h) ) Collision = 1;
277 if( fabs(pB1->x-pB2->x)<0.6*(pB1->w+pB2->w) &&
278 fabs(pB1->y-pB2->y)<0.6*(pB1->h+pB2->h) ) Collision = 1;
280 }/* check next blob to cross current*/
281 pF->Collision = Collision;
282 }/* predict collision */
284 for(i=m_BlobList.GetBlobNum();i>0;--i)
285 {/* find a neighbour on cur frame for each blob from prev frame */
286 CvBlob* pB = m_BlobList.GetBlob(i-1);
287 DefBlobTracker* pBT = (DefBlobTracker*)pB;
288 //int BlobID = CV_BLOB_ID(pB);
289 //CvBlob* pBBest = NULL;
290 //double DistBest = -1;
293 if(pBT->pBlobHyp->GetBlobNum()>0)
294 {/* track all hypothesis */
295 int h,hN = pBT->pBlobHyp->GetBlobNum();
298 int j, jN = m_BlobListNew.GetBlobNum();
299 CvBlob* pB = pBT->pBlobHyp->GetBlob(h);
300 int BlobID = CV_BLOB_ID(pB);
301 CvBlob* pBBest = NULL;
302 double DistBest = -1;
306 CvBlob* pBNew = m_BlobListNew.GetBlob(j);
307 double dx = fabs(CV_BLOB_X(pB)-CV_BLOB_X(pBNew));
308 double dy = fabs(CV_BLOB_Y(pB)-CV_BLOB_Y(pBNew));
309 if(dx > 2*CV_BLOB_WX(pB) || dy > 2*CV_BLOB_WY(pB)) continue;
311 Dist = sqrt(dx*dx+dy*dy);
312 if(Dist < DistBest || pBBest == NULL)
321 CV_BLOB_ID(pB) = BlobID;
324 { /* delete this hypothesis */
325 pBT->pBlobHyp->DelBlob(h);
330 }/* track all hypothesis */
331 }/* track next blob */
337 virtual void ProcessBlob(int BlobIndex, CvBlob* pBlob, IplImage* /*pImg*/, IplImage* /*pImgFG*/ = NULL)
340 CvBlob* pB = m_BlobList.GetBlob(BlobIndex);
341 DefBlobTracker* pBT = (DefBlobTracker*)pB;
342 //CvBlob* pBBest = NULL;
343 //double DistBest = -1;
350 if(m_Collision && pBT->Collision)
351 {/* tracking in collision */
352 pB[0]=pBT->BlobPredict;
353 CV_BLOB_ID(pB)=BlobID;
354 }/* tracking in collision */
356 {/* not collision tracking */
357 CvBlob* pBBest = GetNearestBlob(pB);
360 float w = pBlob->w*(1-m_AlphaSize)+m_AlphaSize*pBBest->w;
361 float h = pBlob->h*(1-m_AlphaSize)+m_AlphaSize*pBBest->h;
362 float x = pBlob->x*(1-m_AlphaPos)+m_AlphaPos*pBBest->x;
363 float y = pBlob->y*(1-m_AlphaPos)+m_AlphaPos*pBBest->y;
368 CV_BLOB_ID(pB) = BlobID;
370 }/* not collision tracking */
376 virtual double GetConfidence(int BlobIndex, CvBlob* pBlob, IplImage* /*pImg*/, IplImage* pImgFG = NULL)
378 /* define koefficients in exp by exp(-XT*K)=VT */
379 static double _KS = -log(0.1)/pow(0.5,2); /* XT = 1, VT = 0.1 - when size is Larger in 2 times Confidence is smoller in 10 times */
380 static double _KP = -log(0.1)/pow(m_pImg->width*0.02,2); /* XT = 0.02*ImgWidth, VT = 0.1*/
381 DefBlobTracker* pBT = (DefBlobTracker*)m_BlobList.GetBlob(BlobIndex);
385 CvBlob* pBC = GetNearestBlob(pBlob);
386 if(pBC == NULL ) return 0;
388 dx = pBC->x-pBlob->x;
389 dy = pBC->y-pBlob->y;
390 dw = (pBC->w-pBlob->w)/pBC->w;
391 dh = (pBC->h-pBlob->h)/pBC->h;
397 { /* Confidence for size by nearest blob */
401 if(m_ConfidenceType==0 && !pBT->Collision)
402 { /* confinence by nearest blob */
406 if(m_ConfidenceType==1 && pBT->AverFG>0)
407 {/* calc summ of mask */
408 float Aver = CalcAverageMask(pBlob, pImgFG );
409 if(Aver < pBT->AverFG)
411 float diff = 1+0.9f*(Aver-pBT->AverFG)/pBT->AverFG;
412 if(diff < 0.1f) diff = 0.1f;
415 }/* calc summ of mask */
417 if(m_ConfidenceType==2)
420 float Aver = CalcAverageMask(pBlob, pImgFG );
421 double B = sqrt(Aver*pBT->AverFG)+sqrt((1-Aver)*(1-pBT->AverFG));
423 W *= exp((B-1)/(2*S));
424 }/* calc summ of mask */
428 virtual void UpdateBlob(int BlobIndex, CvBlob* /*pBlob*/, IplImage* /*pImg*/, IplImage* pImgFG = NULL)
430 DefBlobTracker* pBT = (DefBlobTracker*)m_BlobList.GetBlob(BlobIndex);
432 if(pImgFG==NULL || pBT==NULL) return;
436 //pBT->AverFG = pBT->AverFG * (1-m_Alpha) + m_Alpha * CalcAverageMask(pBlob,pImgFG);
440 virtual void ParamUpdate()
442 char* pCT[3] = {"NearestBlob","AverFG","BC"};
445 CvBlobTracker::ParamUpdate();
449 if(cv_stricmp(m_ConfidenceTypeStr,pCT[i])==0)
451 m_ConfidenceType = i;
454 SetParamStr("ConfidenceType",pCT[m_ConfidenceType]);
456 /* =============== MULTI HYPOTHESIS INTERFACE ================== */
457 /* return number of position hyposetis of currently tracked blob */
458 virtual int GetBlobHypNum(int BlobIdx)
460 DefBlobTracker* pBT = (DefBlobTracker*)m_BlobList.GetBlob(BlobIdx);
461 assert(pBT->pBlobHyp);
462 return pBT->pBlobHyp->GetBlobNum();
463 };/* CvBlobtrackerList::GetBlobHypNum() */
465 /* return pointer to specified blob hypothesis by index blob */
466 virtual CvBlob* GetBlobHyp(int BlobIndex, int hypothesis)
468 DefBlobTracker* pBT = (DefBlobTracker*)m_BlobList.GetBlob(BlobIndex);
469 assert(pBT->pBlobHyp);
470 return pBT->pBlobHyp->GetBlob(hypothesis);
471 };/* CvBlobtrackerList::GetBlobHyp() */
472 /* Set new parameters for specified (by index) blob hyp (can be called several times for each hyp )*/
473 virtual void SetBlobHyp(int BlobIndex, CvBlob* pBlob)
476 {/* clear all hypothesis */
477 int b, bN = m_BlobList.GetBlobNum();
480 DefBlobTracker* pBT = (DefBlobTracker*)m_BlobList.GetBlob(b);
481 assert(pBT->pBlobHyp);
482 pBT->pBlobHyp->Clear();
486 {/* add hypothesis */
487 DefBlobTracker* pBT = (DefBlobTracker*)m_BlobList.GetBlob(BlobIndex);
488 assert(pBT->pBlobHyp);
489 pBT->pBlobHyp->AddBlob(pBlob);
494 CvBlob* GetNearestBlob(CvBlob* pB)
496 //DefBlobTracker* pBT = (DefBlobTracker*)pB;
497 CvBlob* pBBest = NULL;
498 double DistBest = -1;
501 if(pB==NULL) return NULL;
505 for(j=m_BlobListNew.GetBlobNum();j>0;--j)
508 CvBlob* pBNew = m_BlobListNew.GetBlob(j-1);
509 double dx = fabs(CV_BLOB_X(pB)-CV_BLOB_X(pBNew));
510 double dy = fabs(CV_BLOB_Y(pB)-CV_BLOB_Y(pBNew));
511 if(dx > 2*CV_BLOB_WX(pB) || dy > 2*CV_BLOB_WY(pB)) continue;
513 Dist = sqrt(dx*dx+dy*dy);
514 if(Dist < DistBest || pBBest == NULL)
521 }; /* GetNearestBlob */
525 CvBlobTracker* cvCreateBlobTrackerCC()
527 return (CvBlobTracker*) new CvBlobTrackerCC;
529 /*============== BLOB TRACKERCC CLASS DECLARATION =============== */