• 第二周学习报告


    第二周学习报告

    学习目标

    • 背景建模
    • 目标追踪

    学习内容:

    1、帧差法
    2、混合高斯模型
    3、光流估计

    学习时间:

    9.11 ~9.17

    学习产出:

    背景建模是针对摄像头固定场景,对场景中的所有运动的动目标进行分割的一种方法。因此场景必须是固定的,目标必须是运动的。

    一、帧差法

    由于场景中的目标在运动,目标的影像在不同图像帧中的位置不同。该类算法对时间上连续的两帧图像进行差分运算,不同帧对应的像素点相减,判断灰度差的绝对值。当超过一定阈值时,即可判断为运动的目标,从而实现目标检测功能。帧差法一般分为两帧差分和三帧差分。
    两帧差分:
    取连续的两帧序列,用后一帧减去前一帧,将其结果与阈值比较。
    三帧差分:
    取连续的三帧序列 k、k+1、k+2,先让前两帧差分,再让后两帧差分,最后对这两个差分图做与运算。

    二、混合高斯模型

    高斯混合模型(Gaussian Mixture Model)通常简称GMM,是一种业界广泛使用的聚类算法,该方法使用了高斯分布作为参数模型,并使用了期望最大(Expectation Maximization,简称EM)算法进行训练。
    
    • 1

    在进行前景检测前,先对背景进行训练,对图像中每个背景采用一个混合高斯模型进行模拟,每个背景的混合高斯的个数可以自适应。然后在测试中对新来的像素进行GMM匹配,如果该像素值能够匹配其中一个高斯,则认为是背景,否则认为是前景。

    混合高斯模型学习方法:

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

    混合高斯模型测试方法
    在测试阶段,对新来像素点的值与混合高斯模型中的每一个均值比较,如果其差值在两倍方差之间则认为是背景,否则认为是前景(人)。将前景赋值为255,背景赋值为0。这样就形成了一幅前景二值图
    在这里插入图片描述
    测试代码

    cap = cv.VideoCapture('./video/02.mp4')
    kernel = cv.getStructuringElement(cv.MORPH_ELLIPSE, (3, 3))
    # 混合高斯模型
    fgbg = cv.createBackgroundSubtractorMOG2()
    
    while (True):
        ret, frame = cap.read()
        fgmask = fgbg.apply(frame)
        # 形态学开运算去噪声
        fgmask = cv.morphologyEx(fgmask, cv.MORPH_OPEN, kernel)
        contours, hierarchy = cv.findContours(fgmask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    
        # 寻找轮廓
        for c in contours:
            # 计算周长
            peri = cv.arcLength(c, True)
            if peri > 188:
                (x, y, w, h) = cv.boundingRect(c)
                cv.rectangle(frame, (x, y), (x + w, y + h), (0, 0, 255), 2)
    
        cv.imshow('frame', frame)
        cv.imshow('fgmask', fgmask)
        k = cv.waitKey(150) & 0xff
        if k == 27:
            break
    cap.release()
    
    • 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

    三、光流估计

    光流是指在连续的两帧图像当中,由于图像中的物体移动或者摄像头的移动而使得图像中的目标形成的矢量运动轨迹叫做光流。本质上光流是个向量场,表示了一个像素点从第一帧过渡到第二帧的运动过程,体现该像素点在成像平面上的瞬时速度。
    光流估计基于以下三个假设:

    • 亮度恒定:同一点随着时间的变化,其亮度不会发生变化
    • 小运动:随着时间的变化不会引起位置的剧烈变化,只有小运动情况下才能用前后帧之间单位位置变化引起的灰度变化去近似灰度对位置的偏导数
    • 空间一致:一个场景上邻近的点投影到图像上也是邻近的点,且邻近点速度一致。因为光流法基本方程约束只有一个,而要求x、y方向的速度,有两个未知变量,所以需要联立n多个方程求解。
      光流估计算法有稀疏光流估计算法cv2.calcOpticalFlowPyrLK()稠密光流估计cv2.calcOpticalFlowFarneback()。稀疏光流估计算法为Lucas-Kanade算法

    光流估计效果图:
    在这里插入图片描述
    测试代码:

    
    cap = cv.VideoCapture('./video/02.mp4')
    
    # 角点检测所需参数
    feature_params = dict(maxCorners=100, qualityLevel=0.3, minDistance=7)
    
    # lucas kanade参数,maxLevel为金字塔层级,winSize表示选择多少个点进行u和v的求解。
    lk_params = dict(winSize=(15, 15), maxLevel=2)
    # 随机颜色条
    color = np.random.randint(0, 255, (100, 3))
    
    # 拿到第一帧图像
    ret, old_frame = cap.read()
    old_gray = cv.cvtColor(old_frame, cv.COLOR_BGR2GRAY)
    
    # 返回所有检测特征点,需要传入图像,角点最大数量(效率),品质因子(特征值越大越好)来筛选
    # 距离相当于在该区间内只取最大的
    p0 = cv.goodFeaturesToTrack(old_gray, mask=None, **feature_params)
    print('p0',p0)
    
    # 创建一个mask
    mask = np.zeros_like(old_frame)
    
    while (True):
        # 读取当前帧
        ret, frame = cap.read()
        # 转为灰度
        frame_gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
        # p1表示光流检测后的角点位置,同p0一样,也是一个数组,对应是第一个点的位置,st表示该角点是否是运动的角点,err表示是否出错。
        p1, st, err = cv.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
        print('p1',p1)
    
        # st == 1 表示有用的特征点
        good_new = p1[st == 1]
        good_old = p0[st == 1]
    
        # 绘制轨迹
        for i, (new, old) in enumerate(zip(good_new, good_old)):
            # ravel()函数用于将二维数组或多维数组更改为连续的扁平数组
            a, b = new.ravel()
            c, d = old.ravel()
            mask = cv.line(mask, (int(a), int(b)), (int(c), int(d)), color[i].tolist(), 2)
            frame = cv.circle(frame, (int(a), int(b)), 5, color[i].tolist(), -1)
        img = cv.add(frame, mask)
    
        cv.imshow('img', img)
        k = cv.waitKey(150) & 0xff
        if k == 27:
            break
    
        # 更新
        old_gray = frame_gray.copy()
        p0 = good_new.reshape(-1, 1, 2)
    
    cv.destroyAllWindows()
    cap.release()
    
    • 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
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
  • 相关阅读:
    java继承
    Vue---方法和事件绑定
    【Spring常见错误】No qualifying bean of type
    刷题leetcode-两数之和
    it端到端运营监控
    【毕业设计】大数据房价数据分析可视化 - python
    el-table 合集行合并
    007.iSCSI服务器CHAP双向认证配置
    企业应用架构研究系列三:应用系统集成
    鹰潭恒温恒湿实验室设计方案总结
  • 原文地址:https://blog.csdn.net/weixin_44432831/article/details/126914350