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.
42 #include "precomp.hpp"
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();
99 case 2: SetModuleName("P"); break;
100 case 4: SetModuleName("PV"); break;
101 case 5: SetModuleName("PVS"); break;
107 if(m_pMem)cvReleaseMemStorage(&m_pMem);
110 void AddBlob(CvBlob* pBlob)
112 float FV[MAX_FV_SIZE+1];
114 DefBlobFVN* pFVBlob = (DefBlobFVN*)m_BlobList.GetBlobByID(CV_BLOB_ID(pBlob));
116 if(!m_ClearFlag) Clear();
121 BlobNew.blob = pBlob[0];
122 BlobNew.LastFrame = m_Frame;
124 BlobNew.FrameNum = 0;
125 m_BlobList.AddBlob((CvBlob*)&BlobNew);
126 pFVBlob = (DefBlobFVN*)m_BlobList.GetBlobByID(CV_BLOB_ID(pBlob));
127 } /* Add new record if necessary. */
129 pFVBlob->blob = pBlob[0];
132 for(i=(BLOB_NUM-1); i>0; --i)
134 pFVBlob->BlobSeq[i] = pFVBlob->BlobSeq[i-1];
137 pFVBlob->BlobSeq[0] = pBlob[0];
140 { /* Calculate FV position: */
141 FV[0] = CV_BLOB_X(pBlob);
142 FV[1] = CV_BLOB_Y(pBlob);
146 { /* Add new FV if position is enough: */
147 *(int*)(FV+m_Dim) = CV_BLOB_ID(pBlob);
148 cvSeqPush( m_pFVSeq, FV );
150 else if(pFVBlob->FrameNum > BLOB_NUM)
151 { /* Calculate velocity for more complex FV: */
154 { /* Average velocity: */
155 CvBlob* pBlobSeq = pFVBlob->BlobSeq;
157 for(i=1;i<BLOB_NUM;++i)
159 AverVx += CV_BLOB_X(pBlobSeq+i-1)-CV_BLOB_X(pBlobSeq+i);
160 AverVy += CV_BLOB_Y(pBlobSeq+i-1)-CV_BLOB_Y(pBlobSeq+i);
162 AverVx /= BLOB_NUM-1;
163 AverVy /= BLOB_NUM-1;
170 { /* State duration: */
171 float T = (CV_BLOB_WX(pBlob)+CV_BLOB_WY(pBlob))*0.01f;
173 if( fabs(AverVx) < T && fabs(AverVy) < T)
177 FV[4] = (float)pFVBlob->state;
178 } /* State duration. */
181 *(int*)(FV+m_Dim) = CV_BLOB_ID(pBlob);
182 cvSeqPush( m_pFVSeq, FV );
184 } /* If velocity is calculated. */
187 pFVBlob->LastFrame = m_Frame;
190 void Process(IplImage* pImg, IplImage* /*pFG*/)
193 if(!m_ClearFlag) Clear();
194 for(i=m_BlobList.GetBlobNum(); i>0; --i)
195 { /* Delete unused blob: */
196 DefBlobFVN* pFVBlob = (DefBlobFVN*)m_BlobList.GetBlob(i-1);
197 if(pFVBlob->LastFrame < m_Frame)
199 m_BlobList.DelBlob(i-1);
201 } /* Check next blob in list. */
205 m_FVMax[0] = (float)(pImg->width-1);
206 m_FVMax[1] = (float)(pImg->height-1);
207 m_FVVar[0] = m_FVMax[0]*0.01f;
208 m_FVVar[1] = m_FVMax[1]*0.01f;
209 m_FVVar[2] = (float)(pImg->width-1)/1440.0f;
210 m_FVMax[2] = (float)(pImg->width-1)*0.02f;
211 m_FVMin[2] = -m_FVMax[2];
212 m_FVVar[3] = (float)(pImg->width-1)/1440.0f;
213 m_FVMax[3] = (float)(pImg->height-1)*0.02f;
214 m_FVMin[3] = -m_FVMax[3];
215 m_FVMax[4] = 25*32.0f; /* max state is 32 sec */
222 virtual void Release(){delete this;};
223 virtual int GetFVSize(){return m_Dim;};
224 virtual int GetFVNum()
226 return m_pFVSeq->total;
229 virtual float* GetFV(int index, int* pFVID)
231 float* pFV = (float*)cvGetSeqElem( m_pFVSeq, index );
232 if(pFVID)pFVID[0] = *(int*)(pFV+m_Dim);
235 virtual float* GetFVMin(){return m_FVMin;}; /* returned pointer to array of minimal values of FV, if return 0 then FVrange is not exist */
236 virtual float* GetFVMax(){return m_FVMax;}; /* returned pointer to array of maximal values of FV, if return 0 then FVrange is not exist */
237 virtual float* GetFVVar(){return m_FVVar;}; /* returned pointer to array of maximal values of FV, if return 0 then FVrange is not exist */
238 };/* CvBlobTrackFVGenN */
240 CvBlobTrackFVGen* cvCreateFVGenP(){return (CvBlobTrackFVGen*)new CvBlobTrackFVGenN(2);}
241 CvBlobTrackFVGen* cvCreateFVGenPV(){return (CvBlobTrackFVGen*)new CvBlobTrackFVGenN(4);}
242 CvBlobTrackFVGen* cvCreateFVGenPVS(){return (CvBlobTrackFVGen*)new CvBlobTrackFVGenN(5);}
245 #define MAX_FV_SIZE 4
246 class CvBlobTrackFVGenSS: public CvBlobTrackFVGen
249 CvBlobSeq m_BlobList;
250 CvMemStorage* m_pMem;
252 float m_FVMax[MAX_FV_SIZE];
253 float m_FVMin[MAX_FV_SIZE];
254 float m_FVVar[MAX_FV_SIZE];
256 CvBlob m_BlobSeq[BLOB_NUM];
263 cvClearMemStorage(m_pMem);
264 m_pFVSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(float)*(m_Dim+1), m_pMem);
268 CvBlobTrackFVGenSS(int dim = 2 ):m_BlobList(sizeof(DefBlobFVN))
271 assert(dim <= MAX_FV_SIZE);
281 m_pMem = cvCreateMemStorage();
286 ~CvBlobTrackFVGenSS()
288 if(m_pMem)cvReleaseMemStorage(&m_pMem);
291 void AddBlob(CvBlob* pBlob)
293 //float FV[MAX_FV_SIZE+1];
295 DefBlobFVN* pFVBlob = (DefBlobFVN*)m_BlobList.GetBlobByID(CV_BLOB_ID(pBlob));
297 if(!m_ClearFlag) Clear();
302 BlobNew.blob = pBlob[0];
303 BlobNew.LastFrame = m_Frame;
305 BlobNew.FrameNum = 0;
306 m_BlobList.AddBlob((CvBlob*)&BlobNew);
307 pFVBlob = (DefBlobFVN*)m_BlobList.GetBlobByID(CV_BLOB_ID(pBlob));
308 } /* Add new record if necessary. */
311 for(i=(BLOB_NUM-1); i>0; --i)
313 pFVBlob->BlobSeq[i] = pFVBlob->BlobSeq[i-1];
316 pFVBlob->BlobSeq[0] = pBlob[0];
318 if(pFVBlob->FrameNum > BLOB_NUM)
319 { /* Average velocity: */
320 CvBlob* pBlobSeq = pFVBlob->BlobSeq;
321 float T = (CV_BLOB_WX(pBlob)+CV_BLOB_WY(pBlob))*0.01f;
325 for(i=1; i<BLOB_NUM; ++i)
327 AverVx += CV_BLOB_X(pBlobSeq+i-1)-CV_BLOB_X(pBlobSeq+i);
328 AverVy += CV_BLOB_Y(pBlobSeq+i-1)-CV_BLOB_Y(pBlobSeq+i);
330 AverVx /= BLOB_NUM-1;
331 AverVy /= BLOB_NUM-1;
333 if( fabs(AverVx) < T && fabs(AverVy) < T)
339 if(pFVBlob->state == 5)
340 { /* Object is stopped: */
341 float FV[MAX_FV_SIZE];
342 FV[0] = pFVBlob->blob.x;
343 FV[1] = pFVBlob->blob.y;
344 FV[2] = pFVBlob->BlobSeq[0].x;
345 FV[3] = pFVBlob->BlobSeq[0].y;
346 *(int*)(FV+m_Dim) = CV_BLOB_ID(pBlob);
347 cvSeqPush( m_pFVSeq, FV );
348 } /* Object is stopped. */
351 pFVBlob->LastFrame = m_Frame;
353 void Process(IplImage* pImg, IplImage* /*pFG*/)
357 if(!m_ClearFlag) Clear();
359 for(i=m_BlobList.GetBlobNum();i>0;--i)
360 { /* Delete unused blob: */
361 DefBlobFVN* pFVBlob = (DefBlobFVN*)m_BlobList.GetBlob(i-1);
362 if(pFVBlob->LastFrame < m_Frame)
364 float FV[MAX_FV_SIZE+1];
365 FV[0] = pFVBlob->blob.x;
366 FV[1] = pFVBlob->blob.y;
367 FV[2] = pFVBlob->BlobSeq[0].x;
368 FV[3] = pFVBlob->BlobSeq[0].y;
369 *(int*)(FV+m_Dim) = CV_BLOB_ID(pFVBlob);
370 cvSeqPush( m_pFVSeq, FV );
371 m_BlobList.DelBlob(i-1);
373 } /* Check next blob in list. */
375 /* Set max min range: */
380 m_FVMax[0] = (float)(pImg->width-1);
381 m_FVMax[1] = (float)(pImg->height-1);
382 m_FVMax[2] = (float)(pImg->width-1);
383 m_FVMax[3] = (float)(pImg->height-1);
384 m_FVVar[0] = m_FVMax[0]*0.01f;
385 m_FVVar[1] = m_FVMax[1]*0.01f;
386 m_FVVar[2] = m_FVMax[2]*0.01f;
387 m_FVVar[3] = m_FVMax[3]*0.01f;
392 virtual void Release(){delete this;};
393 virtual int GetFVSize(){return m_Dim;};
394 virtual int GetFVNum()
396 return m_pFVSeq->total;
399 virtual float* GetFV(int index, int* pFVID)
401 float* pFV = (float*)cvGetSeqElem( m_pFVSeq, index );
402 if(pFVID)pFVID[0] = *(int*)(pFV+m_Dim);
406 virtual float* GetFVMin(){return m_FVMin;}; /* returned pointer to array of minimal values of FV, if return 0 then FVrange is not exist */
407 virtual float* GetFVMax(){return m_FVMax;}; /* returned pointer to array of maximal values of FV, if return 0 then FVrange is not exist */
408 virtual float* GetFVVar(){return m_FVVar;}; /* returned pointer to array of maximal values of FV, if return 0 then FVrange is not exist */
409 };/* CvBlobTrackFVGenSS */
411 CvBlobTrackFVGen* cvCreateFVGenSS(){return (CvBlobTrackFVGen*)new CvBlobTrackFVGenSS;}
413 /*======================= TRAJECTORY ANALYZER MODULES =====================*/
414 /* Trajectory Analyser module */
421 CvSparseMatIterator m_SparseIterator;
422 CvSparseNode* m_pSparseNode;
427 CvSparseMat* m_pSparse;
431 DefMat(int dim = 0, int* sizes = NULL, int type = SPARSE)
433 /* Create sparse or ND matrix but not both: */
434 m_pSparseNode = NULL;
441 if(dim>0 && sizes != 0)
442 Realloc(dim, sizes, type);
446 if(m_pSparse)cvReleaseSparseMat(&m_pSparse);
447 if(m_pND)cvReleaseMatND(&m_pND);
448 if(m_IDXs) cvFree(&m_IDXs);
451 void Realloc(int dim, int* sizes, int type = SPARSE)
453 if(m_pSparse)cvReleaseSparseMat(&m_pSparse);
454 if(m_pND)cvReleaseMatND(&m_pND);
460 for(size=1,i=0;i<dim;++i)
473 } /* Define matrix type. */
477 m_pSparse = cvCreateSparseMat( dim, sizes, CV_32SC1 );
482 m_pND = cvCreateMatND( dim, sizes, CV_32SC1 );
484 m_IDXs = (int*)cvAlloc(sizeof(int)*dim);
490 void Save(const char* File)
492 if(m_pSparse)cvSave(File, m_pSparse );
493 if(m_pND)cvSave(File, m_pND );
495 void Save(CvFileStorage* fs, const char* name)
499 cvWrite(fs, name, m_pSparse );
503 cvWrite(fs, name, m_pND );
506 void Load(const char* File)
508 CvFileStorage* fs = cvOpenFileStorage( File, NULL, CV_STORAGE_READ );
512 if(m_pSparse) cvReleaseSparseMat(&m_pSparse);
513 if(m_pND) cvReleaseMatND(&m_pND);
517 if(ptr && CV_IS_MATND_HDR(ptr)) m_pND = (CvMatND*)ptr;
518 if(ptr && CV_IS_SPARSE_MAT_HDR(ptr)) m_pSparse = (CvSparseMat*)ptr;
519 cvReleaseFileStorage(&fs);
524 void Load(CvFileStorage* fs, CvFileNode* node, const char* name)
526 CvFileNode* n = cvGetFileNodeByName(fs,node,name);
527 void* ptr = n?cvRead(fs,n):NULL;
530 if(m_pSparse) cvReleaseSparseMat(&m_pSparse);
531 if(m_pND) cvReleaseMatND(&m_pND);
534 if(CV_IS_MATND_HDR(ptr)) m_pND = (CvMatND*)ptr;
535 if(CV_IS_SPARSE_MAT_HDR(ptr)) m_pSparse = (CvSparseMat*)ptr;
539 printf("WARNING!!! Can't load %s matrix\n",name);
549 { /* Calculate Volume of loaded hist: */
550 CvSparseMatIterator mat_iterator;
551 CvSparseNode* node = cvInitSparseMatIterator( m_pSparse, &mat_iterator );
553 for( ; node != 0; node = cvGetNextSparseNode( &mat_iterator ))
555 int val = *(int*)CV_NODE_VAL( m_pSparse, node ); /* get value of the element
556 (assume that the type is CV_32SC1) */
558 if(m_Max < val)m_Max = val;
560 } /* Calculate Volume of loaded hist. */
563 { /* Calculate Volume of loaded hist: */
567 cvGetMat( m_pND, &mat, NULL, 1 );
569 vol = cvSum(&mat).val[0];
570 m_Volume = cvRound(vol);
571 cvMinMaxLoc( &mat, NULL, &max_val);
572 m_Max = cvRound(max_val);
573 /* MUST BE WRITTEN LATER */
574 } /* Calculate Volume of loaded hist. */
577 int* GetPtr(int* indx)
579 if(m_pSparse) return (int*)cvPtrND( m_pSparse, indx, NULL, 1, NULL);
580 if(m_pND) return (int*)cvPtrND( m_pND, indx, NULL, 1, NULL);
584 int GetVal(int* indx)
586 int* p = GetPtr(indx);
591 int Add(int* indx, int val)
594 int* pVal = GetPtr(indx);
595 if(pVal == NULL) return -1;
599 if(m_Max < NewVal)m_Max = NewVal;
603 void Add(DefMat* pMatAdd)
607 for(Val = pMatAdd->GetNext(&pIDXS, 1 );pIDXS;Val=pMatAdd->GetNext(&pIDXS, 0 ))
613 int SetMax(int* indx, int val)
616 int* pVal = GetPtr(indx);
617 if(pVal == NULL) return -1;
620 m_Volume += val-pVal[0];
624 if(m_Max < NewVal)m_Max = NewVal;
628 int GetNext(int** pIDXS, int init = 0)
634 m_pSparseNode = (init || m_pSparseNode==NULL)?
635 cvInitSparseMatIterator( m_pSparse, &m_SparseIterator ):
636 cvGetNextSparseNode( &m_SparseIterator );
640 int* pVal = (int*)CV_NODE_VAL( m_pSparse, m_pSparseNode );
641 if(pVal)Val = pVal[0];
642 pIDXS[0] = CV_NODE_IDX( m_pSparse, m_pSparseNode );
644 }/* Sparse matrix. */
653 m_IDXs[i] = cvGetDimSize( m_pND, i )-1;
656 Val = GetVal(m_IDXs);
664 m_IDXs[i] = cvGetDimSize( m_pND, i )-1;
673 Val = GetVal(m_IDXs);
678 } /* Sparse matrix. */
687 typedef struct DefTrackFG
690 // CvBlobTrackFVGen* pFVGen;
695 class CvBlobTrackAnalysisHist : public CvBlobTrackAnalysis
697 /*---------------- Internal functions: --------------------*/
701 const char* m_SmoothKernel;
702 float m_AbnormalThreshold;
706 char m_DataFileName[1024];
710 int m_HistVolumeSaved;
714 CvBlobSeq m_TrackFGList;
715 //CvBlobTrackFVGen* (*m_CreateFVGen)();
716 CvBlobTrackFVGen* m_pFVGen;
719 if(m_DataFileName[0])
721 m_HistMat.Save(m_DataFileName);
722 m_HistVolumeSaved = m_HistMat.m_Volume;
727 if(m_DataFileName[0])m_HistMat.Load(m_DataFileName);
728 m_HistVolumeSaved = m_HistMat.m_Volume;
732 m_pFVi = (int*)cvAlloc(sizeof(int)*m_Dim);
733 m_pFViVar = (int*)cvAlloc(sizeof(int)*m_Dim);
734 m_pFViVarRes = (int*)cvAlloc(sizeof(int)*m_Dim);
735 m_Sizes = (int*)cvAlloc(sizeof(int)*m_Dim);
737 { /* Create init sparce matrix: */
739 for(i=0;i<m_Dim;++i)m_Sizes[i] = m_BinNum;
740 m_HistMat.Realloc(m_Dim,m_Sizes,SPARSE);
741 m_HistVolumeSaved = 0;
742 } /* Create init sparce matrix. */
748 for(i=m_TrackFGList.GetBlobNum();i>0;--i)
750 //DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlob(i-1);
751 // pF->pFVGen->Release();
752 m_TrackFGList.DelBlob(i-1);
756 cvFree(&m_pFViVarRes);
760 virtual void ParamUpdate()
762 if(m_BinNum != m_BinNumParam)
765 m_BinNum = m_BinNumParam;
770 CvBlobTrackAnalysisHist(CvBlobTrackFVGen* (*createFVGen)()):m_TrackFGList(sizeof(DefTrackFG))
772 m_pFVGen = createFVGen();
773 m_Dim = m_pFVGen->GetFVSize();
778 m_DataFileName[0] = 0;
780 m_AbnormalThreshold = 0.02f;
781 AddParam("AbnormalThreshold",&m_AbnormalThreshold);
782 CommentParam("AbnormalThreshold","If trajectory histogram value is lesst then <AbnormalThreshold*DataBaseTrackNum> then trajectory is abnormal");
785 AddParam("SmoothRadius",&m_SmoothRadius);
786 CommentParam("AbnormalThreshold","Radius (in bins) for histogram smoothing");
788 m_SmoothKernel = "L";
789 AddParam("SmoothKernel",&m_SmoothKernel);
790 CommentParam("SmoothKernel","L - Linear, G - Gaussian");
793 m_BinNumParam = m_BinNum;
794 AddParam("BinNum",&m_BinNumParam);
795 CommentParam("BinNum","Number of bin for each dimention of feature vector");
798 SetModuleName("Hist");
802 ~CvBlobTrackAnalysisHist()
809 /*----------------- Interface: --------------------*/
810 virtual void AddBlob(CvBlob* pBlob)
812 DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlobByID(CV_BLOB_ID(pBlob));
814 { /* create new filter */
818 F.LastFrame = m_Frame;
819 // F.pFVGen = m_CreateFVGen();
820 F.pHist = new DefMat(m_Dim,m_Sizes,SPARSE);
821 m_TrackFGList.AddBlob((CvBlob*)&F);
822 pF = (DefTrackFG*)m_TrackFGList.GetBlobByID(CV_BLOB_ID(pBlob));
827 pF->LastFrame = m_Frame;
828 m_pFVGen->AddBlob(pBlob);
830 virtual void Process(IplImage* pImg, IplImage* pFG)
833 m_pFVGen->Process(pImg, pFG);
834 int SK = m_SmoothKernel[0];
836 for(i=0; i<m_pFVGen->GetFVNum(); ++i)
839 float* pFV = m_pFVGen->GetFV(i,&BlobID);
840 float* pFVMax = m_pFVGen->GetFVMax();
841 float* pFVMin = m_pFVGen->GetFVMin();
842 DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlobByID(BlobID);
847 pF->LastFrame = m_Frame;
851 for(j=0; j<m_Dim; ++j)
854 float f0 = pFVMin?pFVMin[j]:0;
855 float f1 = pFVMax?pFVMax[j]:1;
857 index = cvRound((m_BinNum-1)*(pFV[j]-f0)/(f1-f0));
859 if(index>=m_BinNum)index=m_BinNum-1;
864 HistVal = m_HistMat.GetVal(m_pFVi);/* get bin value*/
866 { /* Calculate state: */
867 float T = m_HistMat.m_Max*m_AbnormalThreshold; /* calc threshold */
869 if(m_TrackNum>0) T = 256.0f * m_TrackNum*m_AbnormalThreshold;
872 pF->state = (T - HistVal)/(T*0.2f) + 0.5f;
874 if(pF->state<0)pF->state=0;
875 if(pF->state>1)pF->state=1;
878 { /* If it is a new FV then add it to trajectory histogram: */
880 int r = m_SmoothRadius;
882 // printf("BLob %3d NEW FV [", CV_BLOB_ID(pF));
883 // for(i=0;i<m_Dim;++i) printf("%d,", m_pFVi[i]);
886 for(i=0; i<m_Dim; ++i)
897 for(i=0; i<m_Dim; ++i)
899 m_pFViVarRes[i] = m_pFVi[i]+m_pFViVar[i];
900 if(m_pFViVarRes[i]<0) good= 0;
901 if(m_pFViVarRes[i]>=m_BinNum) good= 0;
902 dist += m_pFViVar[i]*m_pFViVar[i];
903 }/* Calculate next dimension. */
905 if(SK=='G' || SK=='g')
907 double dist2 = dist/(r*r);
908 HistAdd = cvRound(256*exp(-dist2)); /* Hist Add for (dist=1) = 25.6*/
910 else if(SK=='L' || SK=='l')
912 dist = (float)(sqrt(dist)/(r+1));
913 HistAdd = cvRound(256*(1-dist));
917 HistAdd = 255; /* Flat smoothing. */
920 if(good && HistAdd>0)
921 { /* Update histogram: */
923 pF->pHist->SetMax(m_pFViVarRes, HistAdd);
924 } /* Update histogram. */
926 for(i=0; i<m_Dim; ++i)
928 if((m_pFViVar[i]++) < r)
931 } /* Increase next dimension variable. */
933 } /* Next variation. */
937 { /* Check all blobs on list: */
939 for(i=m_TrackFGList.GetBlobNum(); i>0; --i)
940 { /* Add histogram and delete blob from list: */
941 DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlob(i-1);
942 if(pF->LastFrame+3 < m_Frame && pF->pHist)
944 m_HistMat.Add(pF->pHist);
947 m_TrackFGList.DelBlob(i-1);
955 { /* Debug output: */
958 IplImage* pI = cvCloneImage(pImg);
962 for(Val = m_HistMat.GetNext(&idxs,1); idxs; Val=m_HistMat.GetNext(&idxs,0))
963 { /* Draw all elements: */
968 if(Val == 0) continue;
970 vf = (float)Val/(m_HistMat.m_Max?m_HistMat.m_Max:1);
971 x = cvRound((float)(pI->width-1)*(float)idxs[0] / (float)m_BinNum);
972 y = cvRound((float)(pI->height-1)*(float)idxs[1] / (float)m_BinNum);
974 cvCircle(pI, cvPoint(x,y), cvRound(vf*pI->height/(m_BinNum*2)),CV_RGB(255,0,0),CV_FILLED);
977 int dx = -2*(idxs[2]-m_BinNum/2);
978 int dy = -2*(idxs[3]-m_BinNum/2);
979 cvLine(pI,cvPoint(x,y),cvPoint(x+dx,y+dy),CV_RGB(0,cvRound(vf*255),1));
982 m_pFVGen->GetFVMax()[0]==m_pFVGen->GetFVMax()[2] &&
983 m_pFVGen->GetFVMax()[1]==m_pFVGen->GetFVMax()[3])
985 int x = cvRound((float)(pI->width-1)*(float)idxs[2] / (float)m_BinNum);
986 int y = cvRound((float)(pI->height-1)*(float)idxs[3] / (float)m_BinNum);
987 cvCircle(pI, cvPoint(x,y), cvRound(vf*pI->height/(m_BinNum*2)),CV_RGB(0,0,255),CV_FILLED);
989 } /* Draw all elements. */
991 for(i=m_TrackFGList.GetBlobNum();i>0;--i)
993 DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlob(i-1);
994 DefMat* pHist = pF?pF->pHist:NULL;
996 if(pHist==NULL) continue;
998 for(Val = pHist->GetNext(&idxs,1);idxs;Val=pHist->GetNext(&idxs,0))
999 { /* Draw all elements: */
1004 if(Val == 0) continue;
1006 vf = (float)Val/(pHist->m_Max?pHist->m_Max:1);
1007 x = cvRound((float)(pI->width-1)*(float)idxs[0] / (float)m_BinNum);
1008 y = cvRound((float)(pI->height-1)*(float)idxs[1] / (float)m_BinNum);
1010 cvCircle(pI, cvPoint(x,y), cvRound(2*vf),CV_RGB(0,0,cvRound(255*vf)),CV_FILLED);
1013 int dx = -2*(idxs[2]-m_BinNum/2);
1014 int dy = -2*(idxs[3]-m_BinNum/2);
1015 cvLine(pI,cvPoint(x,y),cvPoint(x+dx,y+dy),CV_RGB(0,0,255));
1018 m_pFVGen->GetFVMax()[0]==m_pFVGen->GetFVMax()[2] &&
1019 m_pFVGen->GetFVMax()[1]==m_pFVGen->GetFVMax()[3])
1020 { /* if SS feature vector */
1021 int x = cvRound((float)(pI->width-1)*(float)idxs[2] / (float)m_BinNum);
1022 int y = cvRound((float)(pI->height-1)*(float)idxs[3] / (float)m_BinNum);
1023 cvCircle(pI, cvPoint(x,y), cvRound(vf*pI->height/(m_BinNum*2)),CV_RGB(0,0,255),CV_FILLED);
1025 } /* Draw all elements. */
1028 //cvNamedWindow("Hist",0);
1029 //cvShowImage("Hist", pI);
1030 cvReleaseImage(&pI);
1034 float GetState(int BlobID)
1036 DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlobByID(BlobID);
1037 return pF?pF->state:0.0f;
1040 /* Return 0 if trajectory is normal;
1041 rreturn >0 if trajectory abnormal. */
1042 virtual const char* GetStateDesc(int BlobID)
1044 if(GetState(BlobID)>0.5) return "abnormal";
1048 virtual void SetFileName(char* DataBaseName)
1050 if(m_HistMat.m_Volume!=m_HistVolumeSaved)SaveHist();
1051 m_DataFileName[0] = m_DataFileName[1000] = 0;
1055 strncpy(m_DataFileName,DataBaseName,1000);
1056 strcat(m_DataFileName, ".yml");
1061 virtual void SaveState(CvFileStorage* fs)
1063 int b, bN = m_TrackFGList.GetBlobNum();
1064 cvWriteInt(fs,"BlobNum",bN);
1065 cvStartWriteStruct(fs,"BlobList",CV_NODE_SEQ);
1069 DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlob(b);
1070 cvStartWriteStruct(fs,NULL,CV_NODE_MAP);
1071 cvWriteStruct(fs,"Blob", &(pF->blob), "ffffi");
1072 cvWriteInt(fs,"LastFrame",pF->LastFrame);
1073 cvWriteReal(fs,"State",pF->state);
1074 pF->pHist->Save(fs, "Hist");
1075 cvEndWriteStruct(fs);
1077 cvEndWriteStruct(fs);
1078 m_HistMat.Save(fs, "Hist");
1081 virtual void LoadState(CvFileStorage* fs, CvFileNode* node)
1083 CvFileNode* pBLN = cvGetFileNodeByName(fs,node,"BlobList");
1085 if(pBLN && CV_NODE_IS_SEQ(pBLN->tag))
1087 int b, bN = pBLN->data.seq->total;
1090 DefTrackFG* pF = NULL;
1092 CvFileNode* pBN = (CvFileNode*)cvGetSeqElem(pBLN->data.seq,b);
1095 cvReadStructByName(fs, pBN, "Blob", &Blob, "ffffi");
1097 pF = (DefTrackFG*)m_TrackFGList.GetBlobByID(Blob.ID);
1098 if(pF==NULL) continue;
1100 pF->state = (float)cvReadIntByName(fs,pBN,"State",cvRound(pF->state));
1102 pF->pHist->Load(fs,pBN,"Hist");
1106 m_HistMat.Load(fs, node, "Hist");
1110 virtual void Release(){ delete this; };
1116 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisHistP()
1117 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisHist(cvCreateFVGenP);}
1119 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisHistPV()
1120 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisHist(cvCreateFVGenPV);}
1122 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisHistPVS()
1123 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisHist(cvCreateFVGenPVS);}
1125 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisHistSS()
1126 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisHist(cvCreateFVGenSS);}
1128 typedef struct DefTrackSVM
1131 // CvBlobTrackFVGen* pFVGen;
1139 class CvBlobTrackAnalysisSVM : public CvBlobTrackAnalysis
1141 /*---------------- Internal functions: --------------------*/
1143 CvMemStorage* m_pMem;
1146 char m_DataFileName[1024];
1149 //CvStatModel* m_pStatModel;
1152 CvMat* m_pTrainData;
1153 int m_LastTrainDataSize;
1154 // CvBlobTrackFVGen* (*m_CreateFVGen)();
1155 CvBlobTrackFVGen* m_pFVGen;
1158 IplImage* m_pStatImg; /* for debug purpose */
1160 void RetrainStatModel()
1162 ///////// !!!!! TODO !!!!! Repair /////////////
1165 CvSVMModelParams SVMParams = {0};
1166 CvStatModel* pM = NULL;
1169 memset(&SVMParams,0,sizeof(SVMParams));
1170 SVMParams.svm_type = CV_SVM_ONE_CLASS;
1171 SVMParams.kernel_type = CV_SVM_RBF;
1172 SVMParams.gamma = 2.0/(m_RBFWidth*m_RBFWidth);
1173 SVMParams.nu = m_NU;
1174 SVMParams.degree = 3;
1175 SVMParams.criteria = cvTermCriteria(CV_TERMCRIT_EPS, 100, 1e-3 );
1180 if(m_pTrainData == NULL) return;
1182 int64 TickCount = cvGetTickCount();
1183 printf("Frame: %d\n Retrain SVM\nData Size = %d\n",m_Frame, m_pTrainData->rows);
1184 pM = cvTrainSVM( m_pTrainData,CV_ROW_SAMPLE, NULL, (CvStatModelParams*)&SVMParams, NULL, NULL);
1185 TickCount = cvGetTickCount() - TickCount ;
1186 printf("SV Count = %d\n",((CvSVMModel*)pM)->sv_total);
1187 printf("Processing Time = %.1f(ms)\n",TickCount/(1000*cvGetTickFrequency()));
1190 if(pM==NULL) return;
1191 if(m_pStatModel) cvReleaseStatModel(&m_pStatModel);
1194 if(m_pTrainData && m_Wnd)
1197 IplImage* pW = cvCreateImage(m_ImgSize,IPL_DEPTH_32F,1);
1198 IplImage* pI = cvCreateImage(m_ImgSize,IPL_DEPTH_8U,1);
1199 float* pFVVar = m_pFVGen->GetFVVar();
1203 for(i=0; i<m_pTrainData->rows; ++i)
1204 { /* Draw all elements: */
1205 float* pFV = (float*)(m_pTrainData->data.ptr + m_pTrainData->step*i);
1206 int x = cvRound(pFV[0]*pFVVar[0]);
1207 int y = cvRound(pFV[1]*pFVVar[1]);
1211 if(x>=pW->width)x=pW->width-1;
1213 if(y>=pW->height)y=pW->height-1;
1215 r = ((float*)(pW->imageData + y*pW->widthStep))[x];
1217 ((float*)(pW->imageData + y*pW->widthStep))[x] = r;
1219 if(r>MaxVal)MaxVal=r;
1222 if(MaxVal>0)cvConvertScale(pW,pI,255/MaxVal,0);
1223 cvNamedWindow("SVMData",0);
1224 cvShowImage("SVMData",pI);
1225 cvSaveImage("SVMData.bmp",pI);
1226 cvReleaseImage(&pW);
1227 cvReleaseImage(&pI);
1228 } /* Prepare for debug. */
1230 if(m_pStatModel && m_Wnd && m_Dim == 2)
1232 float* pFVVar = m_pFVGen->GetFVVar();
1234 if(m_pStatImg==NULL)
1236 m_pStatImg = cvCreateImage(m_ImgSize,IPL_DEPTH_8U,1);
1240 for(y=0; y<m_pStatImg->height; y+=1) for(x=0; x<m_pStatImg->width; x+=1)
1241 { /* Draw all elements: */
1243 uchar* pData = (uchar*)m_pStatImg->imageData + x + y*m_pStatImg->widthStep;
1245 float xy[2] = {x/pFVVar[0],y/pFVVar[1]};
1246 cvInitMatHeader( &FVmat, 1, 2, CV_32F, xy );
1247 res = cvStatModelPredict( m_pStatModel, &FVmat, NULL );
1248 pData[0]=((res>0.5)?255:0);
1251 cvNamedWindow("SVMMask",0);
1252 cvShowImage("SVMMask",m_pStatImg);
1253 cvSaveImage("SVMMask.bmp",m_pStatImg);
1254 } /* Prepare for debug. */
1257 void SaveStatModel()
1259 if(m_DataFileName[0])
1261 if(m_pTrainData)cvSave(m_DataFileName, m_pTrainData);
1264 void LoadStatModel()
1266 if(m_DataFileName[0])
1268 CvMat* pTrainData = (CvMat*)cvLoad(m_DataFileName);
1269 if(CV_IS_MAT(pTrainData) && pTrainData->width == m_Dim)
1271 if(m_pTrainData) cvReleaseMat(&m_pTrainData);
1272 m_pTrainData = pTrainData;
1278 CvBlobTrackAnalysisSVM(CvBlobTrackFVGen* (*createFVGen)()):m_Tracks(sizeof(DefTrackSVM))
1280 m_pFVGen = createFVGen();
1281 m_Dim = m_pFVGen->GetFVSize();
1282 m_pFV = (float*)cvAlloc(sizeof(float)*m_Dim);
1285 m_pTrainData = NULL;
1286 m_pStatModel = NULL;
1287 m_DataFileName[0] = 0;
1289 m_LastTrainDataSize = 0;
1292 AddParam("Nu",&m_NU);
1293 CommentParam("Nu","Parameters that tunes SVM border elastic");
1296 AddParam("RBFWidth",&m_RBFWidth);
1297 CommentParam("RBFWidth","Parameters that tunes RBF kernel function width.");
1299 SetModuleName("SVM");
1301 } /* Constructor. */
1303 ~CvBlobTrackAnalysisSVM()
1307 for(i=m_Tracks.GetBlobNum();i>0;--i)
1309 DefTrackSVM* pF = (DefTrackSVM*)m_Tracks.GetBlob(i-1);
1310 if(pF->pMem) cvReleaseMemStorage(&pF->pMem);
1311 //pF->pFVGen->Release();
1313 if(m_pStatImg)cvReleaseImage(&m_pStatImg);
1317 /*----------------- Interface: --------------------*/
1318 virtual void AddBlob(CvBlob* pBlob)
1320 DefTrackSVM* pF = (DefTrackSVM*)m_Tracks.GetBlobByID(CV_BLOB_ID(pBlob));
1322 m_pFVGen->AddBlob(pBlob);
1325 { /* Create new record: */
1329 F.LastFrame = m_Frame;
1330 //F.pFVGen = m_CreateFVGen();
1331 F.pMem = cvCreateMemStorage();
1332 F.pFVSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(float)*m_Dim,F.pMem);
1338 m_Tracks.AddBlob((CvBlob*)&F);
1339 pF = (DefTrackSVM*)m_Tracks.GetBlobByID(CV_BLOB_ID(pBlob));
1343 pF->blob = pBlob[0];
1344 pF->LastFrame = m_Frame;
1347 virtual void Process(IplImage* pImg, IplImage* pFG)
1350 float* pFVVar = m_pFVGen->GetFVVar();
1352 m_pFVGen->Process(pImg, pFG);
1353 m_ImgSize = cvSize(pImg->width,pImg->height);
1355 for(i=m_pFVGen->GetFVNum(); i>0; --i)
1358 float* pFV = m_pFVGen->GetFV(i,&BlobID);
1359 DefTrackSVM* pF = (DefTrackSVM*)m_Tracks.GetBlobByID(BlobID);
1371 for(j=0; j<m_Dim; ++j)
1373 m_pFV[j] = pFV[j]/pFVVar[j];
1376 cvInitMatHeader( &FVmat, 1, m_Dim, CV_32F, m_pFV );
1377 //pF->state = cvStatModelPredict( m_pStatModel, &FVmat, NULL )<0.5;
1381 dx = (pF->blob.x - pF->BlobLast.x);
1382 dy = (pF->blob.y - pF->BlobLast.y);
1384 if(pF->BlobLast.x<0 || (dx*dx+dy*dy) >= 2*2)
1385 { /* Add feature vector to train data base: */
1386 pF->BlobLast = pF->blob;
1387 cvSeqPush(pF->pFVSeq,pFV);
1389 } /* Process one blob. */
1392 for(i=m_Tracks.GetBlobNum(); i>0; --i)
1393 { /* Check each blob record: */
1394 DefTrackSVM* pF = (DefTrackSVM*)m_Tracks.GetBlob(i-1);
1396 if(pF->LastFrame+3 < m_Frame )
1397 { /* Retrain stat model and delete blob filter: */
1399 int old_height = m_pTrainData?m_pTrainData->height:0;
1400 int height = old_height + pF->pFVSeq->total*mult;
1401 CvMat* pTrainData = cvCreateMat(height, m_Dim, CV_32F);
1403 if(m_pTrainData && pTrainData)
1404 { /* Create new train data matrix: */
1405 int h = pTrainData->height;
1406 pTrainData->height = MIN(pTrainData->height, m_pTrainData->height);
1407 cvCopy(m_pTrainData,pTrainData);
1408 pTrainData->height = h;
1411 for(j=0; j<pF->pFVSeq->total; ++j)
1412 { /* Copy new data to train data: */
1413 float* pFVVar = m_pFVGen->GetFVVar();
1414 float* pFV = (float*)cvGetSeqElem(pF->pFVSeq,j);
1417 for(k=0; k<mult; ++k)
1420 float* pTD = (float*)CV_MAT_ELEM_PTR( pTrainData[0], old_height+j*mult+k, 0);
1421 memcpy(pTD,pFV,sizeof(float)*m_Dim);
1423 if(pFVVar)for(t=0;t<m_Dim;++t)
1425 pTD[t] /= pFVVar[t];
1430 for(t=0; t<m_Dim; ++t)
1432 pTD[t] += m_RBFWidth*0.5f*(1-2.0f*rand()/(float)RAND_MAX);
1436 } /* Next new datum. */
1438 if(m_pTrainData) cvReleaseMat(&m_pTrainData);
1439 m_pTrainData = pTrainData;
1441 /* delete track record */
1442 cvReleaseMemStorage(&pF->pMem);
1444 m_Tracks.DelBlob(i-1);
1449 /* Retrain data each 1 minute if new data exist: */
1450 if(m_Frame%(25*60) == 0 && m_pTrainData && m_pTrainData->rows > m_LastTrainDataSize)
1457 if(m_Wnd && m_Dim==2)
1458 { /* Debug output: */
1460 IplImage* pI = cvCloneImage(pImg);
1462 if(m_pStatModel && m_pStatImg)
1464 for(y=0; y<pI->height; y+=2)
1466 uchar* pStatData = (uchar*)m_pStatImg->imageData + y*m_pStatImg->widthStep;
1467 uchar* pData = (uchar*)pI->imageData + y*pI->widthStep;
1469 for(x=0;x<pI->width;x+=2)
1470 { /* Draw all elements: */
1471 int d = pStatData[x];
1472 d = (d<<8) | (d^0xff);
1473 *(ushort*)(pData + x*3) = (ushort)d;
1477 //cvNamedWindow("SVMMap",0);
1478 //cvShowImage("SVMMap", pI);
1479 cvReleaseImage(&pI);
1480 } /* Debug output. */
1482 float GetState(int BlobID)
1484 DefTrackSVM* pF = (DefTrackSVM*)m_Tracks.GetBlobByID(BlobID);
1485 return pF?pF->state:0.0f;
1488 /* Return 0 if trajectory is normal;
1489 return >0 if trajectory abnormal. */
1490 virtual const char* GetStateDesc(int BlobID)
1492 if(GetState(BlobID)>0.5) return "abnormal";
1496 virtual void SetFileName(char* DataBaseName)
1498 if(m_pTrainData)SaveStatModel();
1499 m_DataFileName[0] = m_DataFileName[1000] = 0;
1502 strncpy(m_DataFileName,DataBaseName,1000);
1503 strcat(m_DataFileName, ".yml");
1509 virtual void Release(){ delete this; };
1511 }; /* CvBlobTrackAnalysisSVM. */
1514 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisSVMP()
1515 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisSVM(cvCreateFVGenP);}
1517 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisSVMPV()
1518 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisSVM(cvCreateFVGenPV);}
1520 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisSVMPVS()
1521 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisSVM(cvCreateFVGenPVS);}
1523 CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisSVMSS()
1524 {return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisSVM(cvCreateFVGenSS);}