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.
47 typedef struct DefBlobFVN
50 CvBlob BlobSeq[BLOB_NUM];
56 class CvBlobTrackFVGenN: public CvBlobTrackFVGen
62 float m_FVMax[MAX_FV_SIZE];
63 float m_FVMin[MAX_FV_SIZE];
64 float m_FVVar[MAX_FV_SIZE];
66 CvBlob m_BlobSeq[BLOB_NUM];
75 cvClearMemStorage(m_pMem);
76 m_pFVSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(float)*(m_Dim+1), m_pMem);
81 CvBlobTrackFVGenN(int dim = 2 ):m_BlobList(sizeof(DefBlobFVN))
84 assert(dim <= MAX_FV_SIZE);
86 for(i=0; i<m_Dim; ++i)
94 m_pMem = cvCreateMemStorage();
100 if(m_pMem)cvReleaseMemStorage(&m_pMem);
103 void AddBlob(CvBlob* pBlob)
105 float FV[MAX_FV_SIZE+1];
107 DefBlobFVN* pFVBlob = (DefBlobFVN*)m_BlobList.GetBlobByID(CV_BLOB_ID(pBlob));
109 if(!m_ClearFlag) Clear();
114 BlobNew.blob = pBlob[0];
115 BlobNew.LastFrame = m_Frame;
117 BlobNew.FrameNum = 0;
118 m_BlobList.AddBlob((CvBlob*)&BlobNew);
119 pFVBlob = (DefBlobFVN*)m_BlobList.GetBlobByID(CV_BLOB_ID(pBlob));
120 } /* Add new record if necessary. */
122 pFVBlob->blob = pBlob[0];
125 for(i=(BLOB_NUM-1); i>0; --i)
127 pFVBlob->BlobSeq[i] = pFVBlob->BlobSeq[i-1];
130 pFVBlob->BlobSeq[0] = pBlob[0];
133 { /* Calculate FV position: */
134 FV[0] = CV_BLOB_X(pBlob);
135 FV[1] = CV_BLOB_Y(pBlob);
139 { /* Add new FV if position is enough: */
140 *(int*)(FV+m_Dim) = CV_BLOB_ID(pBlob);
141 cvSeqPush( m_pFVSeq, FV );
143 else if(pFVBlob->FrameNum > BLOB_NUM)
144 { /* Calculate velocity for more complex FV: */
147 { /* Average velocity: */
148 CvBlob* pBlobSeq = pFVBlob->BlobSeq;
150 for(i=1;i<BLOB_NUM;++i)
152 AverVx += CV_BLOB_X(pBlobSeq+i-1)-CV_BLOB_X(pBlobSeq+i);
153 AverVy += CV_BLOB_Y(pBlobSeq+i-1)-CV_BLOB_Y(pBlobSeq+i);
155 AverVx /= BLOB_NUM-1;
156 AverVy /= BLOB_NUM-1;
163 { /* State duration: */
164 float T = (CV_BLOB_WX(pBlob)+CV_BLOB_WY(pBlob))*0.01f;
166 if( fabs(AverVx) < T && fabs(AverVy) < T)
170 FV[4] = (float)pFVBlob->state;
171 } /* State duration. */
174 *(int*)(FV+m_Dim) = CV_BLOB_ID(pBlob);
175 cvSeqPush( m_pFVSeq, FV );
177 } /* If velocity is calculated. */
180 pFVBlob->LastFrame = m_Frame;
183 void Process(IplImage* pImg, IplImage* /*pFG*/)
186 if(!m_ClearFlag) Clear();
187 for(i=m_BlobList.GetBlobNum(); i>0; --i)
188 { /* Delete unused blob: */
189 DefBlobFVN* pFVBlob = (DefBlobFVN*)m_BlobList.GetBlob(i-1);
190 if(pFVBlob->LastFrame < m_Frame)
192 m_BlobList.DelBlob(i-1);
194 } /* Check next blob in list. */
198 m_FVMax[0] = (float)(pImg->width-1);
199 m_FVMax[1] = (float)(pImg->height-1);
200 m_FVVar[0] = m_FVMax[0]*0.01f;
201 m_FVVar[1] = m_FVMax[1]*0.01f;
202 m_FVVar[2] = (float)(pImg->width-1)/1440.0f;
203 m_FVMax[2] = (float)(pImg->width-1)*0.02f;
204 m_FVMin[2] = -m_FVMax[2];
205 m_FVVar[3] = (float)(pImg->width-1)/1440.0f;
206 m_FVMax[3] = (float)(pImg->height-1)*0.02f;
207 m_FVMin[3] = -m_FVMax[3];
208 m_FVMax[4] = 25*32.0f; /* max state is 32 sec */
215 virtual void Release(){delete this;};
216 virtual int GetFVSize(){return m_Dim;};
217 virtual int GetFVNum()
219 return m_pFVSeq->total;
222 virtual float* GetFV(int index, int* pFVID)
224 float* pFV = (float*)cvGetSeqElem( m_pFVSeq, index );
225 if(pFVID)pFVID[0] = *(int*)(pFV+m_Dim);
228 virtual float* GetFVMin(){return m_FVMin;}; /* returned pointer to array of minimal values of FV, if return 0 then FVrange is not exist */
229 virtual float* GetFVMax(){return m_FVMax;}; /* returned pointer to array of maximal values of FV, if return 0 then FVrange is not exist */
230 virtual float* GetFVVar(){return m_FVVar;}; /* returned pointer to array of maximal values of FV, if return 0 then FVrange is not exist */
231 };/* CvBlobTrackFVGenN */
233 CvBlobTrackFVGen* cvCreateFVGenP(){return (CvBlobTrackFVGen*)new CvBlobTrackFVGenN(2);}
234 CvBlobTrackFVGen* cvCreateFVGenPV(){return (CvBlobTrackFVGen*)new CvBlobTrackFVGenN(4);}
235 CvBlobTrackFVGen* cvCreateFVGenPVS(){return (CvBlobTrackFVGen*)new CvBlobTrackFVGenN(5);}
238 #define MAX_FV_SIZE 4
239 class CvBlobTrackFVGenSS: public CvBlobTrackFVGen
242 CvBlobSeq m_BlobList;
243 CvMemStorage* m_pMem;
245 float m_FVMax[MAX_FV_SIZE];
246 float m_FVMin[MAX_FV_SIZE];
247 float m_FVVar[MAX_FV_SIZE];
249 CvBlob m_BlobSeq[BLOB_NUM];
256 cvClearMemStorage(m_pMem);
257 m_pFVSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(float)*(m_Dim+1), m_pMem);
261 CvBlobTrackFVGenSS(int dim = 2 ):m_BlobList(sizeof(DefBlobFVN))
264 assert(dim <= MAX_FV_SIZE);
274 m_pMem = cvCreateMemStorage();
277 ~CvBlobTrackFVGenSS()
279 if(m_pMem)cvReleaseMemStorage(&m_pMem);
282 void AddBlob(CvBlob* pBlob)
284 //float FV[MAX_FV_SIZE+1];
286 DefBlobFVN* pFVBlob = (DefBlobFVN*)m_BlobList.GetBlobByID(CV_BLOB_ID(pBlob));
288 if(!m_ClearFlag) Clear();
293 BlobNew.blob = pBlob[0];
294 BlobNew.LastFrame = m_Frame;
296 BlobNew.FrameNum = 0;
297 m_BlobList.AddBlob((CvBlob*)&BlobNew);
298 pFVBlob = (DefBlobFVN*)m_BlobList.GetBlobByID(CV_BLOB_ID(pBlob));
299 } /* Add new record if necessary. */
302 for(i=(BLOB_NUM-1); i>0; --i)
304 pFVBlob->BlobSeq[i] = pFVBlob->BlobSeq[i-1];
307 pFVBlob->BlobSeq[0] = pBlob[0];
309 if(pFVBlob->FrameNum > BLOB_NUM)
310 { /* Average velocity: */
311 CvBlob* pBlobSeq = pFVBlob->BlobSeq;
312 float T = (CV_BLOB_WX(pBlob)+CV_BLOB_WY(pBlob))*0.01f;
316 for(i=1; i<BLOB_NUM; ++i)
318 AverVx += CV_BLOB_X(pBlobSeq+i-1)-CV_BLOB_X(pBlobSeq+i);
319 AverVy += CV_BLOB_Y(pBlobSeq+i-1)-CV_BLOB_Y(pBlobSeq+i);
321 AverVx /= BLOB_NUM-1;
322 AverVy /= BLOB_NUM-1;
324 if( fabs(AverVx) < T && fabs(AverVy) < T)
330 if(pFVBlob->state == 5)
331 { /* Object is stopped: */
332 float FV[MAX_FV_SIZE];
333 FV[0] = pFVBlob->blob.x;
334 FV[1] = pFVBlob->blob.y;
335 FV[2] = pFVBlob->BlobSeq[0].x;
336 FV[3] = pFVBlob->BlobSeq[0].y;
337 *(int*)(FV+m_Dim) = CV_BLOB_ID(pBlob);
338 cvSeqPush( m_pFVSeq, FV );
339 } /* Object is stopped. */
342 pFVBlob->LastFrame = m_Frame;
344 void Process(IplImage* pImg, IplImage* /*pFG*/)
348 if(!m_ClearFlag) Clear();
350 for(i=m_BlobList.GetBlobNum();i>0;--i)
351 { /* Delete unused blob: */
352 DefBlobFVN* pFVBlob = (DefBlobFVN*)m_BlobList.GetBlob(i-1);
353 if(pFVBlob->LastFrame < m_Frame)
355 float FV[MAX_FV_SIZE+1];
356 FV[0] = pFVBlob->blob.x;
357 FV[1] = pFVBlob->blob.y;
358 FV[2] = pFVBlob->BlobSeq[0].x;
359 FV[3] = pFVBlob->BlobSeq[0].y;
360 *(int*)(FV+m_Dim) = CV_BLOB_ID(pFVBlob);
361 cvSeqPush( m_pFVSeq, FV );
362 m_BlobList.DelBlob(i-1);
364 } /* Check next blob in list. */
366 /* Set max min range: */
371 m_FVMax[0] = (float)(pImg->width-1);
372 m_FVMax[1] = (float)(pImg->height-1);
373 m_FVMax[2] = (float)(pImg->width-1);
374 m_FVMax[3] = (float)(pImg->height-1);
375 m_FVVar[0] = m_FVMax[0]*0.01f;
376 m_FVVar[1] = m_FVMax[1]*0.01f;
377 m_FVVar[2] = m_FVMax[2]*0.01f;
378 m_FVVar[3] = m_FVMax[3]*0.01f;
383 virtual void Release(){delete this;};
384 virtual int GetFVSize(){return m_Dim;};
385 virtual int GetFVNum()
387 return m_pFVSeq->total;
390 virtual float* GetFV(int index, int* pFVID)
392 float* pFV = (float*)cvGetSeqElem( m_pFVSeq, index );
393 if(pFVID)pFVID[0] = *(int*)(pFV+m_Dim);
397 virtual float* GetFVMin(){return m_FVMin;}; /* returned pointer to array of minimal values of FV, if return 0 then FVrange is not exist */
398 virtual float* GetFVMax(){return m_FVMax;}; /* returned pointer to array of maximal values of FV, if return 0 then FVrange is not exist */
399 virtual float* GetFVVar(){return m_FVVar;}; /* returned pointer to array of maximal values of FV, if return 0 then FVrange is not exist */
400 };/* CvBlobTrackFVGenSS */
402 CvBlobTrackFVGen* cvCreateFVGenSS(){return (CvBlobTrackFVGen*)new CvBlobTrackFVGenSS;}
404 /*======================= TRAJECTORY ANALYZER MODULES =====================*/
405 /* Trajectory Analyser module */
412 CvSparseMatIterator m_SparseIterator;
413 CvSparseNode* m_pSparseNode;
418 CvSparseMat* m_pSparse;
422 DefMat(int dim = 0, int* sizes = NULL, int type = SPARSE)
424 /* Create sparse or ND matrix but not both: */
425 m_pSparseNode = NULL;
432 if(dim>0 && sizes != 0)
433 Realloc(dim, sizes, type);
437 if(m_pSparse)cvReleaseSparseMat(&m_pSparse);
438 if(m_pND)cvReleaseMatND(&m_pND);
439 if(m_IDXs) cvFree(&m_IDXs);
442 void Realloc(int dim, int* sizes, int type = SPARSE)
444 if(m_pSparse)cvReleaseSparseMat(&m_pSparse);
445 if(m_pND)cvReleaseMatND(&m_pND);
451 for(size=1,i=0;i<dim;++i)
464 } /* Define matrix type. */
468 m_pSparse = cvCreateSparseMat( dim, sizes, CV_32SC1 );
473 m_pND = cvCreateMatND( dim, sizes, CV_32SC1 );
475 m_IDXs = (int*)cvAlloc(sizeof(int)*dim);
481 void Save(char* File)
483 if(m_pSparse)cvSave(File, m_pSparse );
484 if(m_pND)cvSave(File, m_pND );
486 void Save(CvFileStorage* fs, char* name)
490 cvWrite(fs, name, m_pSparse );
494 cvWrite(fs, name, m_pND );
497 void Load(char* File)
499 CvFileStorage* fs = cvOpenFileStorage( File, NULL, CV_STORAGE_READ );
503 if(m_pSparse) cvReleaseSparseMat(&m_pSparse);
504 if(m_pND) cvReleaseMatND(&m_pND);
508 if(ptr && CV_IS_MATND_HDR(ptr)) m_pND = (CvMatND*)ptr;
509 if(ptr && CV_IS_SPARSE_MAT_HDR(ptr)) m_pSparse = (CvSparseMat*)ptr;
510 cvReleaseFileStorage(&fs);
515 void Load(CvFileStorage* fs, CvFileNode* node, char* name)
517 CvFileNode* n = cvGetFileNodeByName(fs,node,name);
518 void* ptr = n?cvRead(fs,n):NULL;
521 if(m_pSparse) cvReleaseSparseMat(&m_pSparse);
522 if(m_pND) cvReleaseMatND(&m_pND);
525 if(CV_IS_MATND_HDR(ptr)) m_pND = (CvMatND*)ptr;
526 if(CV_IS_SPARSE_MAT_HDR(ptr)) m_pSparse = (CvSparseMat*)ptr;
530 printf("WARNING!!! Can't load %s matrix\n",name);
540 { /* Calculate Volume of loaded hist: */
541 CvSparseMatIterator mat_iterator;
542 CvSparseNode* node = cvInitSparseMatIterator( m_pSparse, &mat_iterator );
544 for( ; node != 0; node = cvGetNextSparseNode( &mat_iterator ))
546 int val = *(int*)CV_NODE_VAL( m_pSparse, node ); /* get value of the element
547 (assume that the type is CV_32SC1) */
549 if(m_Max < val)m_Max = val;
551 } /* Calculate Volume of loaded hist. */
554 { /* Calculate Volume of loaded hist: */
558 cvGetMat( m_pND, &mat, NULL, 1 );
560 vol = cvSum(&mat).val[0];
561 m_Volume = cvRound(vol);
562 cvMinMaxLoc( &mat, NULL, &max_val);
563 m_Max = cvRound(max_val);
564 /* MUST BE WRITTEN LATER */
565 } /* Calculate Volume of loaded hist. */
568 int* GetPtr(int* indx)
570 if(m_pSparse) return (int*)cvPtrND( m_pSparse, indx, NULL, 1, NULL);
571 if(m_pND) return (int*)cvPtrND( m_pND, indx, NULL, 1, NULL);
575 int GetVal(int* indx)
577 int* p = GetPtr(indx);
582 int Add(int* indx, int val)
585 int* pVal = GetPtr(indx);
586 if(pVal == NULL) return -1;
590 if(m_Max < NewVal)m_Max = NewVal;
594 void Add(DefMat* pMatAdd)
598 for(Val = pMatAdd->GetNext(&pIDXS, 1 );pIDXS;Val=pMatAdd->GetNext(&pIDXS, 0 ))
604 int SetMax(int* indx, int val)
607 int* pVal = GetPtr(indx);
608 if(pVal == NULL) return -1;
611 m_Volume += val-pVal[0];
615 if(m_Max < NewVal)m_Max = NewVal;
619 int GetNext(int** pIDXS, int init = 0)
625 m_pSparseNode = (init || m_pSparseNode==NULL)?
626 cvInitSparseMatIterator( m_pSparse, &m_SparseIterator ):
627 cvGetNextSparseNode( &m_SparseIterator );
631 int* pVal = (int*)CV_NODE_VAL( m_pSparse, m_pSparseNode );
632 if(pVal)Val = pVal[0];
633 pIDXS[0] = CV_NODE_IDX( m_pSparse, m_pSparseNode );
635 }/* Sparse matrix. */
644 m_IDXs[i] = cvGetDimSize( m_pND, i )-1;
647 Val = GetVal(m_IDXs);
655 m_IDXs[i] = cvGetDimSize( m_pND, i )-1;
664 Val = GetVal(m_IDXs);
669 } /* Sparse matrix. */
678 typedef struct DefTrackFG
681 // CvBlobTrackFVGen* pFVGen;
686 class CvBlobTrackAnalysisHist : public CvBlobTrackAnalysis
688 /*---------------- Internal functions: --------------------*/
692 char* m_SmoothKernel;
693 float m_AbnormalThreshold;
697 char m_DataFileName[1024];
701 int m_HistVolumeSaved;
705 CvBlobSeq m_TrackFGList;
706 //CvBlobTrackFVGen* (*m_CreateFVGen)();
707 CvBlobTrackFVGen* m_pFVGen;
710 if(m_DataFileName[0])
712 m_HistMat.Save(m_DataFileName);
713 m_HistVolumeSaved = m_HistMat.m_Volume;
718 if(m_DataFileName[0])m_HistMat.Load(m_DataFileName);
719 m_HistVolumeSaved = m_HistMat.m_Volume;
723 m_pFVi = (int*)cvAlloc(sizeof(int)*m_Dim);
724 m_pFViVar = (int*)cvAlloc(sizeof(int)*m_Dim);
725 m_pFViVarRes = (int*)cvAlloc(sizeof(int)*m_Dim);
726 m_Sizes = (int*)cvAlloc(sizeof(int)*m_Dim);
728 { /* Create init sparce matrix: */
730 for(i=0;i<m_Dim;++i)m_Sizes[i] = m_BinNum;
731 m_HistMat.Realloc(m_Dim,m_Sizes,SPARSE);
732 m_HistVolumeSaved = 0;
733 } /* Create init sparce matrix. */
739 for(i=m_TrackFGList.GetBlobNum();i>0;--i)
741 //DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlob(i-1);
742 // pF->pFVGen->Release();
743 m_TrackFGList.DelBlob(i-1);
747 cvFree(&m_pFViVarRes);
751 virtual void ParamUpdate()
753 if(m_BinNum != m_BinNumParam)
756 m_BinNum = m_BinNumParam;
761 CvBlobTrackAnalysisHist(CvBlobTrackFVGen* (*createFVGen)()):m_TrackFGList(sizeof(DefTrackFG))
763 m_pFVGen = createFVGen();
764 m_Dim = m_pFVGen->GetFVSize();
769 m_DataFileName[0] = 0;
771 m_AbnormalThreshold = 0.02f;
772 AddParam("AbnormalThreshold",&m_AbnormalThreshold);
773 CommentParam("AbnormalThreshold","If trajectory histogram value is lesst then <AbnormalThreshold*DataBaseTrackNum> then trajectory is abnormal");
776 AddParam("SmoothRadius",&m_SmoothRadius);
777 CommentParam("AbnormalThreshold","Radius (in bins) for histogram smoothing");
779 m_SmoothKernel = "L";
780 AddParam("SmoothKernel",&m_SmoothKernel);
781 CommentParam("SmoothKernel","L - Linear, G - Gaussian");
784 m_BinNumParam = m_BinNum;
785 AddParam("BinNum",&m_BinNumParam);
786 CommentParam("BinNum","Number of bin for each dimention of feature vector");
791 ~CvBlobTrackAnalysisHist()
798 /*----------------- Interface: --------------------*/
799 virtual void AddBlob(CvBlob* pBlob)
801 DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlobByID(CV_BLOB_ID(pBlob));
803 { /* create new filter */
807 F.LastFrame = m_Frame;
808 // F.pFVGen = m_CreateFVGen();
809 F.pHist = new DefMat(m_Dim,m_Sizes,SPARSE);
810 m_TrackFGList.AddBlob((CvBlob*)&F);
811 pF = (DefTrackFG*)m_TrackFGList.GetBlobByID(CV_BLOB_ID(pBlob));
816 pF->LastFrame = m_Frame;
817 m_pFVGen->AddBlob(pBlob);
819 virtual void Process(IplImage* pImg, IplImage* pFG)
822 m_pFVGen->Process(pImg, pFG);
823 int SK = m_SmoothKernel[0];
825 for(i=0; i<m_pFVGen->GetFVNum(); ++i)
828 float* pFV = m_pFVGen->GetFV(i,&BlobID);
829 float* pFVMax = m_pFVGen->GetFVMax();
830 float* pFVMin = m_pFVGen->GetFVMin();
831 DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlobByID(BlobID);
836 pF->LastFrame = m_Frame;
840 for(j=0; j<m_Dim; ++j)
843 float f0 = pFVMin?pFVMin[j]:0;
844 float f1 = pFVMax?pFVMax[j]:1;
846 index = cvRound((m_BinNum-1)*(pFV[j]-f0)/(f1-f0));
848 if(index>=m_BinNum)index=m_BinNum-1;
853 HistVal = m_HistMat.GetVal(m_pFVi);/* get bin value*/
855 { /* Calculate state: */
856 float T = m_HistMat.m_Max*m_AbnormalThreshold; /* calc threshold */
858 if(m_TrackNum>0) T = 256.0f * m_TrackNum*m_AbnormalThreshold;
861 pF->state = (T - HistVal)/(T*0.2f) + 0.5f;
863 if(pF->state<0)pF->state=0;
864 if(pF->state>1)pF->state=1;
867 { /* If it is a new FV then add it to trajectory histogram: */
869 int r = m_SmoothRadius;
871 // printf("BLob %3d NEW FV [", CV_BLOB_ID(pF));
872 // for(i=0;i<m_Dim;++i) printf("%d,", m_pFVi[i]);
875 for(i=0; i<m_Dim; ++i)
886 for(i=0; i<m_Dim; ++i)
888 m_pFViVarRes[i] = m_pFVi[i]+m_pFViVar[i];
889 if(m_pFViVarRes[i]<0) good= 0;
890 if(m_pFViVarRes[i]>=m_BinNum) good= 0;
891 dist += m_pFViVar[i]*m_pFViVar[i];
892 }/* Calculate next dimension. */
894 if(SK=='G' || SK=='g')
896 double dist2 = dist/(r*r);
897 HistAdd = cvRound(256*exp(-dist2)); /* Hist Add for (dist=1) = 25.6*/
899 else if(SK=='L' || SK=='l')
901 dist = (float)(sqrt(dist)/(r+1));
902 HistAdd = cvRound(256*(1-dist));
906 HistAdd = 255; /* Flat smoothing. */
909 if(good && HistAdd>0)
910 { /* Update histogram: */
912 pF->pHist->SetMax(m_pFViVarRes, HistAdd);
913 } /* Update histogram. */
915 for(i=0; i<m_Dim; ++i)
917 if((m_pFViVar[i]++) < r)
920 } /* Increase next dimension variable. */
922 } /* Next variation. */
926 { /* Check all blobs on list: */
928 for(i=m_TrackFGList.GetBlobNum(); i>0; --i)
929 { /* Add histogram and delete blob from list: */
930 DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlob(i-1);
931 if(pF->LastFrame+3 < m_Frame && pF->pHist)
933 m_HistMat.Add(pF->pHist);
936 m_TrackFGList.DelBlob(i-1);
944 { /* Debug output: */
947 IplImage* pI = cvCloneImage(pImg);
951 for(Val = m_HistMat.GetNext(&idxs,1); idxs; Val=m_HistMat.GetNext(&idxs,0))
952 { /* Draw all elements: */
957 if(Val == 0) continue;
959 vf = (float)Val/(m_HistMat.m_Max?m_HistMat.m_Max:1);
960 x = cvRound((float)(pI->width-1)*(float)idxs[0] / (float)m_BinNum);
961 y = cvRound((float)(pI->height-1)*(float)idxs[1] / (float)m_BinNum);
963 cvCircle(pI, cvPoint(x,y), cvRound(vf*pI->height/(m_BinNum*2)),CV_RGB(255,0,0),CV_FILLED);
966 int dx = -2*(idxs[2]-m_BinNum/2);
967 int dy = -2*(idxs[3]-m_BinNum/2);
968 cvLine(pI,cvPoint(x,y),cvPoint(x+dx,y+dy),CV_RGB(0,cvRound(vf*255),1));
971 m_pFVGen->GetFVMax()[0]==m_pFVGen->GetFVMax()[2] &&
972 m_pFVGen->GetFVMax()[1]==m_pFVGen->GetFVMax()[3])
974 int x = cvRound((float)(pI->width-1)*(float)idxs[2] / (float)m_BinNum);
975 int y = cvRound((float)(pI->height-1)*(float)idxs[3] / (float)m_BinNum);
976 cvCircle(pI, cvPoint(x,y), cvRound(vf*pI->height/(m_BinNum*2)),CV_RGB(0,0,255),CV_FILLED);
978 } /* Draw all elements. */
980 for(i=m_TrackFGList.GetBlobNum();i>0;--i)
982 DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlob(i-1);
983 DefMat* pHist = pF?pF->pHist:NULL;
985 if(pHist==NULL) continue;
987 for(Val = pHist->GetNext(&idxs,1);idxs;Val=pHist->GetNext(&idxs,0))
988 { /* Draw all elements: */
993 if(Val == 0) continue;
995 vf = (float)Val/(pHist->m_Max?pHist->m_Max:1);
996 x = cvRound((float)(pI->width-1)*(float)idxs[0] / (float)m_BinNum);
997 y = cvRound((float)(pI->height-1)*(float)idxs[1] / (float)m_BinNum);
999 cvCircle(pI, cvPoint(x,y), cvRound(2*vf),CV_RGB(0,0,cvRound(255*vf)),CV_FILLED);
1002 int dx = -2*(idxs[2]-m_BinNum/2);
1003 int dy = -2*(idxs[3]-m_BinNum/2);
1004 cvLine(pI,cvPoint(x,y),cvPoint(x+dx,y+dy),CV_RGB(0,0,255));
1007 m_pFVGen->GetFVMax()[0]==m_pFVGen->GetFVMax()[2] &&
1008 m_pFVGen->GetFVMax()[1]==m_pFVGen->GetFVMax()[3])
1009 { /* if SS feature vector */
1010 int x = cvRound((float)(pI->width-1)*(float)idxs[2] / (float)m_BinNum);
1011 int y = cvRound((float)(pI->height-1)*(float)idxs[3] / (float)m_BinNum);
1012 cvCircle(pI, cvPoint(x,y), cvRound(vf*pI->height/(m_BinNum*2)),CV_RGB(0,0,255),CV_FILLED);
1014 } /* Draw all elements. */
1017 //cvNamedWindow("Hist",0);
1018 //cvShowImage("Hist", pI);
1019 cvReleaseImage(&pI);
1023 float GetState(int BlobID)
1025 DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlobByID(BlobID);
1026 return pF?pF->state:0.0f;
1029 /* Return 0 if trajectory is normal;
1030 rreturn >0 if trajectory abnormal. */
1031 virtual char* GetStateDesc(int BlobID)
1033 if(GetState(BlobID)>0.5) return "abnormal";
1037 virtual void SetFileName(char* DataBaseName)
1039 if(m_HistMat.m_Volume!=m_HistVolumeSaved)SaveHist();
1040 m_DataFileName[0] = 0;
1044 strncpy(m_DataFileName,DataBaseName,1000);
1045 strcat(m_DataFileName, ".yml");
1050 virtual void SaveState(CvFileStorage* fs)
1052 int b, bN = m_TrackFGList.GetBlobNum();
1053 cvWriteInt(fs,"BlobNum",bN);
1054 cvStartWriteStruct(fs,"BlobList",CV_NODE_SEQ);
1058 DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlob(b);
1059 cvStartWriteStruct(fs,NULL,CV_NODE_MAP);
1060 cvWriteStruct(fs,"Blob", &(pF->blob), "ffffi");
1061 cvWriteInt(fs,"LastFrame",pF->LastFrame);
1062 cvWriteReal(fs,"State",pF->state);
1063 pF->pHist->Save(fs, "Hist");
1064 cvEndWriteStruct(fs);
1066 cvEndWriteStruct(fs);
1067 m_HistMat.Save(fs, "Hist");
1070 virtual void LoadState(CvFileStorage* fs, CvFileNode* node)
1072 CvFileNode* pBLN = cvGetFileNodeByName(fs,node,"BlobList");
1074 if(pBLN && CV_NODE_IS_SEQ(pBLN->tag))
1076 int b, bN = pBLN->data.seq->total;
1079 DefTrackFG* pF = NULL;
1081 CvFileNode* pBN = (CvFileNode*)cvGetSeqElem(pBLN->data.seq,b);
1084 cvReadStructByName(fs, pBN, "Blob", &Blob, "ffffi");
1086 pF = (DefTrackFG*)m_TrackFGList.GetBlobByID(Blob.ID);
1087 if(pF==NULL) continue;
1089 pF->state = (float)cvReadIntByName(fs,pBN,"State",cvRound(pF->state));
1091 pF->pHist->Load(fs,pBN,"Hist");
1095 m_HistMat.Load(fs, node, "Hist");
1099 virtual void Release(){ delete this; };
1105 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisHistP()
1106 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisHist(cvCreateFVGenP);}
1108 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisHistPV()
1109 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisHist(cvCreateFVGenPV);}
1111 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisHistPVS()
1112 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisHist(cvCreateFVGenPVS);}
1114 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisHistSS()
1115 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisHist(cvCreateFVGenSS);}
1117 typedef struct DefTrackSVM
1120 // CvBlobTrackFVGen* pFVGen;
1128 class CvBlobTrackAnalysisSVM : public CvBlobTrackAnalysis
1130 /*---------------- Internal functions: --------------------*/
1132 CvMemStorage* m_pMem;
1135 char m_DataFileName[1024];
1138 //CvStatModel* m_pStatModel;
1141 CvMat* m_pTrainData;
1142 int m_LastTrainDataSize;
1143 // CvBlobTrackFVGen* (*m_CreateFVGen)();
1144 CvBlobTrackFVGen* m_pFVGen;
1147 IplImage* m_pStatImg; /* for debug purpose */
1149 void RetrainStatModel()
1151 ///////// !!!!! TODO !!!!! Repair /////////////
1154 CvSVMModelParams SVMParams = {0};
1155 CvStatModel* pM = NULL;
1158 memset(&SVMParams,0,sizeof(SVMParams));
1159 SVMParams.svm_type = CV_SVM_ONE_CLASS;
1160 SVMParams.kernel_type = CV_SVM_RBF;
1161 SVMParams.gamma = 2.0/(m_RBFWidth*m_RBFWidth);
1162 SVMParams.nu = m_NU;
1163 SVMParams.degree = 3;
1164 SVMParams.criteria = cvTermCriteria(CV_TERMCRIT_EPS, 100, 1e-3 );
1169 if(m_pTrainData == NULL) return;
1171 int64 TickCount = cvGetTickCount();
1172 printf("Frame: %d\n Retrain SVM\nData Size = %d\n",m_Frame, m_pTrainData->rows);
1173 pM = cvTrainSVM( m_pTrainData,CV_ROW_SAMPLE, NULL, (CvStatModelParams*)&SVMParams, NULL, NULL);
1174 TickCount = cvGetTickCount() - TickCount ;
1175 printf("SV Count = %d\n",((CvSVMModel*)pM)->sv_total);
1176 printf("Processing Time = %.1f(ms)\n",TickCount/(1000*cvGetTickFrequency()));
1179 if(pM==NULL) return;
1180 if(m_pStatModel) cvReleaseStatModel(&m_pStatModel);
1183 if(m_pTrainData && m_Wnd)
1186 IplImage* pW = cvCreateImage(m_ImgSize,IPL_DEPTH_32F,1);
1187 IplImage* pI = cvCreateImage(m_ImgSize,IPL_DEPTH_8U,1);
1188 float* pFVVar = m_pFVGen->GetFVVar();
1192 for(i=0; i<m_pTrainData->rows; ++i)
1193 { /* Draw all elements: */
1194 float* pFV = (float*)(m_pTrainData->data.ptr + m_pTrainData->step*i);
1195 int x = cvRound(pFV[0]*pFVVar[0]);
1196 int y = cvRound(pFV[1]*pFVVar[1]);
1200 if(x>=pW->width)x=pW->width-1;
1202 if(y>=pW->height)y=pW->height-1;
1204 r = ((float*)(pW->imageData + y*pW->widthStep))[x];
1206 ((float*)(pW->imageData + y*pW->widthStep))[x] = r;
1208 if(r>MaxVal)MaxVal=r;
1211 if(MaxVal>0)cvConvertScale(pW,pI,255/MaxVal,0);
1212 cvNamedWindow("SVMData",0);
1213 cvShowImage("SVMData",pI);
1214 cvSaveImage("SVMData.bmp",pI);
1215 cvReleaseImage(&pW);
1216 cvReleaseImage(&pI);
1217 } /* Prepare for debug. */
1219 if(m_pStatModel && m_Wnd && m_Dim == 2)
1221 float* pFVVar = m_pFVGen->GetFVVar();
1223 if(m_pStatImg==NULL)
1225 m_pStatImg = cvCreateImage(m_ImgSize,IPL_DEPTH_8U,1);
1229 for(y=0; y<m_pStatImg->height; y+=1) for(x=0; x<m_pStatImg->width; x+=1)
1230 { /* Draw all elements: */
1232 uchar* pData = (uchar*)m_pStatImg->imageData + x + y*m_pStatImg->widthStep;
1234 float xy[2] = {x/pFVVar[0],y/pFVVar[1]};
1235 cvInitMatHeader( &FVmat, 1, 2, CV_32F, xy );
1236 res = cvStatModelPredict( m_pStatModel, &FVmat, NULL );
1237 pData[0]=((res>0.5)?255:0);
1240 cvNamedWindow("SVMMask",0);
1241 cvShowImage("SVMMask",m_pStatImg);
1242 cvSaveImage("SVMMask.bmp",m_pStatImg);
1243 } /* Prepare for debug. */
1246 void SaveStatModel()
1248 if(m_DataFileName[0])
1250 if(m_pTrainData)cvSave(m_DataFileName, m_pTrainData);
1253 void LoadStatModel()
1255 if(m_DataFileName[0])
1257 CvMat* pTrainData = (CvMat*)cvLoad(m_DataFileName);
1258 if(CV_IS_MAT(pTrainData) && pTrainData->width == m_Dim)
1260 if(m_pTrainData) cvReleaseMat(&m_pTrainData);
1261 m_pTrainData = pTrainData;
1267 CvBlobTrackAnalysisSVM(CvBlobTrackFVGen* (*createFVGen)()):m_Tracks(sizeof(DefTrackSVM))
1269 m_pFVGen = createFVGen();
1270 m_Dim = m_pFVGen->GetFVSize();
1271 m_pFV = (float*)cvAlloc(sizeof(float)*m_Dim);
1274 m_pTrainData = NULL;
1275 m_pStatModel = NULL;
1276 m_DataFileName[0] = 0;
1278 m_LastTrainDataSize = 0;
1281 AddParam("Nu",&m_NU);
1282 CommentParam("Nu","Parameters that tunes SVM border elastic");
1285 AddParam("RBFWidth",&m_RBFWidth);
1286 CommentParam("RBFWidth","Parameters that tunes RBF kernel function width.");
1288 } /* Constructor. */
1290 ~CvBlobTrackAnalysisSVM()
1294 for(i=m_Tracks.GetBlobNum();i>0;--i)
1296 DefTrackSVM* pF = (DefTrackSVM*)m_Tracks.GetBlob(i-1);
1297 if(pF->pMem) cvReleaseMemStorage(&pF->pMem);
1298 //pF->pFVGen->Release();
1300 if(m_pStatImg)cvReleaseImage(&m_pStatImg);
1304 /*----------------- Interface: --------------------*/
1305 virtual void AddBlob(CvBlob* pBlob)
1307 DefTrackSVM* pF = (DefTrackSVM*)m_Tracks.GetBlobByID(CV_BLOB_ID(pBlob));
1309 m_pFVGen->AddBlob(pBlob);
1312 { /* Create new record: */
1316 F.LastFrame = m_Frame;
1317 //F.pFVGen = m_CreateFVGen();
1318 F.pMem = cvCreateMemStorage();
1319 F.pFVSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(float)*m_Dim,F.pMem);
1325 m_Tracks.AddBlob((CvBlob*)&F);
1326 pF = (DefTrackSVM*)m_Tracks.GetBlobByID(CV_BLOB_ID(pBlob));
1330 pF->blob = pBlob[0];
1331 pF->LastFrame = m_Frame;
1334 virtual void Process(IplImage* pImg, IplImage* pFG)
1337 float* pFVVar = m_pFVGen->GetFVVar();
1339 m_pFVGen->Process(pImg, pFG);
1340 m_ImgSize = cvSize(pImg->width,pImg->height);
1342 for(i=m_pFVGen->GetFVNum(); i>0; --i)
1345 float* pFV = m_pFVGen->GetFV(i,&BlobID);
1346 DefTrackSVM* pF = (DefTrackSVM*)m_Tracks.GetBlobByID(BlobID);
1358 for(j=0; j<m_Dim; ++j)
1360 m_pFV[j] = pFV[j]/pFVVar[j];
1363 cvInitMatHeader( &FVmat, 1, m_Dim, CV_32F, m_pFV );
1364 //pF->state = cvStatModelPredict( m_pStatModel, &FVmat, NULL )<0.5;
1368 dx = (pF->blob.x - pF->BlobLast.x);
1369 dy = (pF->blob.y - pF->BlobLast.y);
1371 if(pF->BlobLast.x<0 || (dx*dx+dy*dy) >= 2*2)
1372 { /* Add feature vector to train data base: */
1373 pF->BlobLast = pF->blob;
1374 cvSeqPush(pF->pFVSeq,pFV);
1376 } /* Process one blob. */
1379 for(i=m_Tracks.GetBlobNum(); i>0; --i)
1380 { /* Check each blob record: */
1381 DefTrackSVM* pF = (DefTrackSVM*)m_Tracks.GetBlob(i-1);
1383 if(pF->LastFrame+3 < m_Frame )
1384 { /* Retrain stat model and delete blob filter: */
1386 int old_height = m_pTrainData?m_pTrainData->height:0;
1387 int height = old_height + pF->pFVSeq->total*mult;
1388 CvMat* pTrainData = cvCreateMat(height, m_Dim, CV_32F);
1390 if(m_pTrainData && pTrainData)
1391 { /* Create new train data matrix: */
1392 int h = pTrainData->height;
1393 pTrainData->height = MIN(pTrainData->height, m_pTrainData->height);
1394 cvCopy(m_pTrainData,pTrainData);
1395 pTrainData->height = h;
1398 for(j=0; j<pF->pFVSeq->total; ++j)
1399 { /* Copy new data to train data: */
1400 float* pFVVar = m_pFVGen->GetFVVar();
1401 float* pFV = (float*)cvGetSeqElem(pF->pFVSeq,j);
1404 for(k=0; k<mult; ++k)
1407 float* pTD = (float*)CV_MAT_ELEM_PTR( pTrainData[0], old_height+j*mult+k, 0);
1408 memcpy(pTD,pFV,sizeof(float)*m_Dim);
1410 if(pFVVar)for(t=0;t<m_Dim;++t)
1412 pTD[t] /= pFVVar[t];
1417 for(t=0; t<m_Dim; ++t)
1419 pTD[t] += m_RBFWidth*0.5f*(1-2.0f*rand()/(float)RAND_MAX);
1423 } /* Next new datum. */
1425 if(m_pTrainData) cvReleaseMat(&m_pTrainData);
1426 m_pTrainData = pTrainData;
1428 /* delete track record */
1429 cvReleaseMemStorage(&pF->pMem);
1431 m_Tracks.DelBlob(i-1);
1436 /* Retrain data each 1 minute if new data exist: */
1437 if(m_Frame%(25*60) == 0 && m_pTrainData && m_pTrainData->rows > m_LastTrainDataSize)
1444 if(m_Wnd && m_Dim==2)
1445 { /* Debug output: */
1447 IplImage* pI = cvCloneImage(pImg);
1449 if(m_pStatModel && m_pStatImg)
1451 for(y=0; y<pI->height; y+=2)
1453 uchar* pStatData = (uchar*)m_pStatImg->imageData + y*m_pStatImg->widthStep;
1454 uchar* pData = (uchar*)pI->imageData + y*pI->widthStep;
1456 for(x=0;x<pI->width;x+=2)
1457 { /* Draw all elements: */
1458 int d = pStatData[x];
1459 d = (d<<8) | (d^0xff);
1460 *(ushort*)(pData + x*3) = (ushort)d;
1464 //cvNamedWindow("SVMMap",0);
1465 //cvShowImage("SVMMap", pI);
1466 cvReleaseImage(&pI);
1467 } /* Debug output. */
1469 float GetState(int BlobID)
1471 DefTrackSVM* pF = (DefTrackSVM*)m_Tracks.GetBlobByID(BlobID);
1472 return pF?pF->state:0.0f;
1475 /* Return 0 if trajectory is normal;
1476 return >0 if trajectory abnormal. */
1477 virtual char* GetStateDesc(int BlobID)
1479 if(GetState(BlobID)>0.5) return "abnormal";
1483 virtual void SetFileName(char* DataBaseName)
1485 if(m_pTrainData)SaveStatModel();
1486 m_DataFileName[0] = 0;
1489 strncpy(m_DataFileName,DataBaseName,1000);
1490 strcat(m_DataFileName, ".yml");
1496 virtual void Release(){ delete this; };
1498 }; /* CvBlobTrackAnalysisSVM. */
1501 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisSVMP()
1502 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisSVM(cvCreateFVGenP);}
1504 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisSVMPV()
1505 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisSVM(cvCreateFVGenPV);}
1507 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisSVMPVS()
1508 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisSVM(cvCreateFVGenPVS);}
1510 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisSVMSS()
1511 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisSVM(cvCreateFVGenSS);}