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
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
19 // * Redistribution's of source code must retain the above copyright notice,
20 // this list of conditions and the following disclaimer.
22 // * Redistribution's in binary form must reproduce the above copyright notice,
23 // this list of conditions and the following disclaimer in the documentation
24 // and/or other materials provided with the distribution.
26 // * The name of Intel Corporation may not be used to endorse or promote products
27 // derived from this software without specific prior written permission.
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
44 typedef struct DefTrackPoint
54 DefTrackRec(int id = 0,int BlobSize = sizeof(DefTrackPoint))
57 m_pMem = cvCreateMemStorage();
58 m_pSeq = cvCreateSeq(0,sizeof(CvSeq),BlobSize,m_pMem);
62 cvReleaseMemStorage(&m_pMem);
64 inline DefTrackPoint* GetPoint(int PointIndex)
66 return (DefTrackPoint*)cvGetSeqElem(m_pSeq,PointIndex);
68 inline void DelPoint(int PointIndex)
70 cvSeqRemove(m_pSeq,PointIndex);
76 inline void AddPoint(float x, float y, float r)
78 DefTrackPoint p = {x,y,r,0};
79 int Num = GetPointNum();
82 DefTrackPoint* pPrev = GetPoint(Num-1);
84 float dx = x-pPrev->x;
85 float dy = y-pPrev->y;
86 p.vx = Alpha*dx+(1-Alpha)*pPrev->vx;
87 p.vy = Alpha*dy+(1-Alpha)*pPrev->vy;
88 p.v = Alpha*dx+(1-Alpha)*pPrev->v;
92 inline void AddPoint(DefTrackPoint* pB)
93 {/* add point and recal last velocities */
100 for(i=MAX(0,Num-wnd-1);i<Num;++i)
101 {/* next updating point */
102 DefTrackPoint* p = GetPoint(i);
111 float dt = (float)(j1-j0);
112 DefTrackPoint* p0 = GetPoint(j0);
113 DefTrackPoint* p1 = GetPoint(j1);
114 p->vx = (p1->x - p0->x) / dt;
115 p->vy = (p1->y - p0->y) / dt;
116 p->v = (float)sqrt(p->vx*p->vx+p->vy*p->vy);
118 }/* next updating point */
124 printf("Blob %d: ",ID);
125 for(i=0;i<GetPointNum();++i)
127 DefTrackPoint* p = GetPoint(i);
128 printf(",(%.2f,%.2f,%f.2)",p->vx,p->vy,p->v);
134 inline int GetPointNum()
136 return m_pSeq->total;
139 CvMemStorage* m_pMem;
143 /* fill array pIdxPairs by pair of index of correspondent blobs */
144 /* return number of pairs */
145 /* pIdxPairs must have size not less that 2*(pSeqNum+pSeqTNum) */
146 /* pTmp is pointer to memory which size is pSeqNum*pSeqTNum*16 */
147 typedef struct DefMatch
149 int Idx; /* prev best blob index */
150 int IdxT; /* prev best template blob index */
151 double D; /* blob to blob distance sum */
153 static int cvTrackMatch(DefTrackRec* pSeq, int MaxLen, DefTrackRec* pSeqT, int* pIdxPairs, void* pTmp)
156 DefMatch* pMT = (DefMatch*)pTmp;
157 int Num = pSeq->GetPointNum();
158 int NumT = pSeqT->GetPointNum();
160 int i0=0; /* last point in the track sequence */
162 if(MaxLen > 0 && Num > MaxLen)
163 {/* set new point seq len and new last point in this seq */
165 i0 = pSeq->GetPointNum() - Num;
169 { /* for eacj point row */
170 for(it=0;it<NumT;++it)
171 { /* for each point templet column */
172 DefTrackPoint* pB = pSeq->GetPoint(i+i0);
173 DefTrackPoint* pBT = pSeqT->GetPoint(it);
174 DefMatch* pMT_cur = pMT + i*NumT + it;
175 double dx = pB->x-pBT->x;
176 double dy = pB->y-pBT->y;
177 double D = dx*dx+dy*dy;
178 int DI[3][2] = {{-1,-1},{-1,0},{0,-1}};
187 for(iDI=0;iDI<3;++iDI)
189 int i_prev = i+DI[iDI][0];
190 int it_prev = it+DI[iDI][1];
191 if(i_prev >= 0 && it_prev>=0)
193 double D_cur = D+pMT[NumT*i_prev+it_prev].D;
194 if(pMT_cur->D > D_cur || (pMT_cur->Idx<0) )
195 {/* set new best local way */
197 pMT_cur->Idx = i_prev;
198 pMT_cur->IdxT = it_prev;
201 }/* check next direction */
202 }/* fill next colum from table */
205 { /* back tracking */
206 /* find best end in template */
208 DefMatch* pMT_best = pMT + (Num-1)*NumT;
209 i = Num-1; /* set current i to last position */
210 for(it=1;it<NumT;++it)
212 DefMatch* pMT_new = pMT + it + i*NumT;
213 if(pMT_best->D > pMT_new->D)
215 pMT_best->D = pMT_new->D;
218 }/* find best end template point */
220 /* back tracking whole sequence */
221 for(it = it_best;i>=0 && it>=0;)
223 DefMatch* pMT_new = pMT + it + i*NumT;
224 pIdxPairs[2*NumPair] = i+i0;
225 pIdxPairs[2*NumPair+1] = it;
231 }/* end back tracing */
236 typedef struct DefTrackForDist
246 class CvBlobTrackAnalysisTrackDist : public CvBlobTrackAnalysis
248 /*---------------- internal functions --------------------*/
250 char* m_pDebugAVIName; /* for debuf purpose */
251 //CvVideoWriter* m_pDebugAVI; /* for debuf purpose */
252 IplImage* m_pDebugImg; /* for debuf purpose */
254 char m_DataFileName[1024];
256 CvBlobSeq m_TrackDataBase;
261 float m_AbnormalThreshold;
262 float m_PosThreshold;
263 float m_VelThreshold;
264 inline void* ReallocTempData(int Size)
266 if(Size <= m_TempDataSize && m_pTempData) return m_pTempData;
267 cvFree(&m_pTempData);
269 m_pTempData = cvAlloc(Size);
270 if(m_pTempData) m_TempDataSize = Size;
272 }/* ReallocTempData */
274 CvBlobTrackAnalysisTrackDist():m_Tracks(sizeof(DefTrackForDist)),m_TrackDataBase(sizeof(DefTrackForDist))
282 m_pDebugAVIName = NULL;
283 AddParam("DebugAVI",&m_pDebugAVIName);
284 CommentParam("DebugAVI","Name of AVI file to save images from debug window");
287 AddParam("TraceLen",&m_TraceLen);
288 CommentParam("TraceLen","Length (in frames) of trajectory part that is used for comparison");
290 m_AbnormalThreshold = 0.02f;
291 AddParam("AbnormalThreshold",&m_AbnormalThreshold);
292 CommentParam("AbnormalThreshold","If trajectory is equal with less then <AbnormalThreshold*DataBaseTrackNum> tracks then trajectory is abnormal");
294 m_PosThreshold = 1.25;
295 AddParam("PosThreshold",&m_PosThreshold);
296 CommentParam("PosThreshold","Minimal allowd distance in blob width that is allowed");
298 m_VelThreshold = 0.5;
299 AddParam("VelThreshold",&m_VelThreshold);
300 CommentParam("VelThreshold","Minimal allowed relative difference between blob speed");
303 ~CvBlobTrackAnalysisTrackDist()
306 for(i=m_Tracks.GetBlobNum();i>0;--i)
308 DefTrackForDist* pF = (DefTrackForDist*)m_Tracks.GetBlob(i-1);
311 if(m_pDebugImg) cvReleaseImage(&m_pDebugImg);
312 //if(m_pDebugAVI) cvReleaseVideoWriter(&m_pDebugAVI);
315 /*----------------- interface --------------------*/
316 virtual void AddBlob(CvBlob* pBlob)
318 DefTrackForDist* pF = (DefTrackForDist*)m_Tracks.GetBlobByID(CV_BLOB_ID(pBlob));
320 { /* create new TRack record */
324 F.LastFrame = m_Frame;
325 F.pTrack = new DefTrackRec(CV_BLOB_ID(pBlob));
326 m_Tracks.AddBlob((CvBlob*)&F);
327 pF = (DefTrackForDist*)m_Tracks.GetBlobByID(CV_BLOB_ID(pBlob));
332 pF->pTrack->AddPoint(pBlob->x,pBlob->y,pBlob->w*0.5f);
334 pF->LastFrame = m_Frame;
336 virtual void Process(IplImage* pImg, IplImage* /*pFG*/)
339 double MinTv = pImg->width/1440.0; /* minimal threshold for speed difference */
340 double MinTv2 = MinTv*MinTv;
341 for(i=m_Tracks.GetBlobNum();i>0;--i)
343 DefTrackForDist* pF = (DefTrackForDist*)m_Tracks.GetBlob(i-1);
345 if(pF->LastFrame == m_Frame || pF->LastFrame+1 == m_Frame)
346 {/* process one blob trajectory */
349 for(it=m_TrackDataBase.GetBlobNum();it>0;--it)
350 {/* check template */
351 DefTrackForDist* pFT = (DefTrackForDist*)m_TrackDataBase.GetBlob(it-1);
352 int Num = pF->pTrack->GetPointNum();
353 int NumT = pFT->pTrack->GetPointNum();
354 int* pPairIdx = (int*)ReallocTempData(sizeof(int)*2*(Num+NumT)+sizeof(DefMatch)*Num*NumT);
355 void* pTmpData = pPairIdx+2*(Num+NumT);
365 PairNum = cvTrackMatch( pF->pTrack, m_TraceLen, pFT->pTrack, pPairIdx, pTmpData );
366 Equal = MAX(1,cvRound(PairNum*0.1));
368 UseVel = 3*pF->pTrack->GetPointNum() > m_TraceLen;
369 UsePos = 10*pF->pTrack->GetPointNum() > m_TraceLen;
371 { /* check continues */
373 int DI = pPairIdx[0*2+0]-pPairIdx[(PairNum-1)*2+0];
374 int DIt = pPairIdx[0*2+1]-pPairIdx[(PairNum-1)*2+1];
375 if(UseVel && DI != 0)
377 D = (float)(DI-DIt)/(float)DI;
378 if(fabs(D)>m_VelThreshold)Equal=0;
379 if(fabs(D)>m_VelThreshold*0.5)Equal/=2;
381 }/* check continues */
383 for(k=0;Equal>0 && k<PairNum;++k)
384 {/* compare with threshold */
385 int j = pPairIdx[k*2+0];
386 int jt = pPairIdx[k*2+1];
387 DefTrackPoint* pB = pF->pTrack->GetPoint(j);
388 DefTrackPoint* pBT = pFT->pTrack->GetPoint(jt);
389 double dx = pB->x-pBT->x;
390 double dy = pB->y-pBT->y;
391 double dvx = pB->vx - pBT->vx;
392 double dvy = pB->vy - pBT->vy;
393 //double dv = pB->v - pBT->v;
394 double D = dx*dx+dy*dy;
395 double Td = pBT->r*m_PosThreshold;
396 double dv2 = dvx*dvx+dvy*dvy;
397 double Tv2 = (pBT->vx*pBT->vx+pBT->vy*pBT->vy)*m_VelThreshold*m_VelThreshold;
398 double Tvm = pBT->v*m_VelThreshold;
401 if(Tv2 < MinTv2) Tv2 = MinTv2;
402 if(Tvm < MinTv) Tvm = MinTv;
404 /* check trajectory position */
405 if(UsePos && D > Td*Td)
410 /* check trajectory velacity */
411 /* don't consider tails of trajectory becasue its unnstable for velosity calculation */
412 if(UseVel && j>5 && jt>5 && dv2 > Tv2 )
416 }/* compare with threshold */
426 float T = m_TrackDataBase.GetBlobNum() * m_AbnormalThreshold; /* calc threshold */
430 pF->state = (T - NumEq)/(T*0.2f) + 0.5f;
432 if(pF->state<0)pF->state=0;
433 if(pF->state>1)pF->state=1;
435 /*if(0)if(pF->state>0)
437 printf("Abnormal blob(%d) %d < %f, state=%f\n",CV_BLOB_ID(pF),NumEq,T, pF->state);
440 }/* process one blob trajectory */
442 {/* move track to trcaks data base */
443 m_TrackDataBase.AddBlob((CvBlob*)pF);
444 m_Tracks.DelBlob(i-1);
453 if(m_pDebugImg==NULL)
454 m_pDebugImg = cvCloneImage(pImg);
456 cvCopyImage(pImg, m_pDebugImg);
458 for(i=m_TrackDataBase.GetBlobNum();i>0;--i)
459 {/* draw all elements from trackdata base */
461 DefTrackForDist* pF = (DefTrackForDist*)m_TrackDataBase.GetBlob(i-1);
462 CvScalar color = CV_RGB(0,0,0);
463 if(!pF->close) continue;
466 color = CV_RGB(0,0,255);
470 color = CV_RGB(0,0,128);
473 for(j=pF->pTrack->GetPointNum();j>0;j--)
475 DefTrackPoint* pB = pF->pTrack->GetPoint(j-1);
476 int r = 0;//MAX(cvRound(pB->r),1);
477 cvCircle(m_pDebugImg, cvPoint(cvRound(pB->x),cvRound(pB->y)), r, color);
480 }/* draw all elements from trackdata base */
482 for(i=m_Tracks.GetBlobNum();i>0;--i)
483 {/* draw all elements for all trajectories */
484 DefTrackForDist* pF = (DefTrackForDist*)m_Tracks.GetBlob(i-1);
486 int c = cvRound(pF->state*255);
487 CvScalar color = CV_RGB(c,255-c,0);
488 CvPoint p = cvPointFrom32f(CV_BLOB_CENTER(pF));
489 int x = cvRound(CV_BLOB_RX(pF)), y = cvRound(CV_BLOB_RY(pF));
490 CvSize s = cvSize(MAX(1,x), MAX(1,y));
492 cvEllipse( m_pDebugImg,
496 CV_RGB(c,255-c,0), cvRound(1+(0*c)/255) );
498 for(j=pF->pTrack->GetPointNum();j>0;j--)
500 DefTrackPoint* pB = pF->pTrack->GetPoint(j-1);
501 if(pF->pTrack->GetPointNum()-j > m_TraceLen) break;
502 cvCircle(m_pDebugImg, cvPoint(cvRound(pB->x),cvRound(pB->y)), 0, color);
505 }/* draw all elements for all trajectories */
507 //cvNamedWindow("Tracks",0);
508 //cvShowImage("Tracks", m_pDebugImg);
512 if(m_pDebugImg && m_pDebugAVIName)
514 if(m_pDebugAVI==NULL)
515 {/* create avi file for writing */
516 m_pDebugAVI = cvCreateVideoWriter(
518 CV_FOURCC('x','v','i','d'),
520 cvSize(m_pDebugImg->width,m_pDebugImg->height));
521 if(m_pDebugAVI == NULL)
523 printf("WARNING!!! Can not create AVI file %s for writing\n",m_pDebugAVIName);
525 }/* create avi file for writing */
526 if(m_pDebugAVI)cvWriteFrame( m_pDebugAVI, m_pDebugImg );
527 }/* write debug window to AVI file */
531 float GetState(int BlobID)
533 DefTrackForDist* pF = (DefTrackForDist*)m_Tracks.GetBlobByID(BlobID);
534 return pF?pF->state:0.0f;
536 /* return 0 if trajectory is normal
537 return >0 if trajectory abnormal */
538 virtual char* GetStateDesc(int BlobID)
540 if(GetState(BlobID)>0.5) return "abnormal";
543 virtual void SetFileName(char* DataBaseName)
545 m_DataFileName[0] = 0;
548 strncpy(m_DataFileName,DataBaseName,1000);
549 strcat(m_DataFileName, ".yml");
553 virtual void Release(){ delete this; };
559 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisTrackDist()
560 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisTrackDist;}