0%

【Opencv】目标追踪——高斯混合模型分离算法(MOG)

1 环境

  • Python 3.8.8
  • PyCharm 2021
  • opencv-python

2 效果

在这里插入图片描述

3 原理

  视频图像中的目标检测与跟踪,是计算机视觉的基础课题,同时具有广泛的应用价值。视觉目标(单目标)跟踪任务就是在给定某视频序列初始帧的目标大小与位置的情况下,预测后续帧中该目标的大小与位置。依照目标与摄像头之间的关系可分为两种场景的目标追踪:

  • 静态场景:目标检测相对简单,研究渐趋成熟。
  • 动态场景:相对复杂,当前研究领域的热点。

本文只介绍静态场景的目标追踪,动态的在后序文章中会分享。

  在静态场景中,背景是静止的,则我们可以通过背景减除(Background Subtraction)来进行预处理。例如,考虑像访客柜台这样的情况,其中静态摄像机(监控)拍摄进入或离开房间的访客数量,或者交通摄像机提取有关车辆的信息等。在所有这些情况下,首先需要单独提取人员或车辆. 从技术上讲,需要从静态背景中提取移动的前景。那么我们可以通过帧差法来计算像素差从而获取到前景对象。

  如果只有背景图像,例如没有访客的房间图像,没有车辆的道路图像等,这很容易。只需从背景中减去新图像。就可以单独获得前景对象。但在大多数情况下,可能没有这样的图像,因此我们需要从我们拥有的任何图像中提取背景。当有车辆的影子时,情况变得更加复杂。由于阴影也在移动,简单的减法也会将其标记为前景。它使事情复杂化。

  高斯混合模型分离算法(MOG)算法在一定程度上可解决上述问题,2001年,由P.KadewTraKuPong和R.Bowden在论文 “An improved adaptive background mixture model for real-time tracking with shadow detection” 中提出。MOG2算法,也是高斯混合模型分离算法,是MOG的改进算法。基于2004年发布的 “Improved adaptive Gausian mixture model for background subtraction” 和2006年发布的 “Efficient Adaptive Density Estimation per Image Pixel for the Task of Background Subtraction” 两篇文章提出。该算法的一个重要特征是它为 每个 像素选择适当数量的高斯分布,它可以更好地适应不同场景的照明变化等。可以大家会有疑问,就是为什么一个像素也可以构成高斯分布呢,这里其实是因为我们的视频会持续一段时间,这样每个像素在每个时刻 $\boldsymbol{t}$ 都有对应的状态。因此上述的 每个 像素指的是一个像素在不同时刻 $\boldsymbol{t}$ 的状态。MOG算法的基本思路是基本思路:将图像分为3-5个高斯模型。如果一个像素点与任何一个高斯模型的均值 $\boldsymbol{\mu}$ 的之差大于其3倍的标准差 $\boldsymbol{\sigma}$,则为前景即运动物体,否则则是背景。算法流程如下:

  • 初始各种参数。
  • 使用过去 T 帧图像构造模型。
  • 对于一个新来的像素,如果该像素点的值与其模型均值 $\boldsymbol{\mu}$ 之差在 $\boldsymbol{3*\sigma}$ 内,则属于该分布,并对其进行参数更新。
  • 如果不满足该高斯模型,重新建立一个新的高斯模型。

4 代码

使用 cv2.createBackgroundSubtractorMOG2(history = 500, varThreshold = 16, detectShadows = true) 初始化一个MOG2模型,该函数的参数如下:

  • history:用于训练背景的帧数,默认为500帧。
  • varThreshold:方差阈值,用于判断当前像素是前景还是背景。一般默认16,如果光照变化明显,如阳光下的水面,建议设为25,36。
  • detectShadows:是否检测影子,设为True为检测,False为不检测,检测影子会增加程序时间复杂度,如无特殊要求,建议设为False。

使用 cv2.getStructuringElement(cv.MORPH_ELLIPSE, (3, 3)) 初始化形态学需要的卷积核 kernel,等效成 np.ones((3, 3), np.uint8)

使用 cv2.VideoCapture(video_path) 创建一个视频读取对象capture,capture.read() 进行捕捉画面,返回值如下:

  • ret:布尔值,表示是否正确捕捉到图像帧。
  • frame:图像帧。

使用 cv2.morphologyEx(fgmask, cv.MORPH_OPEN, kernel) 进行形态学处理,这是因为MOG2检测出的前景中有许多白点(如下图),所以使用开操作对白点进行腐蚀。

\[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D8X2h5uB-1649644124426)(C:\Users\爱上层楼\AppData\Roaming\Typora\typora-user-images\image-20220411102139496.png)\]

使用 cv2.imshow() 展示图片,使用 cv2.waitkey(10) & 0xff == 'q' 来延长放映的时间。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import cv2 as cv

def tracking_by_bg_substract() :
model = cv.createBackgroundSubtractorMOG2()
kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (3, 3))
capture = cv.VideoCapture('videos/static_bg_people.avi')

while capture.isOpened() :
ret, frame = capture.read()
if ret :
#对图像帧进行MOG2算法检测
fgmask = model.apply(frame)
fgmask = cv.morphologyEx(fgmask, cv.MORPH_OPEN, kernel)
cv.imshow('frame', frame)
cv.imshow('fgmask', fgmask)

if cv.waitKey(10) & 0xff == ord('q') :
break
else :
break

capture.release()
cv.destroyAllWindows()

if __name__ == '__main__':
tracking_by_bg_substract()

效果如下,效果还不错。在这里插入图片描述