利用Opencv-python 对视频背景进行简单估计

本文介绍了如何使用OpenCV和Python通过中位数法对视频背景进行估计,并结合运动帧检测技术,实现实时动态背景的静态处理。通过选取视频帧的中位数作为背景,然后对比当前帧与背景的差异来识别运动部分。适合处理计算资源有限的情况。
摘要由CSDN通过智能技术生成

引言

很多时候,计算机的处理能力并非十分强大,这种时候我们需要尽可能用简单的算法去实现目标。
本文对用静态相机做动态视频的处理进行了一个基本介绍,容许我们对动态的视频做一个静态的背景估计。

环境&工具

Win10

Python3.8.6 & Opencv4.4

中位数介绍

中位数的意义不言而喻,很多时候对一组数据采用平均数是一种简单有效的方式,然而有些时候,取中位数则是更好的方法。
中位数(Median)又称中值,是按顺序排列的一组数据中居于中间位置的数。
左右分别是好/坏温度计对数据的记录,显然,此时利用中位数所得到的数据比平均数更为精确

1.用中位数做背景估计

对于一个短视频流,我们可以从所有帧中提取一部分,对其中每一个像素进行分析,只要某一个像素没有被移动的物体遮挡超过一半的时间,我们可以取这一像素在每一帧中的值的中位数,以其值作为对该位置背景良好的估计。
我们会用到如下几种函数:

np.median(frames, axis=0).astype(dtype=np.uint8)
cap.get(cv2.CAP_PROP_FRAME_COUNT)

np.median利用了numpy包中的median函数直接求解数组中位数

cap.get(cv2.CAP_PROP_FRAME_COUNT)可以获取cap视频文件的总帧数(实际上是总帧数-1)

接下来我们来看背景估计的源代码(注释为英文且以及比较详尽):

import cv2 as cv
import numpy as np
from skimage import data, filters

# Capture Game Video
cap=cv.VideoCapture('NBA 2K20 2020-10-13 21-44-03.mp4')

# Random 100 frames (7*60=420 frames in total) 
# Use np.random.uniform to generate 100
#cv.CAP_PROP_FRAME_COUNT counts the number of frames in the video
frameIds=cap.get(cv.CAP_PROP_FRAME_COUNT)*np.random.uniform(size=30)

# Store selected frames in an array 'frame'
frames=[]
for i in frameIds:
    cap.set(cv.CAP_PROP_POS_FRAMES,i)
    ret,frame=cap.read()
    frames.append(frame)

#Calculate the median along the time axis
medianFrame = np.median(frames, axis=0).astype(dtype=np.uint8)

cv.imshow('Median Frame',medianFrame)
cv.waitKey(0)


原视频为运动员从一侧跑到另一侧投篮的视频

原视频截图:
在这里插入图片描述

进行背景中位估算之后,得到的背景图如下:
在这里插入图片描述

2.运动帧检测

很多时候,由于计算机计算能力有限,如果对图片中的每一个像素都进行检测,计算量将很大。我们可以类比某些动物,它们只对运动中的物体比较敏感。类似的,我们可以对每一帧建立mask遮罩,先把之前获得的中值图和现有帧率图变为灰度图,然后做减法,与背景(Background)相差较大的像素便是运动的部分,因为他们遮挡了背景像素

下面来看代码:

# Reset frame number to 0
cap.set(cv.CAP_PROP_POS_FRAMES, 0)
#Convert background to grayscale
grayMedianFrame=cv.cvtColor(medianFrame,cv.COLOR_BGR2GRAY)

#Loop over all frames
ret=True
while(ret):

    #Read frame
    ret, frame = cap.read()
    # Convert current frame to grayscale
    frame = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
    # difference of two frames
    dframe = cv.absdiff(frame, grayMedianFrame)
    # Threshold to binarize 阈值去噪声,二值化输出
    th,dframe = cv.threshold(dframe,30,255,cv.THRESH_BINARY)
    # Display image
    cv.imshow("Binary",dframe)
    cv.waitKey(20)

# Release video object
cap.release()

# Destroy all windows
cv2.destroyAllWindows()

输出截图如下:
在这里插入图片描述

有时间后续我会补上输入输出的动图,以便观察。

参考教程

参考了learnopencv官网的博客,有一定修改
LearnOpencv Simple Background estimation

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值