APP下载

非动态的背景建模与前景检测算法

2020-06-21王若宇

河南科技 2020年10期

王若宇

摘 要:为了从一些复杂的场景中提取出人像,用到的开源代码有很多,其均假设若一个像素的颜色在较长时间内变化不大,则认为它是背景。但是,这些开源代码在用于一些自拍摄像头时效果较差,因为当一个人端坐在摄像头前,他的像素不会发生很大变化。因此,本文提出了另外一种算法,该算法基于如下假设:在背景建模期间前景不会出现,且背景建模结束后,背景的变化始终为建模期间背景变化的子集。这种非动态的算法适用于提取距离摄像头距离更近的对象。

关键词:前景提取;前景检测;背景建模

Abstract: In order to extract human images from some complex scenes, many open source codes are used, which assume that if the color of a pixel does not change much in a long time, it is considered as the background. However, these open source codes are not very effective for some self timer cameras, because when a person sits in front of the camera, his pixels will not change greatly. Therefore, this paper proposed another algorithm, which was based on the following assumption: the foreground would not appear during the background modeling, and after the background modeling, the background change was always a subset of the background change during the modeling. This non dynamic algorithm is suitable for extracting objects closer to the camera.

Keywords: foreground extraction;foreground detection;background modeling

1 算法設计

1.1 算法思路

由于是从摄像头采集的图像,因此其有BGR三个通道,每个通道的值为[0,255]。为每一个像素的每一个通道创建一个编码本(CodeBook[1]),编码本中储存有若干个码元(CodeElement),一个码元中储存一个区间。在前景检测阶段,若某一像素的三个通道都落在对应编码本的任一码元里,则认为它是背景;否则,认为它是前景。据此得到掩模,然后利用形态学开闭操作、轮廓检测、凸包运算等消除噪声,优化掩模效果。

创建编码本和码元的思路在数据结构介绍中解释。

1.2 数据结构介绍

1.2.1 码元(CodeElement)。创建码元的代码如下:

1.2.2 编码本(CodeBook)。创建编码本的代码如下:

其中,learnHigh和learnLow表示一个学习阈值。在背景建模阶段,对输入图像的每一个像素的每一通道,遍历其编码本中的码元,如果该通道的值在某个码元中,则跳过;如果该通道的值虽然不在某个码元中,但它在(Min-learnLow)~(Max+learnHigh)中,则表示该码元应该学习这个像素,因此应扩大码元的区间使之包含这个像素。若该通道的值不满足上述两个条件,则应该为它的编码本新建一个码元,并使码元的Max和Min初始值为该通道的值。

1.2.3 编码本索引。编码本索引为codeBooks[]。其本质为Python中的一个列表。它的元素个数为像素数乘以通道数。本来使用三维数组来储存可能会更为直观,但列表并不支持。列表的index与图像的位置和通道的映射关系为:

1.3 核心代码介绍

1.3.1 创建编码本。创建编码本的函数代码如下:

在开始算法时,所需采集的图像信息已经确定,因此编码本数量已经确定。按照设计的顺序向编码本索引中添加所有编码本,以便之后对其进行操作。

该函数的参数依次为三个通道的学习上限和学习下限。

1.3.2 更新编码本。更新编码本的函数代码如下:

建模的核心代码用于建模时更新各个编码本中的码元。根据输入的图像数据,有选择地新建码元或者扩大码元范围。

该函数的参数为当前像素在当前通道的颜色和索引。

1.3.3 清除不常用的码元。清除不常用的码元的函数代码如下:

将更新时间很久远的码元清除,以便减少码元数量,提高代码效率。但是,本次算法由于效率较低,建模数量本身就比较小,而且维护码元更新时间需要大量开销,因此暂时不用这个函数。

1.3.4 计算掩模。计算掩模的函数代码如下:

根据输入的颜色数值及其索引,判断该数值是否在索引指向的编码本的某一码元中,若是,则返回True,否则返回False。

该函数的参数为当前像素在当前通道的颜色和索引。

返回值为表明输入颜色是否在输入索引所指向的编码本中的布尔型值。

1.3.5 主函数循环流程设计

1.3.5.1 建模。设置变量frameNum记录当前帧数,若帧数小于事先设置的createdFrame变量,则表示该帧用于建模,用如下三层循环对该帧所有像素的三个通道遍历,均调用updateCodeBook()函数更新其编码本:

1.3.5.2 显示。当帧数frameNum大于事先设置的createdFrame变量时,表示该帧用于显示。使用如下三层循环寻找掩模:

从图1可以看到,其存在大量噪声,因此需要用形态学方法对其进行处理。

1.3.5.3 优化处理。优化处理步骤如下。

第一步,进行开闭操作初步去除噪声,代码如下。

从图2可知,仍有部分噪声,且手边界被腐蚀。

为了查看目前效果,设置建模帧数为100,并在建模时有意将手出现在建模范围内,但并不一直出现。将处理后掩模对应原视频帧输出,效果如图3所示。

从图3可知,虽然效果不错,但需要的建模时间较长(1 min),且建模时要刻意将手出现在视频里,调节建模效果。

分析20帧建模结果发现,噪声周长远小于识别目标。结合分析100帧建模结果发现,手的边界被腐蚀了部分,应该据此进行进一步处理。

第二步,消除小轮廓,用凸包运算填充大轮廓。

图4中两种风格的图像都是在同一模型下识别的。由于研究者使用的摄像头会在画面较暗时调整相关参数,变为下面的图像风格,正好可以用于测试编码本算法對背景有很大影响但规律变化时的效果。在建模时,刻意调整摄像头相关参数,将上下两图的风格都加入模型中。而后在前景检测阶段,无论摄像头在哪种风格下,都可以准确识别前景。但是,由于凸包运算使得下边掩模丢失部分细节。若检测范围较大,这些细节可以被忽视。

1.4 代码内参数介绍

video为前景的视频来源。backGround为背景的视频来源。smallContour为区分大小轮廓的阈值,周长小于该值为小轮廓,否则为大轮廓。createdFrame为用于建模的帧数。width为由于算法效率太低,只能处理小范围图像,用该值规定处理的宽度;height为由于算法效率太低,只能处理小范围图像,用该值规定处理的高度,具体是取视频左上角该大小的图像,即坐标为[0:height][0:width]的像素。changeNum用于元组扩大范围时,不但包含传入的颜色,而且进一步根据该值扩大范围。基于如下猜测:当颜色color为背景时,[color-changeNum,color+changeNum]都可能为背景。函数creatCodeBook(10, 10, 10, 10, 10, 10)的参数为各个通道的学习阈值。该值越大元组范围越大,元组数目越少。

2 算法特点总结

使用Python实现一个简单的编码本算法。但是,不动态更新编码本,而是与背景减除的思想结合,在程序开始时建模,期待用户将尽可能多的背景情况包含在模型中,又不出现前景。这个条件虽然苛刻,但是有其道理:在只根据当前摄像头输入运行算法的情况下(即没有现成的模型,没有约定的背景或者前景颜色),若一个人端坐在摄像头前,其衣服上的像素颜色变化范围将很小,与背景颜色变化规律几乎是一致的,因此,若建模的时候出现前景,很难将它与背景区别开。

本算法适用于背景规律变化的情况,在建模阶段获取的全部信息都可以在前景检测阶段被成功识别为背景。

此外,对编码本算法做了些许修改,比如,每像素的每个通道一个编码本,而不是每像素一个编码本;学习阈值储存在编码本中而不是码元中等。

本算法未针对前景出现后背景的变化进行计算(如前景的阴影,或前景出现后摄像头自动调节亮度)。摄像头自动调节亮度的问题可通过将视频转化为YUV通道,然后增大V通道的changeNum和学习阈值来改善。

参考文献:

[1]Gary Bradski,Adrian Kaehler.Learning Opencv[M].北京:清华大学出版社,2009.