OpenCV-Python系列之背景分离

从本次教程开始,我们进入新的篇章,之前一直在讨论OpenCV的特征部分,这次我们来讨论OpenCV中的背景分离,又称背景减法模型。

背景分离(BS)是一种通过使用静态相机来生成前景掩码(即包含属于场景中的移动对象像素的二进制图像)的常用技术。

顾名思义,BS计算前景掩码,在当前帧与背景模型之间执行减法运算,其中包含场景的静态部分,或者更一般而言,考虑到所观察场景的特征,可以将其视为背景的所有内容。

image.png

背景建模包括两个主要步骤:

1. 背景初始化;

2. 背景更新。

初步,计算背景的初始模型,而在第二步中,更新模型以适应场景中可能的变化。

在本教程中,我们将学习如何使用OpenCV中的BS。

OpenCV中的使用

OpenCV 中已经包含了其中三种比较容易使用的方法,我们逐一来看。

BackgroundSubtractorMOG

这是一个以混合高斯模型为基础的前景/背景分割算法。它是 P.KadewTraKuPong 和 R.Bowden 在 2001 年提出的。

它使用 K(K=3 或 5)个高斯分布混合对背景像素进行建模。使用这些颜色(在整个视频中)存在时间的长短作为混合的权重。背景的颜色一般持续的时间最长,而且更加静止。

一个像素怎么会有分布呢?在 x,y平面上一个像素就是一个像素,没有分布,但是我们现在讲的背景建模是基于时间序列的,因此每一个像素点所在的位置在整个时间序列中就会有很多值,从而构成一个分布

在编写代码时,我们需要使用函数:cv2.createBackgroundSubtractorMOG() 创建一个背景对象。这个函数有些可选参数,比如要进行建模场景的时间长度,高斯混合成分的数量,阈值等。将他们全部设置为默认值。然后在整个视频中我们是需要使用backgroundsubtractor.apply() 就可以得到前景的掩模了

移动的物体会被标记为白色,背景会被标记为黑色的,前景的掩模就是白色的了。

不过目前这个方法已经被弃用了,OpenCV中也没有了相关函数的API。

BackgroundSubtractorMOG2

这个也是以高斯混合模型为基础的背景/前景分割算法。它是以 2004 年 和 2006 年 Z.Zivkovic 的两篇文章为基础的。这个算法的一个特点是它为每 一个像素选择一个合适数目的高斯分布。(上一个方法中我们使用是 K 高斯分布)。

这样就会对由于亮度等发生变化引起的场景变化产生更好的适应。

和前面一样我们需要创建一个背景对象。但在这里我们我们可以选择是否检测阴影。如果 detectShadows = True(默认值),它就会检测并将影子标记出来,但是这样做会降低处理速度。影子会被标记为灰色。

BackgroundSubtractorMOG2算法的两个改进点:

-阴影检测
-速度快了一倍

我们将使用官方提供的人体跟踪的视频:

image.png

这个我提供在这儿:

test.zip

我们来看代码:

def MOG2():
     cap = cv2.VideoCapture("test.avi")
     fgbg = cv2.createBackgroundSubtractorMOG2()
     while (1):
         ret, frame = cap.read()
         fgmask = fgbg.apply(frame)
         cv2.imshow('frame', fgmask)
         k = cv2.waitKey(100) & 0xff
         if k == 27:
             break
     cap.release()
     cv2.destroyAllWindows()

结果:

image.png

可以看到基本的行人与背景分离出来了。

BackgroundSubtractorGMG

此算法结合了静态背景图像估计和每个像素的贝叶斯分割。这是 2012 年 Andrew_B.Godbehere,Akihiro_Matsukawa 和 Ken_Goldberg 在文章 中提出的。

它使用前面很少的图像(默认为前 120 帧)进行背景建模。使用了概率前 景估计算法(使用贝叶斯估计鉴定前景)。这是一种自适应的估计,新观察到的 对象比旧的对象具有更高的权重,从而对光照变化产生适应。一些形态学操作 如开运算闭运算等被用来除去不需要的噪音。在前几帧图像中你会得到一个黑 色窗口。

对结果进行形态学开运算对与去除噪声很有帮助。

不过同样的,这个方法目前也是不再用了。

BackgroundSubtractorKNN

KNN作为大名鼎鼎的机器学习算法,其用在背景分离应用中也是得心应手,但是在此不对KNN作过多的解释,它属于机器学习的一个算法,比较复杂,我们来看代码:

def KNN():
     cap = cv2.VideoCapture('test.avi')
     fgbg = cv2.createBackgroundSubtractorKNN()
     while (1):
         ret, frame = cap.read()
         fgmask = fgbg.apply(frame)
         cv2.imshow('frame', fgmask)
         k = cv2.waitKey(100) & 0xff
         if k == 27:
             break
     cap.release()
     cv2.destroyAllWindows()

结果:

image.png

实验结果发现KNN的结果要明显优于MOG2算法。

posted @ 2021-12-08 09:43  wuyuan2011woaini  阅读(939)  评论(0编辑  收藏  举报