用OpenCV检测行人移动方向

项目介绍

在此文章中,我们将使用 python 中的 opencv 库创建一个运动热图,用于检测物体或人的流动方向。

输入:一段包含行人运动的视频文件。
输出:运动热图视频,其中的一帧如下图所示:
在这里插入图片描述
使用的 python 及 opencv 库的版本为:

  • python:3.7;
  • opencv-python:4.2.0.34;
  • opencv-contrib-python:4.2.0.34。

实现流程

这个程序是基于一种被称为高斯背景差法的技术,这项技术被广泛应用于用稳定的摄像机检测运动物体。
背景差法创建一个表示帧(图像的静态部分)背景的模板,对于每一帧,它将减去前一帧。
其主要步骤只有两个:

  • 背景初始化:在第一步中,通过冻结第一帧来计算背景的模型;
  • 更新:在第二步中,下一帧将减去上一帧,如果两帧之间发生变化(移动),则这些帧的差异将反映出该变化,可以通过应用过滤器来进行提取差异信息。

代码实现

1. 导入需要的库

import cv2
import copy
import matplotlib.pyplot as plt

2. 读取原始视频并统计帧数

capture = cv2.VideoCapture('test.avi')
length = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))

3. 实例化背景消除器

background_subtractor = cv2.bgsegm.createBackgroundSubtractorMOG()

4. 设置制作的视频的参数

fourcc = cv2.VideoWriter_fourcc(*'XVID')
# width 和 height 可以通过打印下面的 frame.shape 来查看
width = 768
height = 576
video = cv2.VideoWriter('output.avi', fourcc, 30.0, (width, height))

5. 对每一帧进行热图处理

for i in range(0, length-1):

    ret, frame = capture.read()

    # 检查是不是第一帧
    # 初始化背景差法的背景
    if i == 0:

        first_frame = copy.deepcopy(frame)
        height, width = frame.shape[:2]
        accum_image = np.zeros((height, width), np.uint8)  # 初始化 accum_image 数组
    
    fgmask = background_subtractor.apply(frame)  # 消除背景

	# 为了消除例如风,小鸟飞行等少量运动,将阈值与maxValue一起应用到掩膜上。
    threshold = 2
    maxValue = 2
    ret, th1 = cv2.threshold(fgmask, threshold, maxValue, cv2.THRESH_BINARY)
    
    accum_image = cv2.add(accum_image, th1)  # 将掩膜的结果添加到 accum_image 数组中

    color_image_video = cv2.applyColorMap(accum_image, cv2.COLORMAP_HOT)  # 颜色映射被应用于掩膜

    video.write(cv2.add(frame, color_image_video))  # 将掩膜与当前帧合并后写入视频文件

6. 播放制作的视频文件

cap = cv2.VideoCapture('output.avi')
while 1:
    ret, frame = cap.read()  #cap.read()函数返回的第1个参数ret(return value缩写)是一个布尔值,表示当前这一帧是否获取正确
    cv2.imshow("cap", frame)
    if cv2.waitKey(5) & 0xff == ord('q'):  # waitKey的参数表示暂停时间,所以这个值越大,视频播放速度越慢
        break
cap.release()
cv2.destroyAllWindows()

完整代码

import cv2
import copy
import matplotlib.pyplot as plt

capture = cv2.VideoCapture('test.avi')
background_subtractor = cv2.bgsegm.createBackgroundSubtractorMOG()
length = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))

fourcc = cv2.VideoWriter_fourcc(*'XVID')
width = 768
height = 576
video = cv2.VideoWriter('output.avi', fourcc, 30.0, (width, height))

for i in range(0, length-1):

    ret, frame = capture.read()

    if i == 0:

        first_frame = copy.deepcopy(frame)
        height, width = frame.shape[:2]
        accum_image = np.zeros((height, width), np.uint8)
    
    fgmask = background_subtractor.apply(frame)

    threshold = 2
    maxValue = 2
    ret, th1 = cv2.threshold(fgmask, threshold, maxValue, cv2.THRESH_BINARY)
    
    accum_image = cv2.add(accum_image, th1)

    color_image_video = cv2.applyColorMap(accum_image, cv2.COLORMAP_HOT)

    video.write(cv2.add(frame, color_image_video))

cap = cv2.VideoCapture('output.avi')
while 1:
    ret, frame = cap.read()
    cv2.imshow("cap", frame)
    if cv2.waitKey(5) & 0xff == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()

猜你喜欢

转载自blog.csdn.net/qq_36758914/article/details/106805074