OpenCV实现视频背景消除与前景ROI提取

文章转载自https://zhuanlan.zhihu.com/p/67935932,如需了解更多,请查看原文。

概述

✔️ 背景减除(Background Subtraction)是许多基于计算机视觉的任务中的主要预处理步骤。

✔️ 如果有完整的静止的背景帧,可以通过帧差法来计算像素差从而获取到前景对象。但是在大多数情况下,没有这样的图像,所以需要从拥有的任何图像中提取背景。当运动物体有阴影时,由于阴影也在移动,情况会变的变得更加复杂。为此引入了背景减除算法,通过这一方法我们能够从视频中分离出运动的物体前景,从而达到目标检测的目的。

背景消除

✔️ OpenCV中常用的两种背景消除方法,一种是基于高斯混合模型GMM实现的背景提取,另外一种是基于最近邻KNN实现的。

GMM模型

背景:

  • MOG2算法,高斯混合模型分离算法,基于Z.Zivkovic发布的两篇论文,即2004年发布的“Improved adaptive Gausian mixture model for background subtraction”和2006年发布的“Efficient Adaptive Density Estimation per Image Pixel for the Task of Background Subtraction”中提出
  • 它为每个像素选择适当数量的高斯分布,它可以更好地适应不同场景的照明变化等

API:

cv2.createBackgroundSubtractorMOG2(
int  history = 500, 
double  varThreshold = 16,
bool  detectShadows = true 
)

参数解释如下: - history表示过往帧数,500帧,选择history = 1就变成两帧差 - varThreshold表示像素与模型之间的马氏距离,值越大,只有那些最新的像素会被归到前景,值越小前景对光照越敏感。 - detectShadows 是否保留阴影检测,请选择False这样速度快点。

KNN模型

背景:

KNN算法(K-nearest neigbours - based Background/Foreground Segmentation Algorithm)。2006年,由Zoran Zivkovic 和Ferdinand van der Heijden在论文"Efficient adaptive density estimation per image pixel for the task of background subtraction."中提出。

API:

cv2.createBackgroundSubtractorKNN()

实例分析

背景

✔️ 引用Opencv官方Example里的视频 vtest.mp4 来实现背景消除和ROI行人提取。

方法

✔️ 主要通过视频中的背景进行建模,实现背景消除,生成mask图像,通过对mask二值图像分析实现对前景活动对象的区域的提取,整个步骤如下: 1. 初始化背景建模对象GMM 2. 读取视频一帧 3. 使用背景建模消除生成mask 4. 对mask进行轮廓分析提取ROI 5. 绘制ROI对象

代码

import numpy as np
import cv2

# read the video
cap = cv2.VideoCapture('vtest.avi')

# create the subtractor
fgbg = cv2.createBackgroundSubtractorMOG2(
    history=500, varThreshold=100, detectShadows=False)


def getPerson(image, opt=1):

    # get the front mask
    mask = fgbg.apply(frame)

    # eliminate the noise
    line = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 5), (-1, -1))
    mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, line)
    cv2.imshow("mask", mask)

    # find the max area contours
    out, contours, hierarchy = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    for c in range(len(contours)):
        area = cv2.contourArea(contours[c])
        if area < 150:
            continue
        rect = cv2.minAreaRect(contours[c])
        cv2.ellipse(image, rect, (0, 255, 0), 2, 8)
        cv2.circle(image, (np.int32(rect[0][0]), np.int32(rect[0][1])), 2, (255, 0, 0), 2, 8, 0)
    return image, mask


while True:
    ret, frame = cap.read()
    cv2.imwrite("input.png", frame)
    cv2.imshow('input', frame)
    result, m_ = getPerson(frame)
    cv2.imshow('result', result)
    k = cv2.waitKey(50)&0xff
    if k == 27:
        cv2.imwrite("result.png", result)
        cv2.imwrite("mask.png", m_)

        break
cap.release()
cv2.destroyAllWindows()

Input

Front Mask

Result

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值