博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OpenCV计算机视觉实战 - Task7 - 背景建模 & 光流估计
阅读量:4091 次
发布时间:2019-05-25

本文共 3861 字,大约阅读时间需要 12 分钟。

###############################################################

纸上得来终觉浅,绝知此事要躬行
视频
新课件:https://pan.baidu.com/s/1frWHqCVGR2VTn5QBtW4lPA 提取码:xh02
老课件:https://pan.baidu.com/s/1Wi31FxSPBqWiuJX9quX-jA 提取码:bbfg
##############################################################

一、背景建模

法1:帧差法

由于场景中的目标在运动,目标的影像在不同图像帧中的位置不同。该类算法对时间上连续的两帧图像进行差分运算,不同帧对应的像素点相减,判断灰度差的绝对值,当绝对值超过一定阈值时,即可判断为运动目标,从而实现目标的检测功能。

在这里插入图片描述
背景为0,运动目标为1,过滤掉背景

帧差法非常简单,但是会引入噪音 和 空洞问题

法2:混合高斯模型

在进行前景检测前,先对背景进行训练,对图像中每个背景采用一个混合高斯模型进行模拟,每个背景的混合高斯的个数可以自适应。

然后在测试阶段,对新来的像素进行GMM(高斯混合模型)匹配,如果该像素值能够匹配其中一个高斯,则认为是背景,否则认为是前景
由于整个过程GMM模型在不断更新学习中,所以对动态背景有一定的鲁棒性。最后通过对一个有树枝摇摆的动态背景进行前景检测,取得了较好的效果。

在视频中对于像素点的变化情况应当是符合高斯分布

在这里插入图片描述
背景的实际分布应当是多个高斯分布混合在一起每个高斯模型也可以带有权重
在这里插入图片描述

混合高斯模型学习方法1.首先初始化每个高斯模型矩阵参数。	2.取视频中T帧数据图像用来训练高斯混合模型。来了第一个像素之后用它来当做第一个高斯分布。	3.当后面来的像素值时,与前面已有的高斯的均值比较,	如果该像素点的值与其模型均值差在3倍的方差内,则属于该分布,并对其进行参数更新。4.如果下一次来的像素不满足当前高斯分布,用它来创建一个新的高斯分布。

混合高斯模型测试方法

在测试阶段,对新来像素点的值与混合高斯模型中的每一个均值进行比较,如果其差值在2倍的方差之间的话,则认为是背景,否则认为是前景。将前景赋值为255,背景赋值为0。这样就形成了一副前景二值图。

在这里插入图片描述

import numpy as npimport cv2# 经典的测试视频cap = cv2.VideoCapture('test.avi')# 形态学操作需要使用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)    # 寻找视频中的轮廓    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),(0,255,0),2)        cv2.imshow('frame',frame)    cv2.imshow('fgmask', fgmask)    k = cv2.waitKey(150) & 0xff    if k == 27:        breakcap.release()cv2.destroyAllWindows()

缺点:不适用于复杂背景

二、光流估计

光流是空间运动物体在观测成像平面上的像素运动的 “瞬时速度”,根据各个像素点的速度矢量特征,可以对图像进行动态分析,例如目标跟踪。

  1. 亮度恒定:同一点随着时间的变化,其亮度不会发生改变。

  2. 小运动:随着时间的变化不会引起位置的剧烈变化,只有小运动情况下才能用前后帧之间单位位置变化引起的灰度变化去近似灰度对位置的偏导数。

  3. 空间一致:一个场景上邻近的点投影到图像上也是邻近点,且邻近点速度一致。因为光流法基本方程约束只有一个,而要求x,y方向的速度,有两个未知变量。所以需要连立n多个方程求解。

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    如何求解方程组呢?看起来一个像素点根本不够,在物体移动过程中还有哪些特性呢?
    在这里插入图片描述

  • cv2.calcOpticalFlowPyrLK():

    参数:
    prevImage 前一帧图像
    nextImage 当前帧图像
    prevPts 待跟踪的特征点向量
    winSize 搜索窗口的大小
    maxLevel 最大的金字塔层数

    返回:

    nextPts 输出跟踪特征点向量
    status 特征点是否找到,找到的状态为1,未找到的状态为0

  • cv2.goodFeaturesToTrack:去跟踪好的特征

    feature_params
    qualityLevel 品质因子越大,得到的角点越少
    maxLevel 在这个距离范围内,哪个品质因子最强

import numpy as npimport cv2cap = cv2.VideoCapture('test.avi')# 角点检测所需参数feature_params = dict( maxCorners = 100,                       qualityLevel = 0.3,                       minDistance = 7)# lucas kanade参数lk_params = dict( winSize  = (15,15),                  maxLevel = 2)# 随机颜色条color = np.random.randint(0,255,(100,3))# 拿到第一帧图像ret, old_frame = cap.read()old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)# 返回所有检测特征点,需要输入图像,角点最大数量(效率),品质因子(特征值越大的越好,来筛选)# 距离相当于这区间有比这个角点强的,就不要这个弱的了p0 = cv2.goodFeaturesToTrack(old_gray, mask = None, **feature_params) # 第一帧的角点# 创建一个maskmask = np.zeros_like(old_frame)while(True):    ret,frame = cap.read()    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)    # 需要传入前一帧和当前图像以及前一帧检测到的角点    p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)    # st=1表示    good_new = p1[st==1]    good_old = p0[st==1]    # 绘制轨迹    for i,(new,old) in enumerate(zip(good_new,good_old)):        a,b = new.ravel()        c,d = old.ravel()        mask = cv2.line(mask, (a,b),(c,d), color[i].tolist(), 2)        frame = cv2.circle(frame,(a,b),5,color[i].tolist(),-1)    img = cv2.add(frame,mask)    cv2.imshow('frame',img)    k = cv2.waitKey(150) & 0xff    if k == 27:        break    # 更新    old_gray = frame_gray.copy() # 当前帧作为old帧    p0 = good_new.reshape(-1,1,2)cv2.destroyAllWindows()cap.release()

缺点:

  1. 前一帧检测不到的角点(st=0),下一帧(及后续帧)也都检测不到。
  2. 以视频的第一帧为背景,后面出现的新目标也检测不到

转载地址:http://pujii.baihongyu.com/

你可能感兴趣的文章
前端设计之特效表单
查看>>
前端设计之CSS布局:上中下三栏自适应高度CSS布局
查看>>
Java的时间操作玩法实例若干
查看>>
JavaScript:时间日期格式验证大全
查看>>
pinyin4j:拼音与汉字的转换实例
查看>>
XML工具代码:SAX从String字符串XML内获取指定节点或属性的值
查看>>
时间日期:获取两个日期相差几天
查看>>
责任链模式 Chain of Responsibility
查看>>
高并发与大数据解决方案概述
查看>>
解决SimpleDateFormat线程安全问题NumberFormatException: multiple points
查看>>
MySQL数据库存储引擎简介
查看>>
处理Maven本地仓库.lastUpdated文件
查看>>
Kafka | 请求是怎么被处理的?
查看>>
Java并发编程1-线程池
查看>>
CentOS7,玩转samba服务,基于身份验证的共享
查看>>
计算机网络-网络协议模型
查看>>
计算机网络-OSI各层概述
查看>>
Java--String/StringBuffer/StringBuilder区别
查看>>
mySQL--深入理解事务隔离级别
查看>>
分布式之redis复习精讲
查看>>