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

多阶编码本模型(Multi phase codebook model)
作者:王先荣

 注:这是2010年所写的文章,因为要发论文到杂志上的缘故,这篇文章放到博客几天便隐藏起来了,最近论文正是刊出,所以文章又重见天日了。您可以在后面的地址查看或者下载论文。

http://www.ceaj.org/Jweb_gcyyy/CN/abstract/abstract27730.shtml

前言
    本文将介绍一种名为多阶编码本的背景模型,该模型借用《Wallflower:Principles and Practice of Background Maintenance》中的三层模型思路,试图达到适应性更广,更精确,性能更好的目标。像素级处理采用《Real-time foreground-background segmentation using codebook model》中提出的编码本模型,不过对其进行了必要的扩展;区域级处理采用《学习OpenCV》中的形态学及轮廓处理方法;帧间处理以每帧的全局平均灰度值为依据,动态建立多个编码本以适应各种情况。因为博客文章格式比较随意,我在这里只写出要点,并给出实现代码,套话之类的都省了。

 

题外话
    在开始正文之前,我要向大家隆重的介绍一幅我女儿的作品,画中有一座城堡及四个人,分别代表家、王子(??)、公主(女儿)、国王(我)及王后(我老婆)。最近在小孩身上连续发生了一些问题,希望能尽快好起来。


帧间处理
    帧间处理的目的是为了让背景模型能适应尽可能的场景(相对固定及多变的场景)。在更新背景模型及背景减除的之前,需要先计算图像的全局平均灰度值,然后根据平均灰度值选择(或创建)一个合适的编码本,并在选定的编码本中执行更新或者减除。如果需要,也可以选择关闭帧间处理,这样多阶编码本模型就退化成编码本模型。多个编码本分别对应场景的多种可能。为了能够鉴别编码本的适用范围,增加了两个成员,分别是:ymin——最小灰度值,ymax——最大灰度值。在训练背景模型的过程中,ymin和ymax可能会缓慢的扩展。


像素级处理
    像素级处理本质上是对编码本模型的处理,每个像素可能包含多个码元(CodeWord),每个码元的box上限和下限包容了像素值的小幅度变化,多个码元包容了像素的多种可能性。为了能够反映每个码元的重要性,我为码元增加了成员weight(权重);而为了计算出权重,又为码元增加了成员frequency(表示该码元出现的次数),为编码本增加了成员frequencyCounts(用来存储每个像素中所有码元的出现次数之和)。编码本的详细介绍请看kim的论文。增加权重和码元出现次数的灵感来自《Nonparametric Background Generation》,详见原文或者我翻译的博文。


区域级处理
    这里的区域级处理跟通常的不太一样,并非在建模和背景减除时进行采用区域级信息。而是在背景减除之后,使用区域级处理对结果进行加工,达到消除噪声、杂点及过小目标的目的。为什么不在背景建模及背景减除时使用区域级信息呢?原因有两点:(1)为了使计算量不至于过大;(2)即使糅合了区域级信息,结果也没有显著的改善。


算法主要流程
1.更新背景模型

    (1)计算图像的全局平均灰度值;
    (2)根据全局平均灰度值选择合适的编码本;
    (3)如果没有找到合适的编码本,则创建一个新的编码本;
    (4)在合适的编码本或者新编码本中,遍历每个像素;
    (5)遍历每个码元,寻找匹配当前像素值的码元;
    (6)如果找到了匹配的码元,则更新匹配码元及不匹配的码元;
    (7)如果没有找到匹配的码元,则新增一个码元,并更新不匹配的码元。
2.背景减除
    (1)计算图像的全局平均灰度值;
    (2)根据全局平均灰度值选择合适的编码本;
    (3)如果没有找到合适的编码本,则认为所有的像素都是前景;
    (4)如果找到了合适的编码本,遍历每个像素;
    (5)遍历每个码元,如果存在匹配像素当前值的码元,则该像素为背景;如果没有匹配的码元,则像素为背景。
3.区域级处理
    (1)用形态学开、闭操作消除图像中的杂点和噪声;
    (2)用轮廓操作来剔除过小的前景:遍历图像的每个轮廓,如果轮廓的周长小于阀值,则剔除该轮廓;用多边形或者凸包近似余下的轮廓;重新绘制近似轮廓。
4.获取最可靠背景
    (1)选择命中次数最多的编码本;
    (2)遍历每个像素,选择像素中权重最大的码元;
    (3)将最佳码元中box的平均值作为像素值。
5.清除背景模型中消极或权重过小的码元
    (1)遍历每个编码本,若编码本的tAfterClear大于阀值,则执行清除;
    (2)遍历需要清除编码本中的每个像素;
    (3)遍历每个码元,若消极帧数大于阀值,或者权重小于阀值,则删除码元;
    (4)重新计算相关的数据。
6.查表技巧
    在处理的过程中,为了提高计算像素扩展值的速度,采用查表的做法来代替每次都计算:在初始化时先计算好256种可能的扩展值并存入数组,然后再直接从数组中取值。


如何使用多阶编码本模型
    您可以按下列方式来使用编码本模型:

//(1)初始化编码本模型
MultiPhaseCodeBookModel mpcbModel =new MultiPhaseCodeBookModel(imageWidth, imageHeight);
//(2)为了训练背景模型而多次更新背景模型,训练次数自己决定
mpcbModel.Update(image);
//(3)执行背景减除
mpcbModel.Diff(image2);
//(4)使用结果(前景掩码图像)
pictureBox1.Image = mpcbModel.ForegroundMask.Bitmap;
//(5)结束时释放资源
mpcbModel.Dispose();

    完整的示例请参看下列代码:

使用多阶编码本模型——完整示例


使用参考
    1.MultiPhaseCodeBookModel类包含以下公共属性:
int Width;                      //获取图像的宽度
int Height;                     //获取图像的高度
MultiPhaseCodeBookModelParameter Parameter; //获取或者设置多阶编码本模型参数
List<CodeBook> CodeBooks;       //获取编码本列表
double TotalFrameCount;             //获取已经更新的总帧数
Image<Gray, Byte> ForegroundMask;   //获取前景掩码图像
    2.MultiPhaseCodeBookModel类包含以下公共方法:
ClearStale——清除消极或者权重过小的码元
Diff——背景减除
GetAverageGrayValue——获取图像的全局平均灰度值
GetMrbm——获取最可靠背景图像
Update——更新背景模型
UpdateAndDiff——更新背景模型,然后执行背景减除


实现多阶编码本模型
    实现方法遵循上面提到的算法,完整的多阶编码本模型实现代码如下所示:

实现多阶编码本模型


试验
    我用PETS2009中的图像序列对多阶编码本模型进行了一些测试,测试结果还不错,达到了预期的目标。测试环境为:CPU AMD闪龙3200+,内存1.5G。处理768x576大小的图像大致需要150~200M内存。不过性能不够好,更新背景模型大约需要300ms/帧,背景减除大约需要150ms/帧,更新的同时执行背景减除大约需要390ms/帧。如果使用C语言来实现多阶编码本模型,大约可以提高30%的性能;如果采用并行编程,每增加一个CPU大约又可以提高30%的性能。


个人见解
    这段时间看了不少关于背景建模及前景检测方面的资料,并动手实践了固定摄像机的多种方法,而运动摄像机的情况没有涉及。为了适应更复杂的场景,背景模型越来越复杂;复杂的背景模型需要更多的内存和更大的计算量,相应的需要更加强劲的硬件。然而真的需要这么复杂的背景模型吗?我看未必,我倾向于选择刚好够用的背景模型,用牛刀去杀鸡是得不偿失的做法。

 

改进

    今天早上在刷牙的时候突然想到,现在的多阶编码本模型能够做得更好:
(1)数据结构上,其实每个码元中的权重不需要每次都去计算再保存,只需在比较权重之前,计算权重阀值跟像素总帧数的乘积weight',然后用weight'与每个码元的帧数去比较,效果也一样。这样做的好处有:减小了模型的内存占用量,三通道图像中每个码元占用的字节数从28减少到24;在更新模型时不必计算权重,可以为每个码元减少一次乘法运算,减少一次循环。
(2)算法能够优化,例如使用一维数组替代二维数组就能在大循环中节约数十毫秒级的时间。


感谢您耐心看完本文,希望对您有所帮助。

文章的代码不知道弄到哪里去了,找到之后再放上来。

posted @ 2012-04-24 22:59  Wuya  阅读(6345)  评论(31编辑  收藏  举报