使用Python,OpenCV捕获关键事件,并进行视频剪辑
使用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 步骤
- 定义关键事件;
- 将包含事件的视频片段写入到视频文件;
利用线程以确保在输入流和输出视频剪辑文件中执行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捕获关键事件,并进行视频剪辑相关推荐
- 使用Python和OpenCV捕获鼠标事件,并裁剪图像
使用Python和OpenCV捕获鼠标事件,并裁剪图像 1. 效果图 2. 源码 参考 这篇博客将介绍如何使用Python和OpenCV捕获鼠标事件.还演示了如何快速裁剪和提取图像区域,这在为自己的自 ...
- python+opencv 实现图像人脸检测及视频中的人脸检测
执着于理想,纯粹于当下. 文章目录 一.数据和知识准备 1. 下载HAAR与LBP数据 2. opencv相关知识 二.python+opencv实现人脸检测 1. 图像单人脸检测 2. 图像多人脸检 ...
- Python OpenCV高速公路道路汽车车辆摄像头视频侦测检测识别统计数量
Python OpenCV高速公路道路汽车车辆侦测检测识别统计数量 如需安装运行环境或远程调试,可加QQ905733049由专业技术人员远程协助! 运行结果如下: 运行主要代码如下: import c ...
- python在哪下快播_moviepy音视频剪辑:使用fl_time进行诸如快播、慢播、倒序播放等时间特效处理的原理和可能遇到的坑...
一.引言 在<moviepy音视频剪辑:moviepy中的剪辑基类Clip的属性和方法详解>介绍了fl_time方法返回一个新剪辑,新剪辑是调用剪辑的一个浅拷贝,但新剪辑的时间线被调整,实 ...
- Python+OpenCV 图像处理系列(2)—— 视频捕获、播放和保存
1.视频捕获 为了获取视频,首先需要创建一个 VideoCapture 类对象.它的参数可以是设备的索引号,或者是一个视频文件.设备索引号就是在指定要使用的摄像头.一般的笔记本电脑都有内置摄像头.所以 ...
- Python Opencv 实现鼠标事件(包含一个练习)——事件触发讲解·以及鼠标回调函数的实现
文章目录 鼠标事件概述 鼠标事件发生的结构 鼠标回调函数的标准格式 opencv下包含的所有事件--包含flag和event(可以看一下,熟悉常见事件范围) 鼠标事件的实现函数 一个完整的鼠标事件由一 ...
- android 蓝牙耳机按钮,如何利用android从蓝牙耳机中捕获关键事件_bluetooth_开发99编程知识库...
将广播侦听器添加到 MEDIA_BUTTON: 你应该在应用程序( 不在清单文件中) 中注册你的广播接收器. 否则,谷歌音乐播放器将捕捉你的广播和船上. 你的IntentFilter 优先级应该高于其 ...
- python+opencv+PIL,在图片和视频中写入中文(汉字)
原博客地址:https://blog.csdn.net/wyx100/article/details/80412101 效果 代码 #!/usr/bin/env python # -*- coding ...
- 使用Python+OpenCV将连续图片生成avi视频
import cv2 import osim_dir = '...' # 图片存储路径 video_dir = '.../a.avi' # 视频存储路径及视频名 fps = 30 # 帧率一般选择20 ...
最新文章
- NSInputStream和NSMutableURLRequest-实现保存文件到服务器
- OpenCV图像处理使用笔记(八)——Sobel算子
- oracle+测试权限,Oracle测试题
- Angular 2 JIT vs AOT
- 阿里云插件新版发布,多特性助力提升开发者体验
- NGINX 配置超时时间
- amazeui学习笔记--css(常用组件1)--小徽章Badge
- OpenResty 简单编写一个Module
- android中The connection to adb is down .. You must restart adb and Eclipse问题的解决
- python中字符串模块_Python字符串模块
- php实现des加密,如何在PHP项目中实现一个DES加密解密功能
- Unity小游戏教程系列 | 创建小型太空射击游戏(二)
- Groovy语法介绍
- 计算机哪些方向发展前景,计算机就业的几个方向
- iPhone照片的云端备份和本地移动硬盘备份 策略
- PostgreSQL+PostGIS的使用
- SAP云集成 SAP Integration Suite启用过程,踩坑记
- 云效平台代码管理使用总结
- 诙谐幽默的个性自我介绍
- 转载--期指迎来首个交割日
热门文章
- python的 局部变量与全局变量
- python xlrd 的merged_cells 里面四个参数的含义
- Android shape 画的圆角带四个黑变 问题
- Java之Spring mvc详解(非原创)
- Openfire XMPP Smack RTC IM 即时通讯 聊天 MD
- k64 datasheet学习笔记35---Analog-to-Digital Converter (ADC)
- 2021襄阳谷城高考成绩查询,2021高考襄阳谷城县考生求助电话
- 2022-2028年中国搪胶行业市场深度分析及投资前景分析报告
- SQL中返回一个字符串在另一个中存在的次数
- 判断交换机性能好坏的九个因素