opencv/modules/legacy/src/blobtrackingauto.cpp

482 lines
15 KiB
C++
Raw Normal View History

/*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
//
// Copyright (C) 2000, Intel Corporation, 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*/
/*
This file contain simple implementation of BlobTrackerAuto virtual interface
This module just connected other low level 3 modules
(foreground estimator + BlobDetector + BlobTracker)
and some simple code to detect "lost tracking"
The track is lost when integral of foreground mask image by blob area has low value
*/
#include "precomp.hpp"
#include <time.h>
/* list of Blob Detection modules */
CvBlobDetector* cvCreateBlobDetectorSimple();
/* Get frequency for each module time working estimation: */
static double FREQ = 1000*cvGetTickFrequency();
#if 1
#define COUNTNUM 100
#define TIME_BEGIN() \
{\
static double _TimeSum = 0;\
static int _Count = 0;\
static int _CountBlob = 0;\
int64 _TickCount = cvGetTickCount();\
#define TIME_END(_name_,_BlobNum_) \
_Count++;\
_CountBlob+=_BlobNum_;\
_TimeSum += (cvGetTickCount()-_TickCount)/FREQ;\
if(m_TimesFile)if(_Count%COUNTNUM==0)\
{ \
FILE* out = fopen(m_TimesFile,"at");\
if(out)\
{\
fprintf(out,"ForFrame Frame: %d %s %f on %f blobs\n",_Count,_name_, _TimeSum/COUNTNUM,((float)_CountBlob)/COUNTNUM);\
if(_CountBlob>0)fprintf(out,"ForBlob Frame: %d %s - %f\n",_Count,_name_, _TimeSum/_CountBlob);\
fclose(out);\
}\
_TimeSum = 0;\
_CountBlob = 0;\
}\
}
#else
#define TIME_BEGIN()
#define TIME_END(_name_)
#endif
/* Special extended blob structure for auto blob tracking: */
typedef struct CvBlobTrackAuto
{
CvBlob blob;
int BadFrames;
} CvBlobTrackAuto;
class CvBlobTrackerAuto1: public CvBlobTrackerAuto
{
public:
CvBlobTrackerAuto1(CvBlobTrackerAutoParam1* param);
~CvBlobTrackerAuto1();
CvBlob* GetBlob(int index){return m_BlobList.GetBlob(index);};
CvBlob* GetBlobByID(int ID){return m_BlobList.GetBlobByID(ID);};
int GetBlobNum(){return m_BlobList.GetBlobNum();};
virtual IplImage* GetFGMask(){return m_pFGMask;};
float GetState(int BlobID){return m_pBTA?m_pBTA->GetState(BlobID):0;};
const char* GetStateDesc(int BlobID){return m_pBTA?m_pBTA->GetStateDesc(BlobID):NULL;};
/* Return 0 if trajectory is normal;
return >0 if trajectory abnormal. */
void Process(IplImage* pImg, IplImage* pMask = NULL);
void Release(){delete this;};
private:
IplImage* m_pFGMask;
int m_FGTrainFrames;
CvFGDetector* m_pFG; /* Pointer to foreground mask detector module. */
CvBlobTracker* m_pBT; /* Pointer to Blob tracker module. */
int m_BTDel;
int m_BTReal;
CvBlobDetector* m_pBD; /* Pointer to Blob detector module. */
int m_BDDel;
CvBlobTrackGen* m_pBTGen;
CvBlobTrackPostProc* m_pBTPostProc;
int m_UsePPData;
CvBlobTrackAnalysis* m_pBTA; /* Blob trajectory analyser. */
CvBlobSeq m_BlobList;
int m_FrameCount;
int m_NextBlobID;
const char* m_TimesFile;
public:
virtual void SaveState(CvFileStorage* fs)
{
cvWriteInt(fs,"FrameCount",m_FrameCount);
cvWriteInt(fs,"NextBlobID",m_NextBlobID);
m_BlobList.Write(fs,"BlobList");
};
virtual void LoadState(CvFileStorage* fs, CvFileNode* node)
{
CvFileNode* BlobListNode = cvGetFileNodeByName(fs,node,"BlobList");
m_FrameCount = cvReadIntByName(fs,node, "FrameCount", m_FrameCount);
m_NextBlobID = cvReadIntByName(fs,node, "NextBlobID", m_NextBlobID);
if(BlobListNode)
{
m_BlobList.Load(fs,BlobListNode);
}
};
};
/* Auto Blob tracker creater (sole interface function for this file) */
CvBlobTrackerAuto* cvCreateBlobTrackerAuto1(CvBlobTrackerAutoParam1* param)
{
return (CvBlobTrackerAuto*)new CvBlobTrackerAuto1(param);
}
/* Constructor of auto blob tracker: */
CvBlobTrackerAuto1::CvBlobTrackerAuto1(CvBlobTrackerAutoParam1* param):m_BlobList(sizeof(CvBlobTrackAuto))
{
m_BlobList.AddFormat("i");
m_TimesFile = NULL;
AddParam("TimesFile",&m_TimesFile);
m_NextBlobID = 0;
m_pFGMask = NULL;
m_FrameCount = 0;
m_FGTrainFrames = param?param->FGTrainFrames:0;
m_pFG = param?param->pFG:0;
m_BDDel = 0;
m_pBD = param?param->pBD:NULL;
m_BTDel = 0;
m_pBT = param?param->pBT:NULL;;
m_BTReal = m_pBT?m_pBT->IsModuleName("BlobTrackerReal"):0;
m_pBTGen = param?param->pBTGen:NULL;
m_pBTA = param?param->pBTA:NULL;
m_pBTPostProc = param?param->pBTPP:NULL;
m_UsePPData = param?param->UsePPData:0;
/* Create default submodules: */
if(m_pBD==NULL)
{
m_pBD = cvCreateBlobDetectorSimple();
m_BDDel = 1;
}
if(m_pBT==NULL)
{
m_pBT = cvCreateBlobTrackerMS();
m_BTDel = 1;
}
SetModuleName("Auto1");
} /* CvBlobTrackerAuto1::CvBlobTrackerAuto1 */
/* Destructor for auto blob tracker: */
CvBlobTrackerAuto1::~CvBlobTrackerAuto1()
{
if(m_BDDel)m_pBD->Release();
if(m_BTDel)m_pBT->Release();
}
void CvBlobTrackerAuto1::Process(IplImage* pImg, IplImage* pMask)
{
int CurBlobNum = 0;
IplImage* pFG = pMask;
/* Bump frame counter: */
m_FrameCount++;
if(m_TimesFile)
{
static int64 TickCount = cvGetTickCount();
static double TimeSum = 0;
static int Count = 0;
Count++;
if(Count%100==0)
{
#ifndef WINCE
time_t ltime;
time( &ltime );
2012-10-17 07:18:30 +08:00
char* stime = ctime( &ltime );
#else
2012-10-17 07:18:30 +08:00
/* WINCE does not have above POSIX functions (time,ctime) */
const char* stime = " wince ";
#endif
FILE* out = fopen(m_TimesFile,"at");
double Time;
TickCount = cvGetTickCount()-TickCount;
Time = TickCount/FREQ;
2012-03-17 17:22:31 +08:00
TimeSum += Time;
if(out){fprintf(out,"- %sFrame: %d ALL_TIME - %f\n",stime,Count,TimeSum/1000);fclose(out);}
TimeSum = 0;
TickCount = cvGetTickCount();
}
}
/* Update BG model: */
TIME_BEGIN()
if(m_pFG)
{ /* If FG detector is needed: */
m_pFG->Process(pImg);
pFG = m_pFG->GetMask();
} /* If FG detector is needed. */
TIME_END("FGDetector",-1)
m_pFGMask = pFG; /* For external use. */
/*if(m_pFG && m_pFG->GetParam("DebugWnd") == 1)
{// debug foreground result
IplImage *pFG = m_pFG->GetMask();
if(pFG)
{
cvNamedWindow("FG",0);
cvShowImage("FG", pFG);
}
}*/
/* Track blobs: */
TIME_BEGIN()
if(m_pBT)
{
m_pBT->Process(pImg, pFG);
for(int i=m_BlobList.GetBlobNum(); i>0; --i)
{ /* Update data of tracked blob list: */
CvBlob* pB = m_BlobList.GetBlob(i-1);
int BlobID = CV_BLOB_ID(pB);
int idx = m_pBT->GetBlobIndexByID(BlobID);
m_pBT->ProcessBlob(idx, pB, pImg, pFG);
pB->ID = BlobID;
}
CurBlobNum = m_pBT->GetBlobNum();
}
TIME_END("BlobTracker",CurBlobNum)
/* This part should be removed: */
if(m_BTReal && m_pBT)
{ /* Update blob list (detect new blob for real blob tracker): */
for(int i=m_pBT->GetBlobNum(); i>0; --i)
{ /* Update data of tracked blob list: */
CvBlob* pB = m_pBT->GetBlob(i-1);
if(pB && m_BlobList.GetBlobByID(CV_BLOB_ID(pB)) == NULL )
{
CvBlobTrackAuto NewB;
NewB.blob = pB[0];
NewB.BadFrames = 0;
m_BlobList.AddBlob((CvBlob*)&NewB);
}
} /* Next blob. */
/* Delete blobs: */
for(int i=m_BlobList.GetBlobNum(); i>0; --i)
{ /* Update tracked-blob list: */
CvBlob* pB = m_BlobList.GetBlob(i-1);
if(pB && m_pBT->GetBlobByID(CV_BLOB_ID(pB)) == NULL )
{
m_BlobList.DelBlob(i-1);
}
} /* Next blob. */
} /* Update bloblist. */
TIME_BEGIN()
if(m_pBTPostProc)
{ /* Post-processing module: */
for(int i=m_BlobList.GetBlobNum(); i>0; --i)
{ /* Update tracked-blob list: */
CvBlob* pB = m_BlobList.GetBlob(i-1);
m_pBTPostProc->AddBlob(pB);
}
m_pBTPostProc->Process();
for(int i=m_BlobList.GetBlobNum(); i>0; --i)
{ /* Update tracked-blob list: */
CvBlob* pB = m_BlobList.GetBlob(i-1);
int BlobID = CV_BLOB_ID(pB);
CvBlob* pBN = m_pBTPostProc->GetBlobByID(BlobID);
if(pBN && m_UsePPData && pBN->w >= CV_BLOB_MINW && pBN->h >= CV_BLOB_MINH)
{ /* Set new data for tracker: */
m_pBT->SetBlobByID(BlobID, pBN );
}
if(pBN)
{ /* Update blob list with results from postprocessing: */
pB[0] = pBN[0];
}
}
} /* Post-processing module. */
TIME_END("PostProcessing",CurBlobNum)
/* Blob deleter (experimental and simple): */
TIME_BEGIN()
if(pFG)
{ /* Blob deleter: */
int i;
if(!m_BTReal)for(i=m_BlobList.GetBlobNum();i>0;--i)
{ /* Check all blobs on list: */
CvBlobTrackAuto* pB = (CvBlobTrackAuto*)(m_BlobList.GetBlob(i-1));
int Good = 0;
int w=pFG->width;
int h=pFG->height;
CvRect r = CV_BLOB_RECT(pB);
CvMat mat;
double aver = 0;
double area = CV_BLOB_WX(pB)*CV_BLOB_WY(pB);
if(r.x < 0){r.width += r.x;r.x = 0;}
if(r.y < 0){r.height += r.y;r.y = 0;}
if(r.x+r.width>=w){r.width = w-r.x-1;}
if(r.y+r.height>=h){r.height = h-r.y-1;}
if(r.width > 4 && r.height > 4 && r.x < w && r.y < h &&
r.x >=0 && r.y >=0 &&
r.x+r.width < w && r.y+r.height < h && area > 0)
{
aver = cvSum(cvGetSubRect(pFG,&mat,r)).val[0] / area;
/* if mask in blob area exists then its blob OK*/
if(aver > 0.1*255)Good = 1;
}
else
{
pB->BadFrames+=2;
}
if(Good)
{
pB->BadFrames = 0;
}
else
{
pB->BadFrames++;
}
} /* Next blob: */
/* Check error count: */
for(i=0; i<m_BlobList.GetBlobNum(); ++i)
{
CvBlobTrackAuto* pB = (CvBlobTrackAuto*)m_BlobList.GetBlob(i);
if(pB->BadFrames>3)
{ /* Delete such objects */
/* from tracker... */
m_pBT->DelBlobByID(CV_BLOB_ID(pB));
/* ... and from local list: */
m_BlobList.DelBlob(i);
i--;
}
} /* Check error count for next blob. */
} /* Blob deleter. */
TIME_END("BlobDeleter",m_BlobList.GetBlobNum())
/* Update blobs: */
TIME_BEGIN()
if(m_pBT)
m_pBT->Update(pImg, pFG);
TIME_END("BlobTrackerUpdate",CurBlobNum)
/* Detect new blob: */
TIME_BEGIN()
if(!m_BTReal && m_pBD && pFG && (m_FrameCount > m_FGTrainFrames) )
{ /* Detect new blob: */
static CvBlobSeq NewBlobList;
CvBlobTrackAuto NewB;
NewBlobList.Clear();
if(m_pBD->DetectNewBlob(pImg, pFG, &NewBlobList, &m_BlobList))
{ /* Add new blob to tracker and blob list: */
int i;
IplImage* pmask = pFG;
/*if(0)if(NewBlobList.GetBlobNum()>0 && pFG )
{// erode FG mask (only for FG_0 and MS1||MS2)
pmask = cvCloneImage(pFG);
cvErode(pFG,pmask,NULL,2);
}*/
for(i=0; i<NewBlobList.GetBlobNum(); ++i)
{
CvBlob* pBN = NewBlobList.GetBlob(i);
if(pBN && pBN->w >= CV_BLOB_MINW && pBN->h >= CV_BLOB_MINH)
{
pBN->ID = m_NextBlobID;
CvBlob* pB = m_pBT->AddBlob(pBN, pImg, pmask );
if(pB)
{
NewB.blob = pB[0];
NewB.BadFrames = 0;
m_BlobList.AddBlob((CvBlob*)&NewB);
m_NextBlobID++;
}
}
} /* Add next blob from list of detected blob. */
if(pmask != pFG) cvReleaseImage(&pmask);
} /* Create and add new blobs and trackers. */
} /* Detect new blob. */
TIME_END("BlobDetector",-1)
TIME_BEGIN()
if(m_pBTGen)
{ /* Run track generator: */
for(int i=m_BlobList.GetBlobNum(); i>0; --i)
{ /* Update data of tracked blob list: */
CvBlob* pB = m_BlobList.GetBlob(i-1);
m_pBTGen->AddBlob(pB);
}
m_pBTGen->Process(pImg, pFG);
} /* Run track generator: */
TIME_END("TrajectoryGeneration",-1)
TIME_BEGIN()
if(m_pBTA)
{ /* Trajectory analysis module: */
int i;
for(i=m_BlobList.GetBlobNum(); i>0; i--)
m_pBTA->AddBlob(m_BlobList.GetBlob(i-1));
m_pBTA->Process(pImg, pFG);
} /* Trajectory analysis module. */
TIME_END("TrackAnalysis",m_BlobList.GetBlobNum())
} /* CvBlobTrackerAuto1::Process */