https://blog.csdn.net/qq_42152399/article/details/80383967
用混合高斯背景建模提取出基于二值化图像中的运动目标。对于输入的一段视频文件,无论是提取视频中行人的运动情况还是车的运动情况,某一帧图像以某一像素点为中心和其相邻像素点呈现高斯分布。
如果像素点的值偏离中心值较远,那么,这个像素值属于前景,如果像素点的值偏离中心值很近(在一定方差范围内),那么可以说这个点属于背景。理论上,如果不存在任何干扰的话,是可以准确区分前景和背景的。
简单来说,
创建第一个高斯模型:对于输入的视频文件假设一共有T帧数据,用第一帧第一个像素点对第一个高斯模型的期望值μ1进行初始化,σ1用默认值来初始化。
下一帧图片对应相同位置的像素点为μ2,与μ1的差值和3×σ1的数值比较。如果差距较小,则把第二帧与第一帧图片在同一像素点上的分布视为相同的高斯分布。并且更新当前分布的μ和σ值。如果传入心得一帧图片μ2与μ1相差较大,则说明新传入的帧与上一真图片在该像素点位置属于不同的分布,则利用新传入的一帧再建立一个新的分布,用新传入一帧来初始化新的分布的μ和σ值。
对于一个T帧的视频流数据,通常设置3-5个不同的高斯分布。
创建高斯混合模型的过程可以看作是一个不断学习的过程。对于一个已经完成学习的模型,在测试过程中,输入一张图片某一像素点和该像素点已经建立好的模型进行对比,有较大差异,说明该像素点为前景图像。则说明该像素点属于我们要识别的运动的物体。将前景像素点用255来赋值,背景像素点用0来赋值。
理论上,如果不存在任何干扰的话,是可以准确区分前景和背景的。
但实际情况下,视频会受到很多因素影响,光线亮或暗,摄像头可能出现抖动,画面中可能存在摆动的物体。在混合高斯模型中这些因素会造成干扰。
混合高斯模型适合处理缓慢运动的物体,而频繁变化的物体像素点可能会被视为噪声。
生成高斯模型的代码:
cv2.createBackgroundSubtractorMOG2()
背景建模的代码如下:
import numpy as np
import cv2
cap = cv2.VideoCapture('test.avi')
# cap = cv2.VideoCapture(0)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
fgbg = cv2.createBackgroundSubtractorMOG2()
while(True):
ret, frame = cap.read()
fgmask = fgbg.apply(frame)
fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
im, contours, hierarchy = cv2.findContours(fgmask, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
perimeter = cv2.arcLength(c,True)
if perimeter > 188:
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(frame, (x, y), (x+w, y+h), (123, 123, 17), 2)
cv2.imshow('frame',frame)
cv2.imshow('fgmask', fgmask)
k = cv2.waitKey(150) & 0xff
if k == 27:
break
cap.release()
cv2.destroyAllWindows()
打开摄像头截图如下
读取avi格式文件显示结果如下:
(左侧二值图像中白色区域对应右边的图像应该有框对应的, 自己生成的那张图莫名其妙上传失败):
如上图所示,图片中框内表示检测到视频中运动的物体。对应在二值图像中背景建模的结果。运动的物体赋值为255,其余的背景赋值为0。
看代码:
首先opencv 读取视频文件,cv2.VideoCapture('test.avi')
参数是文件名称则读取文件,参数是0则使用摄像头。
然后定义一个3×3大小的椭圆形的内核,函数cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3))
的作用是生成一个指定形状和大小的内核结构。函数的第一个参数有三种选择
https://blog.csdn.net/u012193416/article/details/79312972
MORPH_RECT | MORPH_CROSS | MORPH_ELLIPSE |
---|---|---|
矩形 | 交叉形 | 椭圆形 |
生成的结构通常用于形态学操作(腐蚀、膨胀)
然后调用这个混合高斯模型的函数用于背景建模cv2.createBackgroundSubtractorMOG2()
,前面解释的那么多原理就是通过这一句代码实现的。
然后用循环来读取视频中的每一帧图片:
while(True):
ret, frame = cap.read()# 有两个返回值,第一个返回值表示是否读取到图片,返回True或者False,第二个参数表示截取到的每一帧图片。
fgmask = fgbg.apply(frame)
fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel)
im, contours, hierarchy = cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
对于读取到的每一帧图片,将混合高斯模型应用于每一张图片。
还记得前面那个人大小为(3,3)的椭圆形的内核吗,用作形态学开运算,作用是去除噪声。
然后对于每一张图片,查找外轮廓
for c in contours:
perimeter = cv2.arcLength(c,True)
if perimeter > 188:
x,y,w,h = cv2.boundingRect(c)
cv2.rectangle(frame, (x, y), (x+w, y+h), (123, 123, 17), 2)
遍历所有轮廓,对于判断为运动的物体,筛选出超过阈值的情况,然后画出矩形框。
最后显示结果
代码链接:
https://pan.baidu.com/s/1glpTqbO60uJG85n-_iJNTw
提取码:unwn
至此,基于混合高斯模型的背景建模任务完成。
感谢:
https://blog.csdn.net/qq_42152399/article/details/80383967
https://blog.csdn.net/u012193416/article/details/79312972