一、概述
OpenCV 团块跟踪过程细分为:前景检测模块、新团块(blob)检测模块、团块跟踪模块、轨迹生成模块和轨迹后处理模块。而跟踪流程模块CvBlobTrackerAuto把这五个模块连接起来。如下图所示:
各个模块的功能:
(1)、前景检测模块:对每个像素判断其是前景还是背景;
(2)、新团块检测模块:使用前景检测的结果检测新进入场景的团块;
(3)、团块跟踪模块:使用新团块检测模块的结果初始化该模块,并跟踪新进入的团块;
(4)、轨迹生成模块:主要是保存操作。它收集所有团块的位置,并在每条轨迹结束时将其保存到硬盘上;
(5)、轨迹后处理模块:进行轨迹的平滑操作。此模块是可选的,可以不包含在处理流程中;
(6)、跟踪流程模块:将前面提到的五个模块连接起来,形成一个处理流程;
二、前景检测模块
前景检测模块将当前帧上的像素分为前景像素和背景像素。OpenCV 实现了两种前景检测方法:混合高斯模型和Liyuan Li 的ACM Multimedia 2003 会议论文中的算法。
CvFGDetector 是个虚类,描述了前景检测模块接口。前景检测模块的输入数据为当前帧图像,输出数据为当前帧的前景掩码(mask)。其结构定义如下:
class CvFGDetector
{
public: virtual IplImage*GetMask( ) = 0;
virtual void Process(IplImage*plmg) = 0;
virtual void Release( ) = 0;
}
三、新团块检测模块
CvBlobDetector 是一个虚类,用来描述新团块检测模块的接口。新团块检测模块的输入数据为当前的前景掩码和已有的团块,输出数据为新检测到的团块。新团块检测模块作用是将新进入物体的位置和大小检测到。模块结构如下:
class CvBlobDetector
{
public:
/*利用前景掩码检测新的团块*/
/*pFGMask-图像的前景掩码*/
/*pNewBlobList-新检测到的团块序列指针*/
/*pOldBlobList-已有团块序列指针*/
virtual int DetectNewBlob(IplImage*pFGMask, CvBlobSeq *pNewBlobList,
CvBlobSeq *pOldBlobList) = 0;
virtual void Release( ) = 0;
}
CvBlobDetector 两个子类 CvBlobDetectorSimple 和 CvBlobDetectorCC。下面简单介绍CvBlobDetectorCC:DetectNewBlob 的处理流程。首先从前景图像pFGMask中检测出所有团块,然后将较小的团块(可能是由噪声引起的)和已经被跟踪团块有重叠的团块丢弃,并对剩余的团块按照大小排序,仅保留10个最大的团块。将这几个团块作为候选新的团块,对它们利用各种筛选,筛除掉不符合标准的团块,将最后真正的新团块保存到变量pNewBlobList中。
四、团块跟踪模块
CvBlobTracker 是一个虚类,用来描述团块跟踪模块的接口。团块跟踪模块的输入数据为当前帧(是BGR图像)、当前帧的前景掩码和新团块,输出数据为当前帧的团块信息(ID,pos,size)。模块结构如下:
class CvBlobTracker:
{
public:
CvBlobTracker();
/* Add new blob to track it and assign to this blob personal ID */
/* pBlob - pointer to structure with blob parameters (ID is ignored)*/
/* pImg - current image */
/* pImgFG - current foreground mask */
/* Return pointer to new added blob: */
virtual CvBlob* AddBlob(CvBlob* pBlob, IplImage* pImg, IplImage* pImgFG = NULL ) = 0;
/* Return number of currently tracked blobs: */
virtual int GetBlobNum() = 0;
/* Return pointer to specified by index blob: */
virtual CvBlob* GetBlob(int BlobIndex) = 0;
/* Delete blob by its index: */
virtual void DelBlob(int BlobIndex) = 0;
/* Process current image and track all existed blobs: */
virtual void Process(IplImage* pImg, IplImage* pImgFG = NULL) = 0;
/* Release blob tracker: */
virtual void Release() = 0;
/* Return pointer to blob by its unique ID: */
virtual int GetBlobIndexByID(int BlobID);
/* Return pointer to blob by its unique ID: */
virtual CvBlob* GetBlobByID(int BlobID);
/* Delete blob by its ID: */
virtual void DelBlobByID(int BlobID);
/* Set new parameters for specified (by index) blob: */
virtual void SetBlob(int /*BlobIndex*/, CvBlob* /*pBlob*/);
/* Set new parameters for specified (by ID) blob: */
virtual void SetBlobByID(int BlobID, CvBlob* pBlob);
};
CvBlobTrackerCC::Process 处理流程是:首先从前景图像pImgFG提取所有团块,并计算团块的质心、宽度和高度。然后对每一个已经被跟踪的轨迹,利用卡尔曼滤波器预测该轨迹在当前帧的团块的位置和大小。如果变了m_Collision值非零,则对当前跟踪的所有团块进行碰撞检测。如果某两个团块存在碰撞,则设置其属性Collision为1。最后一步是对每个跟踪的轨迹进行处理,寻找离上一帧的团块最近的当前帧里的团块,将此团块加入到跟踪轨迹。下图是团块跟踪列表:
五、轨迹生成模块
CvBlobTrackerGen 是用来实现轨迹生成模块的一个虚类。此模块的目的是将整个轨迹保存到指定文件中,同时,也可以为每一个团块计算一些特征并保存。轨迹生成模块的输入数据为当前帧的所有团块,输出数据为保存的轨迹列表。模块数据结构如下:
classCvBlobTrackGen
{
public:
CvBlobTrackGen(){SetTypeName("BlobTrackGen");};
virtual void SetFileName(char* pFileName) = 0;
virtual void AddBlob(CvBlob* pBlob) = 0;
virtual void Process(IplImage* pImg = NULL, IplImage* pFG = NULL) = 0;
virtual void Release() = 0;
};
六、轨迹后处理模块
CvBlobTrackPostProc 是用来实现轨迹后处理模块的一个虚类。此模块的目的是在团块轨迹上做一些滤波处理。例如此模块可以是Kalman 滤波或其他的平滑滤波。轨迹后处理模块的输入数据为当前帧的所有团块,输出数据为当前帧的所有团块。模块结构如下:
class CvBlobTrackPostProc
{
public:
virtual void AddBlob(CvBlob* pBlob) = 0;
virtual void Process() = 0;
virtual int GetBlobNum() = 0;
virtual CvBlob* GetBlob(int index) = 0;
virtual void Release() = 0;
/* Additional functionality: */
virtual CvBlob* GetBlobByID(int BlobID)
{
int i;
for(i=GetBlobNum();i>0;i--)
{
CvBlob* pB=GetBlob(i-1);
if(pB->ID==BlobID) return pB;
}
return NULL;
};
};
轨迹后处理的流程如图如下:
七、处理流程模块
CvBlobTrackerAuto 是一个虚类,用于集成其他模块,构成一个跟踪流程。该模块定义的结构如下:
class CvBlobTrackerAuto
{
public:
virtual void Process(IplImage* pImg, IplImage* pMask = NULL) = 0;
virtual CvBlob* GetBlob(int index) = 0;
virtual CvBlob* GetBlobByID(int ID) = 0;
virtual int GetBlobNum() = 0;
virtual IplImage* GetFGMask(){return NULL;};
virtual float GetState(int BlobID) = 0;
virtual const char* GetStateDesc(int BlobID) = 0;
/* return 0 if trajectory is normal;
* return >0 if trajectory abnormal. */
virtual void Release() = 0;
};
该类关键函数是CvBlobTrackerAuto1::Process,它负责调用其他各子模块。具体流程图如下: