当前位置: 代码迷 >> 综合 >> 背景建模与前景检测3(Background Generation And Foreground Detection Phase 3)
  详细解决方案

背景建模与前景检测3(Background Generation And Foreground Detection Phase 3)

热度:99   发布时间:2023-12-12 09:27:47.0

背景建模与前景检测之三(Background Generation And Foreground Detection Phase 3)

作者:王先荣

    在上一篇文章里,我尝试翻译了《Nonparametric Background Generation》,本文主要介绍以下内容:如何实现该论文的算法,如果利用该算法来进行背景建模及前景检测,最后谈谈我的一些体会。为了使描述更加简便,以下将该论文的算法及实现称为NBGModel。
1 使用示例
    NBGModel在使用上非常的简便,您可以仿照下面的代码来使用它:

    
     
// 初始化NBGModel对象
NBGModel nbgModel = new NBGModel( 320 , 240 );
// 训练背景模型
nbgModel.TrainBackgroundModel(historyImages);
// 前景检测
nbgModel.Update(currentFrame);
// 利用结果
pbResult.Image = nbgModel.ForegroundMask.Bitmap;
// 释放对象
nbgModel.Dispose();

下面是更加完整的示例:

更加完整的示例

 

2 实现NBGModel
    2.1 我在实现NBGModel的时候基本上跟论文中的方式一样,不过有以下两点区别:
(1)论文中的MeanShift计算使用了Epanechnikov核函数,我使用的是矩形窗形式的MeanShift计算。主要是因为我自己不会实现MeanShift,只能利用OpenCV中提供的cvMeanShift函数。这样做也有一个好处——不再需要计算与保存典型点。
(2)论文中的方法在检测的过程中聚集中心会不断的增加,我模仿CodeBook的实现为其增加了一个清除消极聚集中心的ClearStable方法。这样可以在必要的时候将长期不活跃的聚集中心清除掉。

    2.2 NBGModel中用到的数据成员如下所示:
        private int width;                                          //图像的宽度
        private int height;                                         //图像的高度
        private NBGParameter param;                                 //非参数背景模型的参数

        private List<Image<Ycc, Byte>> historyImages = null;        //历史图像:列表个数为param.n,在更新时如果个数大于等于param.n,删除最早的历史图像,加入最新的历史图像
        //由于这里采用矩形窗口方式的MeanShift计算,因此不再需要分组图像的典型点。这跟论文不一样。
        //private List<Image<Ycc,Byte>> convergenceImages = null;   //收敛图像:列表个数为param.m,仅在背景训练时使用,训练结束即被清空,因此这里不再声明
        private Image<Gray, Byte> sampleImage = null;               //样本图像:保存历史图像中每个像素在Y通道的值,用于MeanShift计算
        private List<ClusterCenter<Ycc>>[,] clusterCenters = null;  //聚集中心数据:将收敛点分类之后得到的聚集中心,数组大小为:height x width,列表元素个数不定q(q<=m)。
        private Image<Ycc, Byte> mrbm = null;                       //最可靠背景模型

        private Image<Gray, Byte> backgroundMask = null;            //背景掩码图像

        private double frameCount = 0;                              //总帧数(不包括训练阶段的帧数n)

其中,NBGParameter结构包含以下成员:
        public int n;                       //样本数目:需要被保留的历史图像数目
        public int m;                       //典型点数目:历史图像需要被分为多少组
        public double theta;                //权重系数:权重大于该值的聚集中心为候选背景
        public double t;                    //最小差值:观测值与候选背景的最小差值大于该值时,为前景;否则为背景
        public MCvTermCriteria criteria;    //Mean Shift计算的终止条件:包括最大迭代次数和终止计算的精度

聚集中心ClusterCenter使用类而不是结构,是为了方便更新,它包含以下成员:
        public TColor ci;              //聚集中心的像素值
        public double wi;              //聚集中心的权重
        public double li;              //聚集中心包含的收敛点数目
        public double updateFrameNo;   //更新该聚集中心时的帧数:用于清除消极的聚集中心

    2.3 NBGModel中的关键流程
1.背景建模
(1)将训练用的样本图像添加到历史图像historyImages中;
(2)将历史图像分为m组,以每组所在位置的矩形窗为起点进行MeanShift计算,结果窗的中点为收敛中心,收敛中心的像素值为收敛值,将收敛值添加到收敛图像convergenceImages中;
(3)计算收敛图像的聚集中心:(a)得到收敛中心的最小值Cmin;(b)将[0,Cmin+t]区间中的收敛中心划分为一类;(c)计算已分类收敛中心的平均值,作为聚集中心的值;(d)删除已分类的收敛中心;(e)重复a~d,直到收敛中心全部归类;
(4)得到最可靠背景模型MRBM:在聚集中心中选取wi最大的值作为某个像素的最可靠背景。

2.前景检测
(1)用wi≥theta作为条件选择可能的背景组Cb;
(2)对每个观测值x0,计算x0与Cb的最小差值d;
(3)如果d>t,则该点为前景;否则为背景。

3.背景维持
(1)如果某点为背景,更新最近聚集中心的wi为(li+1)/m;
(2)如果某点为前景:(a)以该点所在的矩形窗为起点进行MeanShift计算,可得到新的收敛中心Cnew(wi=1/m);(b)将Cnew加入到聚集中心clusterCenters;
(3)在必要的时候,清理消极的聚集中心。

    2.4 NBGModel的实现代码
值得注意的是:在实现代码中,有好几个以2结尾的私有方法,它们主要用于演示算法流程,实际上并未使用。为了优化性能而增加了不少指针操作之后的代码可读性变得很差。

NBGModel实现代码

 

3 NBGModel类介绍
    3.1 属性
Width——获取图像的宽度
Height——获取图像的高度
Param——获取参数设置
Mrbm——获取最可靠背景模型图像
BackgroundMask——获取背景掩码图像
ForegroundMask——获取前景掩码图像
FrameCount——获取已被检测的帧数

    3.2 构造函数
public NBGModel(int width, int height)——用默认的参数初始化NBGModel,等价于NBGModel(width, height, NBGParameter.GetDefaultNBGParameter())
public NBGModel(int width, int height, NBGParameter param)——用指定的参数初始化NBGModel

    3.3 方法
AddHistoryImage——添加一幅或者一组历史图像
TrainBackgroundModel——训练背景模型;如果传入了历史图像,则先添加历史图像,然后再训练背景模型
Update——更新背景模型,同时检测前景
ClearStale——清除消极的聚集中心
Dispose——释放资源

4 体会
    NBGModel的确非常有效,非常简洁,特别适用于伴随复杂运动对象的背景建模。我特意选取了PETS2009中的素材对其做了一些测试,结果也证明了NBGModel的优越性。不过需要指出的是,它需要占用大量的内存(主要因为需要保存n幅历史图像);它的计算量比较大。
在使用的过程中,它始终需要在内存中缓存n幅历史图像,1幅最可靠背景模型图像,1幅背景掩码图像,近似m幅图像(聚集中心);而在训练阶段,更需要临时存储m幅收敛图像。
例如:样本数目为100,典型点数目为10,图像尺寸为768x576时,所用的内存接近300M,训练背景需要大约需要33秒,而对每幅图像进行前景检测大约需要600ms。虽然可以使用并行编程来提高性能,但是并不能从根本上解决问题。
(注:测试电脑的CPU为AMD闪龙3200+,内存1.5G。)
    看来,有必要研究一种新的方法,目标是检测效果更好,内存占用低,处理更快速。目前的想法是使用《Wallflower: Principles and Practice of Background Manitenance》中的3层架构(时间轴上的像素级处理,像素间的区域处理,帧间处理),但是对每层架构都选用目前流行的处理方式,并对处理方式进行优化。时间轴上的像素级处理打算使用CodeBook方法,但是增加本文的一些思想。像素间的区域处理打算参考《基于区域相关的核函数背景建模算法》中的方法。帧间处理预计会采用全局灰度统计值作为依据。

最后,按照惯例:感谢您耐心看完本文,希望对您有所帮助。
本文所述方法及代码仅用于学习研究,不得用于商业目的。

  相关解决方案