X-Git-Url: http://git.maemo.org/git/?p=opencv;a=blobdiff_plain;f=src%2Fcvaux%2Fvs%2Fblobtrackanalysishist.cpp;fp=src%2Fcvaux%2Fvs%2Fblobtrackanalysishist.cpp;h=f1a011ad41dbe62a495c01e6a986925f32db8e5c;hp=0000000000000000000000000000000000000000;hb=e4c14cdbdf2fe805e79cd96ded236f57e7b89060;hpb=454138ff8a20f6edb9b65a910101403d8b520643 diff --git a/src/cvaux/vs/blobtrackanalysishist.cpp b/src/cvaux/vs/blobtrackanalysishist.cpp new file mode 100644 index 0000000..f1a011a --- /dev/null +++ b/src/cvaux/vs/blobtrackanalysishist.cpp @@ -0,0 +1,1524 @@ +/*M/////////////////////////////////////////////////////////////////////////////////////// +// +// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. +// +// By downloading, copying, installing or using the software you agree to this license. +// If you do not agree to this license, do not download, install, +// copy or use the software. +// +// +// Intel License Agreement +// For Open Source Computer Vision Library +// +// Copyright (C) 2000, Intel Corporation, all rights reserved. +// Third party copyrights are property of their respective owners. +// +// Redistribution and use in source and binary forms, with or without modification, +// are permitted provided that the following conditions are met: +// +// * Redistribution's of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// * Redistribution's in binary form must reproduce the above copyright notice, +// this list of conditions and the following disclaimer in the documentation +// and/or other materials provided with the distribution. +// +// * The name of Intel Corporation may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// This software is provided by the copyright holders and contributors "as is" and +// any express or implied warranties, including, but not limited to, the implied +// warranties of merchantability and fitness for a particular purpose are disclaimed. +// In no event shall the Intel Corporation or contributors be liable for any direct, +// indirect, incidental, special, exemplary, or consequential damages +// (including, but not limited to, procurement of substitute goods or services; +// loss of use, data, or profits; or business interruption) however caused +// and on any theory of liability, whether in contract, strict liability, +// or tort (including negligence or otherwise) arising in any way out of +// the use of this software, even if advised of the possibility of such damage. +// +//M*/ + +#include "_cvaux.h" + +#define MAX_FV_SIZE 5 +#define BLOB_NUM 5 + +typedef struct DefBlobFVN +{ + CvBlob blob; + CvBlob BlobSeq[BLOB_NUM]; + int state; + int LastFrame; + int FrameNum; +} DefBlobFVN; + +class CvBlobTrackFVGenN: public CvBlobTrackFVGen +{ +private: + CvBlobSeq m_BlobList; + CvMemStorage* m_pMem; + CvSeq* m_pFVSeq; + float m_FVMax[MAX_FV_SIZE]; + float m_FVMin[MAX_FV_SIZE]; + float m_FVVar[MAX_FV_SIZE]; + int m_Dim; + CvBlob m_BlobSeq[BLOB_NUM]; + int m_Frame; + int m_State; + int m_LastFrame; + int m_ClearFlag; + void Clear() + { + if(m_pMem) + { + cvClearMemStorage(m_pMem); + m_pFVSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(float)*(m_Dim+1), m_pMem); + m_ClearFlag = 1; + } + } +public: + CvBlobTrackFVGenN(int dim = 2 ):m_BlobList(sizeof(DefBlobFVN)) + { + int i; + assert(dim <= MAX_FV_SIZE); + m_Dim = dim; + for(i=0; iblob = pBlob[0]; + + /* Shift: */ + for(i=(BLOB_NUM-1); i>0; --i) + { + pFVBlob->BlobSeq[i] = pFVBlob->BlobSeq[i-1]; + } + + pFVBlob->BlobSeq[0] = pBlob[0]; + + if(m_Dim>0) + { /* Calculate FV position: */ + FV[0] = CV_BLOB_X(pBlob); + FV[1] = CV_BLOB_Y(pBlob); + } + + if(m_Dim<=2) + { /* Add new FV if position is enough: */ + *(int*)(FV+m_Dim) = CV_BLOB_ID(pBlob); + cvSeqPush( m_pFVSeq, FV ); + } + else if(pFVBlob->FrameNum > BLOB_NUM) + { /* Calculate velocity for more complex FV: */ + float AverVx = 0; + float AverVy = 0; + { /* Average velocity: */ + CvBlob* pBlobSeq = pFVBlob->BlobSeq; + int i; + for(i=1;i4) + { /* State duration: */ + float T = (CV_BLOB_WX(pBlob)+CV_BLOB_WY(pBlob))*0.01f; + + if( fabs(AverVx) < T && fabs(AverVy) < T) + pFVBlob->state++; + else + pFVBlob->state=0; + FV[4] = (float)pFVBlob->state; + } /* State duration. */ + + /* Add new FV: */ + *(int*)(FV+m_Dim) = CV_BLOB_ID(pBlob); + cvSeqPush( m_pFVSeq, FV ); + + } /* If velocity is calculated. */ + + pFVBlob->FrameNum++; + pFVBlob->LastFrame = m_Frame; + }; /* AddBlob */ + + void Process(IplImage* pImg, IplImage* /*pFG*/) + { + int i; + if(!m_ClearFlag) Clear(); + for(i=m_BlobList.GetBlobNum(); i>0; --i) + { /* Delete unused blob: */ + DefBlobFVN* pFVBlob = (DefBlobFVN*)m_BlobList.GetBlob(i-1); + if(pFVBlob->LastFrame < m_Frame) + { + m_BlobList.DelBlob(i-1); + } + } /* Check next blob in list. */ + + m_FVMin[0] = 0; + m_FVMin[1] = 0; + m_FVMax[0] = (float)(pImg->width-1); + m_FVMax[1] = (float)(pImg->height-1); + m_FVVar[0] = m_FVMax[0]*0.01f; + m_FVVar[1] = m_FVMax[1]*0.01f; + m_FVVar[2] = (float)(pImg->width-1)/1440.0f; + m_FVMax[2] = (float)(pImg->width-1)*0.02f; + m_FVMin[2] = -m_FVMax[2]; + m_FVVar[3] = (float)(pImg->width-1)/1440.0f; + m_FVMax[3] = (float)(pImg->height-1)*0.02f; + m_FVMin[3] = -m_FVMax[3]; + m_FVMax[4] = 25*32.0f; /* max state is 32 sec */ + m_FVMin[4] = 0; + m_FVVar[4] = 10; + + m_Frame++; + m_ClearFlag = 0; + }; + virtual void Release(){delete this;}; + virtual int GetFVSize(){return m_Dim;}; + virtual int GetFVNum() + { + return m_pFVSeq->total; + }; + + virtual float* GetFV(int index, int* pFVID) + { + float* pFV = (float*)cvGetSeqElem( m_pFVSeq, index ); + if(pFVID)pFVID[0] = *(int*)(pFV+m_Dim); + return pFV; + }; + virtual float* GetFVMin(){return m_FVMin;}; /* returned pointer to array of minimal values of FV, if return 0 then FVrange is not exist */ + virtual float* GetFVMax(){return m_FVMax;}; /* returned pointer to array of maximal values of FV, if return 0 then FVrange is not exist */ + virtual float* GetFVVar(){return m_FVVar;}; /* returned pointer to array of maximal values of FV, if return 0 then FVrange is not exist */ +};/* CvBlobTrackFVGenN */ + +CvBlobTrackFVGen* cvCreateFVGenP(){return (CvBlobTrackFVGen*)new CvBlobTrackFVGenN(2);} +CvBlobTrackFVGen* cvCreateFVGenPV(){return (CvBlobTrackFVGen*)new CvBlobTrackFVGenN(4);} +CvBlobTrackFVGen* cvCreateFVGenPVS(){return (CvBlobTrackFVGen*)new CvBlobTrackFVGenN(5);} +#undef MAX_FV_SIZE + +#define MAX_FV_SIZE 4 +class CvBlobTrackFVGenSS: public CvBlobTrackFVGen +{ +private: + CvBlobSeq m_BlobList; + CvMemStorage* m_pMem; + CvSeq* m_pFVSeq; + float m_FVMax[MAX_FV_SIZE]; + float m_FVMin[MAX_FV_SIZE]; + float m_FVVar[MAX_FV_SIZE]; + int m_Dim; + CvBlob m_BlobSeq[BLOB_NUM]; + int m_Frame; + int m_State; + int m_LastFrame; + int m_ClearFlag; + void Clear() + { + cvClearMemStorage(m_pMem); + m_pFVSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(float)*(m_Dim+1), m_pMem); + m_ClearFlag = 1; + } +public: + CvBlobTrackFVGenSS(int dim = 2 ):m_BlobList(sizeof(DefBlobFVN)) + { + int i; + assert(dim <= MAX_FV_SIZE); + m_Dim = dim; + for(i=0;i0; --i) + { + pFVBlob->BlobSeq[i] = pFVBlob->BlobSeq[i-1]; + } + + pFVBlob->BlobSeq[0] = pBlob[0]; + + if(pFVBlob->FrameNum > BLOB_NUM) + { /* Average velocity: */ + CvBlob* pBlobSeq = pFVBlob->BlobSeq; + float T = (CV_BLOB_WX(pBlob)+CV_BLOB_WY(pBlob))*0.01f; + float AverVx = 0; + float AverVy = 0; + int i; + for(i=1; istate++; + else + pFVBlob->state=0; + } + + if(pFVBlob->state == 5) + { /* Object is stopped: */ + float FV[MAX_FV_SIZE]; + FV[0] = pFVBlob->blob.x; + FV[1] = pFVBlob->blob.y; + FV[2] = pFVBlob->BlobSeq[0].x; + FV[3] = pFVBlob->BlobSeq[0].y; + *(int*)(FV+m_Dim) = CV_BLOB_ID(pBlob); + cvSeqPush( m_pFVSeq, FV ); + } /* Object is stopped. */ + + pFVBlob->FrameNum++; + pFVBlob->LastFrame = m_Frame; + }; /* AddBlob */ + void Process(IplImage* pImg, IplImage* /*pFG*/) + { + int i; + + if(!m_ClearFlag) Clear(); + + for(i=m_BlobList.GetBlobNum();i>0;--i) + { /* Delete unused blob: */ + DefBlobFVN* pFVBlob = (DefBlobFVN*)m_BlobList.GetBlob(i-1); + if(pFVBlob->LastFrame < m_Frame) + { + float FV[MAX_FV_SIZE+1]; + FV[0] = pFVBlob->blob.x; + FV[1] = pFVBlob->blob.y; + FV[2] = pFVBlob->BlobSeq[0].x; + FV[3] = pFVBlob->BlobSeq[0].y; + *(int*)(FV+m_Dim) = CV_BLOB_ID(pFVBlob); + cvSeqPush( m_pFVSeq, FV ); + m_BlobList.DelBlob(i-1); + } + } /* Check next blob in list. */ + + /* Set max min range: */ + m_FVMin[0] = 0; + m_FVMin[1] = 0; + m_FVMin[2] = 0; + m_FVMin[3] = 0; + m_FVMax[0] = (float)(pImg->width-1); + m_FVMax[1] = (float)(pImg->height-1); + m_FVMax[2] = (float)(pImg->width-1); + m_FVMax[3] = (float)(pImg->height-1); + m_FVVar[0] = m_FVMax[0]*0.01f; + m_FVVar[1] = m_FVMax[1]*0.01f; + m_FVVar[2] = m_FVMax[2]*0.01f; + m_FVVar[3] = m_FVMax[3]*0.01f; + + m_Frame++; + m_ClearFlag = 0; + }; + virtual void Release(){delete this;}; + virtual int GetFVSize(){return m_Dim;}; + virtual int GetFVNum() + { + return m_pFVSeq->total; + }; + + virtual float* GetFV(int index, int* pFVID) + { + float* pFV = (float*)cvGetSeqElem( m_pFVSeq, index ); + if(pFVID)pFVID[0] = *(int*)(pFV+m_Dim); + return pFV; + }; + + virtual float* GetFVMin(){return m_FVMin;}; /* returned pointer to array of minimal values of FV, if return 0 then FVrange is not exist */ + virtual float* GetFVMax(){return m_FVMax;}; /* returned pointer to array of maximal values of FV, if return 0 then FVrange is not exist */ + virtual float* GetFVVar(){return m_FVVar;}; /* returned pointer to array of maximal values of FV, if return 0 then FVrange is not exist */ +};/* CvBlobTrackFVGenSS */ + +CvBlobTrackFVGen* cvCreateFVGenSS(){return (CvBlobTrackFVGen*)new CvBlobTrackFVGenSS;} + +/*======================= TRAJECTORY ANALYZER MODULES =====================*/ +/* Trajectory Analyser module */ +#define SPARSE 0 +#define ND 1 +#define BYSIZE -1 +class DefMat +{ +private: + CvSparseMatIterator m_SparseIterator; + CvSparseNode* m_pSparseNode; + int* m_IDXs; + int m_Dim; + +public: + CvSparseMat* m_pSparse; + CvMatND* m_pND; + int m_Volume; + int m_Max; + DefMat(int dim = 0, int* sizes = NULL, int type = SPARSE) + { + /* Create sparse or ND matrix but not both: */ + m_pSparseNode = NULL; + m_pSparse = NULL; + m_pND = NULL; + m_Volume = 0; + m_Max = 0; + m_IDXs = NULL; + m_Dim = 0; + if(dim>0 && sizes != 0) + Realloc(dim, sizes, type); + } + ~DefMat() + { + if(m_pSparse)cvReleaseSparseMat(&m_pSparse); + if(m_pND)cvReleaseMatND(&m_pND); + if(m_IDXs) cvFree(&m_IDXs); + } + + void Realloc(int dim, int* sizes, int type = SPARSE) + { + if(m_pSparse)cvReleaseSparseMat(&m_pSparse); + if(m_pND)cvReleaseMatND(&m_pND); + + if(type == BYSIZE ) + { + int size = 0; + int i; + for(size=1,i=0;i (2<<20)) + { /* if size > 1M */ + type = SPARSE; + } + else + { + type = ND; + } + } /* Define matrix type. */ + + if(type == SPARSE) + { + m_pSparse = cvCreateSparseMat( dim, sizes, CV_32SC1 ); + m_Dim = dim; + } + if(type == ND ) + { + m_pND = cvCreateMatND( dim, sizes, CV_32SC1 ); + cvZero(m_pND); + m_IDXs = (int*)cvAlloc(sizeof(int)*dim); + m_Dim = dim; + } + m_Volume = 0; + m_Max = 0; + } + void Save(const char* File) + { + if(m_pSparse)cvSave(File, m_pSparse ); + if(m_pND)cvSave(File, m_pND ); + } + void Save(CvFileStorage* fs, const char* name) + { + if(m_pSparse) + { + cvWrite(fs, name, m_pSparse ); + } + else if(m_pND) + { + cvWrite(fs, name, m_pND ); + } + } + void Load(const char* File) + { + CvFileStorage* fs = cvOpenFileStorage( File, NULL, CV_STORAGE_READ ); + if(fs) + { + void* ptr; + if(m_pSparse) cvReleaseSparseMat(&m_pSparse); + if(m_pND) cvReleaseMatND(&m_pND); + m_Volume = 0; + m_Max = 0; + ptr = cvLoad(File); + if(ptr && CV_IS_MATND_HDR(ptr)) m_pND = (CvMatND*)ptr; + if(ptr && CV_IS_SPARSE_MAT_HDR(ptr)) m_pSparse = (CvSparseMat*)ptr; + cvReleaseFileStorage(&fs); + } + AfterLoad(); + } /* Load. */ + + void Load(CvFileStorage* fs, CvFileNode* node, const char* name) + { + CvFileNode* n = cvGetFileNodeByName(fs,node,name); + void* ptr = n?cvRead(fs,n):NULL; + if(ptr) + { + if(m_pSparse) cvReleaseSparseMat(&m_pSparse); + if(m_pND) cvReleaseMatND(&m_pND); + m_Volume = 0; + m_Max = 0; + if(CV_IS_MATND_HDR(ptr)) m_pND = (CvMatND*)ptr; + if(CV_IS_SPARSE_MAT_HDR(ptr)) m_pSparse = (CvSparseMat*)ptr; + } + else + { + printf("WARNING!!! Can't load %s matrix\n",name); + } + AfterLoad(); + } /* Load. */ + + void AfterLoad() + { + m_Volume = 0; + m_Max = 0; + if(m_pSparse) + { /* Calculate Volume of loaded hist: */ + CvSparseMatIterator mat_iterator; + CvSparseNode* node = cvInitSparseMatIterator( m_pSparse, &mat_iterator ); + + for( ; node != 0; node = cvGetNextSparseNode( &mat_iterator )) + { + int val = *(int*)CV_NODE_VAL( m_pSparse, node ); /* get value of the element + (assume that the type is CV_32SC1) */ + m_Volume += val; + if(m_Max < val)m_Max = val; + } + } /* Calculate Volume of loaded hist. */ + + if(m_pND) + { /* Calculate Volume of loaded hist: */ + CvMat mat; + double max_val; + double vol; + cvGetMat( m_pND, &mat, NULL, 1 ); + + vol = cvSum(&mat).val[0]; + m_Volume = cvRound(vol); + cvMinMaxLoc( &mat, NULL, &max_val); + m_Max = cvRound(max_val); + /* MUST BE WRITTEN LATER */ + } /* Calculate Volume of loaded hist. */ + } /* AfterLoad. */ + + int* GetPtr(int* indx) + { + if(m_pSparse) return (int*)cvPtrND( m_pSparse, indx, NULL, 1, NULL); + if(m_pND) return (int*)cvPtrND( m_pND, indx, NULL, 1, NULL); + return NULL; + } /* GetPtr. */ + + int GetVal(int* indx) + { + int* p = GetPtr(indx); + if(p)return p[0]; + return -1; + } /* GetVal. */ + + int Add(int* indx, int val) + { + int NewVal; + int* pVal = GetPtr(indx); + if(pVal == NULL) return -1; + pVal[0] += val; + NewVal = pVal[0]; + m_Volume += val; + if(m_Max < NewVal)m_Max = NewVal; + return NewVal; + } /* Add. */ + + void Add(DefMat* pMatAdd) + { + int* pIDXS = NULL; + int Val = 0; + for(Val = pMatAdd->GetNext(&pIDXS, 1 );pIDXS;Val=pMatAdd->GetNext(&pIDXS, 0 )) + { + Add(pIDXS,Val); + } + } /* Add. */ + + int SetMax(int* indx, int val) + { + int NewVal; + int* pVal = GetPtr(indx); + if(pVal == NULL) return -1; + if(val > pVal[0]) + { + m_Volume += val-pVal[0]; + pVal[0] = val; + } + NewVal = pVal[0]; + if(m_Max < NewVal)m_Max = NewVal; + return NewVal; + } /* Add. */ + + int GetNext(int** pIDXS, int init = 0) + { + int Val = 0; + pIDXS[0] = NULL; + if(m_pSparse) + { + m_pSparseNode = (init || m_pSparseNode==NULL)? + cvInitSparseMatIterator( m_pSparse, &m_SparseIterator ): + cvGetNextSparseNode( &m_SparseIterator ); + + if(m_pSparseNode) + { + int* pVal = (int*)CV_NODE_VAL( m_pSparse, m_pSparseNode ); + if(pVal)Val = pVal[0]; + pIDXS[0] = CV_NODE_IDX( m_pSparse, m_pSparseNode ); + } + }/* Sparse matrix. */ + + if(m_pND) + { + int i; + if(init) + { + for(i=0;i0) + break; + m_IDXs[i] = cvGetDimSize( m_pND, i )-1; + } + if(i==m_Dim) + { + pIDXS[0] = NULL; + } + else + { + pIDXS[0] = m_IDXs; + Val = GetVal(m_IDXs); + } + + } /* Get next ND. */ + + } /* Sparse matrix. */ + + return Val; + + }; /* GetNext. */ +}; + +#define FV_NUM 10 +#define FV_SIZE 10 +typedef struct DefTrackFG +{ + CvBlob blob; + // CvBlobTrackFVGen* pFVGen; + int LastFrame; + float state; + DefMat* pHist; +} DefTrackFG; +class CvBlobTrackAnalysisHist : public CvBlobTrackAnalysis +{ + /*---------------- Internal functions: --------------------*/ +private: + int m_BinNumParam; + int m_SmoothRadius; + const char* m_SmoothKernel; + float m_AbnormalThreshold; + int m_TrackNum; + int m_Frame; + int m_BinNum; + char m_DataFileName[1024]; + int m_Dim; + int* m_Sizes; + DefMat m_HistMat; + int m_HistVolumeSaved; + int* m_pFVi; + int* m_pFViVar; + int* m_pFViVarRes; + CvBlobSeq m_TrackFGList; + //CvBlobTrackFVGen* (*m_CreateFVGen)(); + CvBlobTrackFVGen* m_pFVGen; + void SaveHist() + { + if(m_DataFileName[0]) + { + m_HistMat.Save(m_DataFileName); + m_HistVolumeSaved = m_HistMat.m_Volume; + } + }; + void LoadHist() + { + if(m_DataFileName[0])m_HistMat.Load(m_DataFileName); + m_HistVolumeSaved = m_HistMat.m_Volume; + } + void AllocData() + { /* AllocData: */ + m_pFVi = (int*)cvAlloc(sizeof(int)*m_Dim); + m_pFViVar = (int*)cvAlloc(sizeof(int)*m_Dim); + m_pFViVarRes = (int*)cvAlloc(sizeof(int)*m_Dim); + m_Sizes = (int*)cvAlloc(sizeof(int)*m_Dim); + + { /* Create init sparce matrix: */ + int i; + for(i=0;i0;--i) + { + //DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlob(i-1); + // pF->pFVGen->Release(); + m_TrackFGList.DelBlob(i-1); + } + cvFree(&m_pFVi); + cvFree(&m_pFViVar); + cvFree(&m_pFViVarRes); + cvFree(&m_Sizes); + } /* FreeData. */ + + virtual void ParamUpdate() + { + if(m_BinNum != m_BinNumParam) + { + FreeData(); + m_BinNum = m_BinNumParam; + AllocData(); + } + } +public: + CvBlobTrackAnalysisHist(CvBlobTrackFVGen* (*createFVGen)()):m_TrackFGList(sizeof(DefTrackFG)) + { + m_pFVGen = createFVGen(); + m_Dim = m_pFVGen->GetFVSize(); + m_Frame = 0; + m_pFVi = 0; + m_TrackNum = 0; + m_BinNum = 32; + m_DataFileName[0] = 0; + + m_AbnormalThreshold = 0.02f; + AddParam("AbnormalThreshold",&m_AbnormalThreshold); + CommentParam("AbnormalThreshold","If trajectory histogram value is lesst then then trajectory is abnormal"); + + m_SmoothRadius = 1; + AddParam("SmoothRadius",&m_SmoothRadius); + CommentParam("AbnormalThreshold","Radius (in bins) for histogram smoothing"); + + m_SmoothKernel = "L"; + AddParam("SmoothKernel",&m_SmoothKernel); + CommentParam("SmoothKernel","L - Linear, G - Gaussian"); + + + m_BinNumParam = m_BinNum; + AddParam("BinNum",&m_BinNumParam); + CommentParam("BinNum","Number of bin for each dimention of feature vector"); + + AllocData(); + SetModuleName("Hist"); + + } /* Constructor. */ + + ~CvBlobTrackAnalysisHist() + { + SaveHist(); + FreeData(); + m_pFVGen->Release(); + } /* Destructor. */ + + /*----------------- Interface: --------------------*/ + virtual void AddBlob(CvBlob* pBlob) + { + DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlobByID(CV_BLOB_ID(pBlob)); + if(pF == NULL) + { /* create new filter */ + DefTrackFG F; + F.state = 0; + F.blob = pBlob[0]; + F.LastFrame = m_Frame; + // F.pFVGen = m_CreateFVGen(); + F.pHist = new DefMat(m_Dim,m_Sizes,SPARSE); + m_TrackFGList.AddBlob((CvBlob*)&F); + pF = (DefTrackFG*)m_TrackFGList.GetBlobByID(CV_BLOB_ID(pBlob)); + } + + assert(pF); + pF->blob = pBlob[0]; + pF->LastFrame = m_Frame; + m_pFVGen->AddBlob(pBlob); + }; + virtual void Process(IplImage* pImg, IplImage* pFG) + { + int i; + m_pFVGen->Process(pImg, pFG); + int SK = m_SmoothKernel[0]; + + for(i=0; iGetFVNum(); ++i) + { + int BlobID = 0; + float* pFV = m_pFVGen->GetFV(i,&BlobID); + float* pFVMax = m_pFVGen->GetFVMax(); + float* pFVMin = m_pFVGen->GetFVMin(); + DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlobByID(BlobID); + int HistVal = 1; + + if(pFV==NULL) break; + + pF->LastFrame = m_Frame; + + { /* Binarize FV: */ + int j; + for(j=0; jf0); + index = cvRound((m_BinNum-1)*(pFV[j]-f0)/(f1-f0)); + if(index<0)index=0; + if(index>=m_BinNum)index=m_BinNum-1; + m_pFVi[j] = index; + } + } + + HistVal = m_HistMat.GetVal(m_pFVi);/* get bin value*/ + pF->state = 0; + { /* Calculate state: */ + float T = m_HistMat.m_Max*m_AbnormalThreshold; /* calc threshold */ + + if(m_TrackNum>0) T = 256.0f * m_TrackNum*m_AbnormalThreshold; + if(T>0) + { + pF->state = (T - HistVal)/(T*0.2f) + 0.5f; + } + if(pF->state<0)pF->state=0; + if(pF->state>1)pF->state=1; + } + + { /* If it is a new FV then add it to trajectory histogram: */ + int i,flag = 1; + int r = m_SmoothRadius; + + // printf("BLob %3d NEW FV [", CV_BLOB_ID(pF)); + // for(i=0;i=m_BinNum) good= 0; + dist += m_pFViVar[i]*m_pFViVar[i]; + }/* Calculate next dimension. */ + + if(SK=='G' || SK=='g') + { + double dist2 = dist/(r*r); + HistAdd = cvRound(256*exp(-dist2)); /* Hist Add for (dist=1) = 25.6*/ + } + else if(SK=='L' || SK=='l') + { + dist = (float)(sqrt(dist)/(r+1)); + HistAdd = cvRound(256*(1-dist)); + } + else + { + HistAdd = 255; /* Flat smoothing. */ + } + + if(good && HistAdd>0) + { /* Update histogram: */ + assert(pF->pHist); + pF->pHist->SetMax(m_pFViVarRes, HistAdd); + } /* Update histogram. */ + + for(i=0; i0; --i) + { /* Add histogram and delete blob from list: */ + DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlob(i-1); + if(pF->LastFrame+3 < m_Frame && pF->pHist) + { + m_HistMat.Add(pF->pHist); + delete pF->pHist; + m_TrackNum++; + m_TrackFGList.DelBlob(i-1); + } + }/* next blob */ + } + + m_Frame++; + + if(m_Wnd) + { /* Debug output: */ + int* idxs = NULL; + int Val = 0; + IplImage* pI = cvCloneImage(pImg); + + cvZero(pI); + + for(Val = m_HistMat.GetNext(&idxs,1); idxs; Val=m_HistMat.GetNext(&idxs,0)) + { /* Draw all elements: */ + float vf; + int x,y; + + if(!idxs) break; + if(Val == 0) continue; + + vf = (float)Val/(m_HistMat.m_Max?m_HistMat.m_Max:1); + x = cvRound((float)(pI->width-1)*(float)idxs[0] / (float)m_BinNum); + y = cvRound((float)(pI->height-1)*(float)idxs[1] / (float)m_BinNum); + + cvCircle(pI, cvPoint(x,y), cvRound(vf*pI->height/(m_BinNum*2)),CV_RGB(255,0,0),CV_FILLED); + if(m_Dim > 3) + { + int dx = -2*(idxs[2]-m_BinNum/2); + int dy = -2*(idxs[3]-m_BinNum/2); + cvLine(pI,cvPoint(x,y),cvPoint(x+dx,y+dy),CV_RGB(0,cvRound(vf*255),1)); + } + if( m_Dim==4 && + m_pFVGen->GetFVMax()[0]==m_pFVGen->GetFVMax()[2] && + m_pFVGen->GetFVMax()[1]==m_pFVGen->GetFVMax()[3]) + { + int x = cvRound((float)(pI->width-1)*(float)idxs[2] / (float)m_BinNum); + int y = cvRound((float)(pI->height-1)*(float)idxs[3] / (float)m_BinNum); + cvCircle(pI, cvPoint(x,y), cvRound(vf*pI->height/(m_BinNum*2)),CV_RGB(0,0,255),CV_FILLED); + } + } /* Draw all elements. */ + + for(i=m_TrackFGList.GetBlobNum();i>0;--i) + { + DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlob(i-1); + DefMat* pHist = pF?pF->pHist:NULL; + + if(pHist==NULL) continue; + + for(Val = pHist->GetNext(&idxs,1);idxs;Val=pHist->GetNext(&idxs,0)) + { /* Draw all elements: */ + float vf; + int x,y; + + if(!idxs) break; + if(Val == 0) continue; + + vf = (float)Val/(pHist->m_Max?pHist->m_Max:1); + x = cvRound((float)(pI->width-1)*(float)idxs[0] / (float)m_BinNum); + y = cvRound((float)(pI->height-1)*(float)idxs[1] / (float)m_BinNum); + + cvCircle(pI, cvPoint(x,y), cvRound(2*vf),CV_RGB(0,0,cvRound(255*vf)),CV_FILLED); + if(m_Dim > 3) + { + int dx = -2*(idxs[2]-m_BinNum/2); + int dy = -2*(idxs[3]-m_BinNum/2); + cvLine(pI,cvPoint(x,y),cvPoint(x+dx,y+dy),CV_RGB(0,0,255)); + } + if( m_Dim==4 && + m_pFVGen->GetFVMax()[0]==m_pFVGen->GetFVMax()[2] && + m_pFVGen->GetFVMax()[1]==m_pFVGen->GetFVMax()[3]) + { /* if SS feature vector */ + int x = cvRound((float)(pI->width-1)*(float)idxs[2] / (float)m_BinNum); + int y = cvRound((float)(pI->height-1)*(float)idxs[3] / (float)m_BinNum); + cvCircle(pI, cvPoint(x,y), cvRound(vf*pI->height/(m_BinNum*2)),CV_RGB(0,0,255),CV_FILLED); + } + } /* Draw all elements. */ + } /* Next track. */ + + //cvNamedWindow("Hist",0); + //cvShowImage("Hist", pI); + cvReleaseImage(&pI); + } + }; + + float GetState(int BlobID) + { + DefTrackFG* pF = (DefTrackFG*)m_TrackFGList.GetBlobByID(BlobID); + return pF?pF->state:0.0f; + }; + + /* Return 0 if trajectory is normal; + rreturn >0 if trajectory abnormal. */ + virtual const char* GetStateDesc(int BlobID) + { + if(GetState(BlobID)>0.5) return "abnormal"; + return NULL; + } + + virtual void SetFileName(const char* DataBaseName) + { + if(m_HistMat.m_Volume!=m_HistVolumeSaved)SaveHist(); + m_DataFileName[0] = 0; + + if(DataBaseName) + { + strncpy(m_DataFileName,DataBaseName,1000); + strcat(m_DataFileName, ".yml"); + } + LoadHist(); + }; + + virtual void SaveState(CvFileStorage* fs) + { + int b, bN = m_TrackFGList.GetBlobNum(); + cvWriteInt(fs,"BlobNum",bN); + cvStartWriteStruct(fs,"BlobList",CV_NODE_SEQ); + + for(b=0; bblob), "ffffi"); + cvWriteInt(fs,"LastFrame",pF->LastFrame); + cvWriteReal(fs,"State",pF->state); + pF->pHist->Save(fs, "Hist"); + cvEndWriteStruct(fs); + } + cvEndWriteStruct(fs); + m_HistMat.Save(fs, "Hist"); + }; + + virtual void LoadState(CvFileStorage* fs, CvFileNode* node) + { + CvFileNode* pBLN = cvGetFileNodeByName(fs,node,"BlobList"); + + if(pBLN && CV_NODE_IS_SEQ(pBLN->tag)) + { + int b, bN = pBLN->data.seq->total; + for(b=0; bdata.seq,b); + + assert(pBN); + cvReadStructByName(fs, pBN, "Blob", &Blob, "ffffi"); + AddBlob(&Blob); + pF = (DefTrackFG*)m_TrackFGList.GetBlobByID(Blob.ID); + if(pF==NULL) continue; + assert(pF); + pF->state = (float)cvReadIntByName(fs,pBN,"State",cvRound(pF->state)); + assert(pF->pHist); + pF->pHist->Load(fs,pBN,"Hist"); + } + } + + m_HistMat.Load(fs, node, "Hist"); + }; /* LoadState */ + + + virtual void Release(){ delete this; }; + +}; + + + +CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisHistP() +{return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisHist(cvCreateFVGenP);} + +CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisHistPV() +{return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisHist(cvCreateFVGenPV);} + +CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisHistPVS() +{return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisHist(cvCreateFVGenPVS);} + +CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisHistSS() +{return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisHist(cvCreateFVGenSS);} + +typedef struct DefTrackSVM +{ + CvBlob blob; + // CvBlobTrackFVGen* pFVGen; + int LastFrame; + float state; + CvBlob BlobLast; + CvSeq* pFVSeq; + CvMemStorage* pMem; +} DefTrackSVM; + +class CvBlobTrackAnalysisSVM : public CvBlobTrackAnalysis +{ + /*---------------- Internal functions: --------------------*/ +private: + CvMemStorage* m_pMem; + int m_TrackNum; + int m_Frame; + char m_DataFileName[1024]; + int m_Dim; + float* m_pFV; + //CvStatModel* m_pStatModel; + void* m_pStatModel; + CvBlobSeq m_Tracks; + CvMat* m_pTrainData; + int m_LastTrainDataSize; + // CvBlobTrackFVGen* (*m_CreateFVGen)(); + CvBlobTrackFVGen* m_pFVGen; + float m_NU; + float m_RBFWidth; + IplImage* m_pStatImg; /* for debug purpose */ + CvSize m_ImgSize; + void RetrainStatModel() + { + ///////// !!!!! TODO !!!!! Repair ///////////// +#if 0 + float nu = 0; + CvSVMModelParams SVMParams = {0}; + CvStatModel* pM = NULL; + + + memset(&SVMParams,0,sizeof(SVMParams)); + SVMParams.svm_type = CV_SVM_ONE_CLASS; + SVMParams.kernel_type = CV_SVM_RBF; + SVMParams.gamma = 2.0/(m_RBFWidth*m_RBFWidth); + SVMParams.nu = m_NU; + SVMParams.degree = 3; + SVMParams.criteria = cvTermCriteria(CV_TERMCRIT_EPS, 100, 1e-3 ); + SVMParams.C = 1; + SVMParams.p = 0.1; + + + if(m_pTrainData == NULL) return; + { + int64 TickCount = cvGetTickCount(); + printf("Frame: %d\n Retrain SVM\nData Size = %d\n",m_Frame, m_pTrainData->rows); + pM = cvTrainSVM( m_pTrainData,CV_ROW_SAMPLE, NULL, (CvStatModelParams*)&SVMParams, NULL, NULL); + TickCount = cvGetTickCount() - TickCount ; + printf("SV Count = %d\n",((CvSVMModel*)pM)->sv_total); + printf("Processing Time = %.1f(ms)\n",TickCount/(1000*cvGetTickFrequency())); + + } + if(pM==NULL) return; + if(m_pStatModel) cvReleaseStatModel(&m_pStatModel); + m_pStatModel = pM; + + if(m_pTrainData && m_Wnd) + { + float MaxVal = 0; + IplImage* pW = cvCreateImage(m_ImgSize,IPL_DEPTH_32F,1); + IplImage* pI = cvCreateImage(m_ImgSize,IPL_DEPTH_8U,1); + float* pFVVar = m_pFVGen->GetFVVar(); + int i; + cvZero(pW); + + for(i=0; irows; ++i) + { /* Draw all elements: */ + float* pFV = (float*)(m_pTrainData->data.ptr + m_pTrainData->step*i); + int x = cvRound(pFV[0]*pFVVar[0]); + int y = cvRound(pFV[1]*pFVVar[1]); + float r; + + if(x<0)x=0; + if(x>=pW->width)x=pW->width-1; + if(y<0)y=0; + if(y>=pW->height)y=pW->height-1; + + r = ((float*)(pW->imageData + y*pW->widthStep))[x]; + r++; + ((float*)(pW->imageData + y*pW->widthStep))[x] = r; + + if(r>MaxVal)MaxVal=r; + } /* Next point. */ + + if(MaxVal>0)cvConvertScale(pW,pI,255/MaxVal,0); + cvNamedWindow("SVMData",0); + cvShowImage("SVMData",pI); + cvSaveImage("SVMData.bmp",pI); + cvReleaseImage(&pW); + cvReleaseImage(&pI); + } /* Prepare for debug. */ + + if(m_pStatModel && m_Wnd && m_Dim == 2) + { + float* pFVVar = m_pFVGen->GetFVVar(); + int x,y; + if(m_pStatImg==NULL) + { + m_pStatImg = cvCreateImage(m_ImgSize,IPL_DEPTH_8U,1); + } + cvZero(m_pStatImg); + + for(y=0; yheight; y+=1) for(x=0; xwidth; x+=1) + { /* Draw all elements: */ + float res; + uchar* pData = (uchar*)m_pStatImg->imageData + x + y*m_pStatImg->widthStep; + CvMat FVmat; + float xy[2] = {x/pFVVar[0],y/pFVVar[1]}; + cvInitMatHeader( &FVmat, 1, 2, CV_32F, xy ); + res = cvStatModelPredict( m_pStatModel, &FVmat, NULL ); + pData[0]=((res>0.5)?255:0); + } /* Next point. */ + + cvNamedWindow("SVMMask",0); + cvShowImage("SVMMask",m_pStatImg); + cvSaveImage("SVMMask.bmp",m_pStatImg); + } /* Prepare for debug. */ +#endif + }; + void SaveStatModel() + { + if(m_DataFileName[0]) + { + if(m_pTrainData)cvSave(m_DataFileName, m_pTrainData); + } + }; + void LoadStatModel() + { + if(m_DataFileName[0]) + { + CvMat* pTrainData = (CvMat*)cvLoad(m_DataFileName); + if(CV_IS_MAT(pTrainData) && pTrainData->width == m_Dim) + { + if(m_pTrainData) cvReleaseMat(&m_pTrainData); + m_pTrainData = pTrainData; + RetrainStatModel(); + } + } + } +public: + CvBlobTrackAnalysisSVM(CvBlobTrackFVGen* (*createFVGen)()):m_Tracks(sizeof(DefTrackSVM)) + { + m_pFVGen = createFVGen(); + m_Dim = m_pFVGen->GetFVSize(); + m_pFV = (float*)cvAlloc(sizeof(float)*m_Dim); + m_Frame = 0; + m_TrackNum = 0; + m_pTrainData = NULL; + m_pStatModel = NULL; + m_DataFileName[0] = 0; + m_pStatImg = NULL; + m_LastTrainDataSize = 0; + + m_NU = 0.2f; + AddParam("Nu",&m_NU); + CommentParam("Nu","Parameters that tunes SVM border elastic"); + + m_RBFWidth = 1; + AddParam("RBFWidth",&m_RBFWidth); + CommentParam("RBFWidth","Parameters that tunes RBF kernel function width."); + + SetModuleName("SVM"); + + } /* Constructor. */ + + ~CvBlobTrackAnalysisSVM() + { + int i; + SaveStatModel(); + for(i=m_Tracks.GetBlobNum();i>0;--i) + { + DefTrackSVM* pF = (DefTrackSVM*)m_Tracks.GetBlob(i-1); + if(pF->pMem) cvReleaseMemStorage(&pF->pMem); + //pF->pFVGen->Release(); + } + if(m_pStatImg)cvReleaseImage(&m_pStatImg); + cvFree(&m_pFV); + } /* Destructor. */ + + /*----------------- Interface: --------------------*/ + virtual void AddBlob(CvBlob* pBlob) + { + DefTrackSVM* pF = (DefTrackSVM*)m_Tracks.GetBlobByID(CV_BLOB_ID(pBlob)); + + m_pFVGen->AddBlob(pBlob); + + if(pF == NULL) + { /* Create new record: */ + DefTrackSVM F; + F.state = 0; + F.blob = pBlob[0]; + F.LastFrame = m_Frame; + //F.pFVGen = m_CreateFVGen(); + F.pMem = cvCreateMemStorage(); + F.pFVSeq = cvCreateSeq(0,sizeof(CvSeq),sizeof(float)*m_Dim,F.pMem); + + F.BlobLast.x = -1; + F.BlobLast.y = -1; + F.BlobLast.w = -1; + F.BlobLast.h = -1; + m_Tracks.AddBlob((CvBlob*)&F); + pF = (DefTrackSVM*)m_Tracks.GetBlobByID(CV_BLOB_ID(pBlob)); + } + + assert(pF); + pF->blob = pBlob[0]; + pF->LastFrame = m_Frame; + }; + + virtual void Process(IplImage* pImg, IplImage* pFG) + { + int i; + float* pFVVar = m_pFVGen->GetFVVar(); + + m_pFVGen->Process(pImg, pFG); + m_ImgSize = cvSize(pImg->width,pImg->height); + + for(i=m_pFVGen->GetFVNum(); i>0; --i) + { + int BlobID = 0; + float* pFV = m_pFVGen->GetFV(i,&BlobID); + DefTrackSVM* pF = (DefTrackSVM*)m_Tracks.GetBlobByID(BlobID); + + if(pF && pFV) + { /* Process: */ + float dx,dy; + CvMat FVmat; + + pF->state = 0; + + if(m_pStatModel) + { + int j; + for(j=0; jstate = cvStatModelPredict( m_pStatModel, &FVmat, NULL )<0.5; + pF->state = 1.f; + } + + dx = (pF->blob.x - pF->BlobLast.x); + dy = (pF->blob.y - pF->BlobLast.y); + + if(pF->BlobLast.x<0 || (dx*dx+dy*dy) >= 2*2) + { /* Add feature vector to train data base: */ + pF->BlobLast = pF->blob; + cvSeqPush(pF->pFVSeq,pFV); + } + } /* Process one blob. */ + } /* Next FV. */ + + for(i=m_Tracks.GetBlobNum(); i>0; --i) + { /* Check each blob record: */ + DefTrackSVM* pF = (DefTrackSVM*)m_Tracks.GetBlob(i-1); + + if(pF->LastFrame+3 < m_Frame ) + { /* Retrain stat model and delete blob filter: */ + int mult = 1+m_Dim; + int old_height = m_pTrainData?m_pTrainData->height:0; + int height = old_height + pF->pFVSeq->total*mult; + CvMat* pTrainData = cvCreateMat(height, m_Dim, CV_32F); + int j; + if(m_pTrainData && pTrainData) + { /* Create new train data matrix: */ + int h = pTrainData->height; + pTrainData->height = MIN(pTrainData->height, m_pTrainData->height); + cvCopy(m_pTrainData,pTrainData); + pTrainData->height = h; + } + + for(j=0; jpFVSeq->total; ++j) + { /* Copy new data to train data: */ + float* pFVVar = m_pFVGen->GetFVVar(); + float* pFV = (float*)cvGetSeqElem(pF->pFVSeq,j); + int k; + + for(k=0; k0) + { /* Variate: */ + for(t=0; tpMem); + m_TrackNum++; + m_Tracks.DelBlob(i-1); + + } /* End delete. */ + } /* Next track. */ + + /* Retrain data each 1 minute if new data exist: */ + if(m_Frame%(25*60) == 0 && m_pTrainData && m_pTrainData->rows > m_LastTrainDataSize) + { + RetrainStatModel(); + } + + m_Frame++; + + if(m_Wnd && m_Dim==2) + { /* Debug output: */ + int x,y; + IplImage* pI = cvCloneImage(pImg); + + if(m_pStatModel && m_pStatImg) + + for(y=0; yheight; y+=2) + { + uchar* pStatData = (uchar*)m_pStatImg->imageData + y*m_pStatImg->widthStep; + uchar* pData = (uchar*)pI->imageData + y*pI->widthStep; + + for(x=0;xwidth;x+=2) + { /* Draw all elements: */ + int d = pStatData[x]; + d = (d<<8) | (d^0xff); + *(ushort*)(pData + x*3) = (ushort)d; + } + } /* Next line. */ + + //cvNamedWindow("SVMMap",0); + //cvShowImage("SVMMap", pI); + cvReleaseImage(&pI); + } /* Debug output. */ + }; + float GetState(int BlobID) + { + DefTrackSVM* pF = (DefTrackSVM*)m_Tracks.GetBlobByID(BlobID); + return pF?pF->state:0.0f; + }; + + /* Return 0 if trajectory is normal; + return >0 if trajectory abnormal. */ + virtual const char* GetStateDesc(int BlobID) + { + if(GetState(BlobID)>0.5) return "abnormal"; + return NULL; + } + + virtual void SetFileName(char* DataBaseName) + { + if(m_pTrainData)SaveStatModel(); + m_DataFileName[0] = 0; + if(DataBaseName) + { + strncpy(m_DataFileName,DataBaseName,1000); + strcat(m_DataFileName, ".yml"); + } + LoadStatModel(); + }; + + + virtual void Release(){ delete this; }; + +}; /* CvBlobTrackAnalysisSVM. */ + + +CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisSVMP() +{return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisSVM(cvCreateFVGenP);} + +CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisSVMPV() +{return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisSVM(cvCreateFVGenPV);} + +CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisSVMPVS() +{return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisSVM(cvCreateFVGenPVS);} + +CvBlobTrackAnalysis* cvCreateModuleBlobTrackAnalysisSVMSS() +{return (CvBlobTrackAnalysis*) new CvBlobTrackAnalysisSVM(cvCreateFVGenSS);}