使用Python,OpenCV捕获关键事件,并进行视频剪辑

    • 1. 效果图
    • 2. 原理
      • 2.1 步骤
      • 2.2 如何找到HSV空间值呢?
  • [[[60 255 255]]]
    • 3. 源码
      • 3.1 keyclipwriter.py
      • 3.2 save_key_events.py
    • 参考

上一篇博客介绍了如何使用Python、OpenCV写入视频文件,这一篇将介绍如何做有趣的视频剪辑,而不是保留整个视频文件;

总体目标是构建视频概要,将视频流的最关键,突出和有趣部分提炼成一系列短视频文件。

使用场景有:

  • 访问在区域中检测到的运动物体;
  • 截取入侵者进入房子或公寓的片段;

什么才是视频的关键帧、有趣部分,则完全取决于您的需求和目标;

使用此方法,可以将小时级的视频流素材缩小为多个秒级的有趣事件的小视频,有效地产生视频概要。

1. 效果图

检测画面中的绿色盆,并将其生成gif图,如下:

2. 原理

2.1 步骤

  1. 定义关键事件;
  2. 将包含事件的视频片段写入到视频文件;

利用线程以确保在输入流和输出视频剪辑文件中执行I / O时,不会放慢主程序的速度。
利用内置的Python数据结构,如DEQUE队列以按顺序存放关键帧;

2.2 如何找到HSV空间值呢?

比如要寻找绿色,可以找到绿色对应的BGR(0,255,0) ,利用opencv转换为HSV,然后取[ H-10,S,V]为下限 – [ H+10,S,V]为上限;

green = np.uint8([[[0, 255, 0]]])
hsv_green = cv2.cvtColor(green, cv2.COLOR_BGR2HSV)
print(hsv_green)

[[[60 255 255]]]

3. 源码

3.1 keyclipwriter.py

# 导入必要的包
from collections import deque # 导入队列,FIFO(first in first out)先进先出原则
from threading import Thread
from queue import Queue
import time
import cv2class KeyClipWriter:# bufSize 要在内存缓冲区中缓存的最大帧数# timeout 超时时间def __init__(self, bufSize=64, timeout=1.0):# 存储在内存中要保留的最大缓冲区大小 以及睡眠超时期间self.bufSize = bufSizeself.timeout = timeout# 初始化帧的缓冲区(64帧)、Q:待写入的视频帧、视频写入类、 多线程(以避免I/O延迟)# recordering boolean类型指示录制是否已启动self.frames = deque(maxlen=bufSize)self.Q = Noneself.writer = Noneself.thread = Noneself.recording = Falsedef update(self, frame):# 更新帧缓冲区self.frames.appendleft(frame)# 如果正在记录,将帧加入队列if self.recording:self.Q.put(frame)def start(self, outputPath, fourcc, fps):# 展示正在记录关键事件帧# 表明正在录制,启动视频写入类,初始化需要写入视频文件的帧队列self.recording = Trueself.writer = cv2.VideoWriter(outputPath, fourcc, fps,(600,600), True)self.Q = Queue()# 循环遍历所有帧,并加入队列for i in range(len(self.frames), 0, -1):self.Q.put(self.frames[i - 1])# 开启一个单独的线程写入帧到视频文件self.thread = Thread(target=self.write, args=())self.thread.daemon = Trueself.thread.start()def write(self):# 保持循环while True:# 如果停止了录制,退出线程if not self.recording:return# 判断队列是否已经没有关键事件帧了if not self.Q.empty():# 获取队列中的下一帧并写入视频文件frame = self.Q.get()self.writer.write(frame)# 如果队列已经空了,sleep超时时间以不浪费cpu周期# 使用队列时空闲一会儿尤其重要,队列数据结构是线程安全的,暗示必须在更新内部缓冲区之前获取锁/信号量。# 如果不sleep,当缓冲区为空时,然后写入和更新方法将不断为锁而战斗。相反,最好让视频写入类等待一会儿,直到需要写入文件的队列中存在积压的帧。else:time.sleep(self.timeout)def flush(self):# 通过刷新所有剩余帧来清空队列while not self.Q.empty():frame = self.Q.get()self.writer.write(frame)def finish(self):# 表明结束录制、加入线程# 刷新队列中的所有帧到视频文件# 释放视频写入指针self.recording = Falseself.thread.join()self.flush()self.writer.release()

3.2 save_key_events.py

# USAGE
# python save_key_events.py --output output#  导入必要的包
from pyimagesearch.keyclipwriter import KeyClipWriter
from imutils.video import VideoStream
import argparse
import datetime
import imutils
import time
import cv2# 构建命令行参数及解析
# --output 输出视频剪辑文件的路径及名称
# --picamera 是否使用树莓摄像头,默认-1:不是
# --fps 输出视频剪辑的帧率(即每秒的帧数) 默认20
# --codec 输出视频剪辑的四维编解码器 默认MJPG
# --buffer-size 视频剪切类的缓冲区大小 默认32,用于存储来自相机传感器最近轮询帧的内存缓冲区的大小。
#               较大的缓冲大小将允许在“关键事件”中包含在输出视频剪辑中的“关键事件”之前和之后的更多上下文,而较小的缓冲大小将在“关键事件”之前和之后存储更少的帧;
ap = argparse.ArgumentParser()
ap.add_argument("-o", "--output", required=True,help="path to output directory")
ap.add_argument("-p", "--picamera", type=int, default=-1,help="whether or not the Raspberry Pi camera should be used")
ap.add_argument("-f", "--fps", type=int, default=20,help="FPS of output video")
ap.add_argument("-c", "--codec", type=str, default="MJPG",help="codec of output video")
ap.add_argument("-b", "--buffer-size", type=int, default=32,help="buffer size of video clip writer")
args = vars(ap.parse_args())# 初始化视频流,并预热相机传感器2s
print("[INFO] warming up camera...")
vs = VideoStream(usePiCamera=args["picamera"] > 0).start()
time.sleep(2.0)# 定义绿色球的较低和上边界HSV颜色空间
greenLower = (29, 86, 6)
greenUpper = (64, 255, 255)# 初始化关键事件剪辑类,
# 初始化用于计算尚未包含任何有趣事件的连续帧数的整数。
kcw = KeyClipWriter(bufSize=args["buffer_size"])
consecFrames = 0# 保持循环
while True:# 获取当前帧,缩放,初始化一个布尔类型值updateConsecFrames表示是否连续帧计数器应该被更新frame = vs.read()frame = imutils.resize(frame, width=600)updateConsecFrames = True# 高斯模糊帧,并将其RGB颜色空间转换为HSV颜色空间,因此可以使用颜色阈值blurred = cv2.GaussianBlur(frame, (11, 11), 0)hsv = cv2.cvtColor(blurred, cv2.COLOR_BGR2HSV)# 为绿色构建一个颜色mask,然后执行一系列腐蚀膨胀操作已移除mask中小斑点# cv2.inRange实际进行颜色阈值处理,cv2.erode腐蚀,cv2.dilate膨胀操作mask = cv2.inRange(hsv, greenLower, greenUpper)mask = cv2.erode(mask, None, iterations=2)mask = cv2.dilate(mask, None, iterations=2)# 在mask中查找轮廓cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)cnts = imutils.grab_contours(cnts)# 当发现轮廓时继续处理if len(cnts) > 0:# 寻找mask中最大的轮廓,计算最小外接圆c = max(cnts, key=cv2.contourArea)((x, y), radius) = cv2.minEnclosingCircle(c)updateConsecFrames = radius <= 10# 只有当外接圆轮廓达到一定值时处理if radius > 10:# 重置连续帧计数器为0,绘制外接圆轮廓到帧上consecFrames = 0cv2.circle(frame, (int(x), int(y)), int(radius),(0, 0, 255), 2)# 如果还没开始计关键事件帧数,开始记录if not kcw.recording:timestamp = datetime.datetime.now()p = "{}/{}.avi".format(args["output"],timestamp.strftime("%Y%m%d-%H%M%S"))kcw.start(p, cv2.VideoWriter_fourcc(*args["codec"]),args["fps"])# 如果帧中没有任何事件,将没有关键事件帧的帧计数if updateConsecFrames:consecFrames += 1# 更新关键事件帧缓存区kcw.update(frame)# 如果没有关键事件的帧达到一定数量,计数记录剪辑if kcw.recording and consecFrames == args["buffer_size"]:kcw.finish()# 展示帧cv2.imshow("Frame", frame)key = cv2.waitKey(1) & 0xFF# 按下‘q’键,退出循环if key == ord("q"):break# 如果还在录制中,结束录制
if kcw.recording:kcw.finish()# 清理工作,释放窗口,释放视频文件写入指针
cv2.destroyAllWindows()
vs.stop()

参考

  • https://www.pyimagesearch.com/2016/02/29/saving-key-event-video-clips-with-opencv/

使用Python,OpenCV捕获关键事件,并进行视频剪辑相关推荐

  1. 使用Python和OpenCV捕获鼠标事件,并裁剪图像

    使用Python和OpenCV捕获鼠标事件,并裁剪图像 1. 效果图 2. 源码 参考 这篇博客将介绍如何使用Python和OpenCV捕获鼠标事件.还演示了如何快速裁剪和提取图像区域,这在为自己的自 ...

  2. python+opencv 实现图像人脸检测及视频中的人脸检测

    执着于理想,纯粹于当下. 文章目录 一.数据和知识准备 1. 下载HAAR与LBP数据 2. opencv相关知识 二.python+opencv实现人脸检测 1. 图像单人脸检测 2. 图像多人脸检 ...

  3. Python OpenCV高速公路道路汽车车辆摄像头视频侦测检测识别统计数量

    Python OpenCV高速公路道路汽车车辆侦测检测识别统计数量 如需安装运行环境或远程调试,可加QQ905733049由专业技术人员远程协助! 运行结果如下: 运行主要代码如下: import c ...

  4. python在哪下快播_moviepy音视频剪辑:使用fl_time进行诸如快播、慢播、倒序播放等时间特效处理的原理和可能遇到的坑...

    一.引言 在<moviepy音视频剪辑:moviepy中的剪辑基类Clip的属性和方法详解>介绍了fl_time方法返回一个新剪辑,新剪辑是调用剪辑的一个浅拷贝,但新剪辑的时间线被调整,实 ...

  5. Python+OpenCV 图像处理系列(2)—— 视频捕获、播放和保存

    1.视频捕获 为了获取视频,首先需要创建一个 VideoCapture 类对象.它的参数可以是设备的索引号,或者是一个视频文件.设备索引号就是在指定要使用的摄像头.一般的笔记本电脑都有内置摄像头.所以 ...

  6. Python Opencv 实现鼠标事件(包含一个练习)——事件触发讲解·以及鼠标回调函数的实现

    文章目录 鼠标事件概述 鼠标事件发生的结构 鼠标回调函数的标准格式 opencv下包含的所有事件--包含flag和event(可以看一下,熟悉常见事件范围) 鼠标事件的实现函数 一个完整的鼠标事件由一 ...

  7. android 蓝牙耳机按钮,如何利用android从蓝牙耳机中捕获关键事件_bluetooth_开发99编程知识库...

    将广播侦听器添加到 MEDIA_BUTTON: 你应该在应用程序( 不在清单文件中) 中注册你的广播接收器. 否则,谷歌音乐播放器将捕捉你的广播和船上. 你的IntentFilter 优先级应该高于其 ...

  8. python+opencv+PIL,在图片和视频中写入中文(汉字)

    原博客地址:https://blog.csdn.net/wyx100/article/details/80412101 效果 代码 #!/usr/bin/env python # -*- coding ...

  9. 使用Python+OpenCV将连续图片生成avi视频

    import cv2 import osim_dir = '...' # 图片存储路径 video_dir = '.../a.avi' # 视频存储路径及视频名 fps = 30 # 帧率一般选择20 ...

最新文章

  1. NSInputStream和NSMutableURLRequest-实现保存文件到服务器
  2. OpenCV图像处理使用笔记(八)——Sobel算子
  3. oracle+测试权限,Oracle测试题
  4. Angular 2 JIT vs AOT
  5. 阿里云插件新版发布,多特性助力提升开发者体验
  6. NGINX 配置超时时间
  7. amazeui学习笔记--css(常用组件1)--小徽章Badge
  8. OpenResty 简单编写一个Module
  9. android中The connection to adb is down .. You must restart adb and Eclipse问题的解决
  10. python中字符串模块_Python字符串模块
  11. php实现des加密,如何在PHP项目中实现一个DES加密解密功能
  12. Unity小游戏教程系列 | 创建小型太空射击游戏(二)
  13. Groovy语法介绍
  14. 计算机哪些方向发展前景,计算机就业的几个方向
  15. iPhone照片的云端备份和本地移动硬盘备份 策略
  16. PostgreSQL+PostGIS的使用
  17. SAP云集成 SAP Integration Suite启用过程,踩坑记
  18. 云效平台代码管理使用总结
  19. 诙谐幽默的个性自我介绍
  20. 转载--期指迎来首个交割日

热门文章

  1. python的 局部变量与全局变量
  2. python xlrd 的merged_cells 里面四个参数的含义
  3. Android shape 画的圆角带四个黑变 问题
  4. Java之Spring mvc详解(非原创)
  5. Openfire XMPP Smack RTC IM 即时通讯 聊天 MD
  6. k64 datasheet学习笔记35---Analog-to-Digital Converter (ADC)
  7. 2021襄阳谷城高考成绩查询,2021高考襄阳谷城县考生求助电话
  8. 2022-2028年中国搪胶行业市场深度分析及投资前景分析报告
  9. SQL中返回一个字符串在另一个中存在的次数
  10. 判断交换机性能好坏的九个因素