基于OpenCV的视频流处理方法

OpenCV提供了VideoCapture类和VideoWriter类来支持各种格式的视频流,支持的格式类型会因系统的不同而有所变化,但基本上都是支持avi格式的,且对于视频文件和摄像头画面的读写所用到的接口基本上都相同,因此,我们把它们放在一起来讲了。

1. 获取VideoCapture类实例

不管是读取视频文件还是捕获摄像头画面,都使用到了VideoCapture类,但不同的是传入的形参不一样,如果我们传给VideoCapture类的是一个视频文件路径那么将是读取来自视频文件的画面,而如果我们传给VideoCapture类的是摄像头编号那么将是读取来自摄像头的画面,其使用示例如下:

# 获取VideoCapture类实例,读取视频文件
fcap = cv2.VideoCapture('demo.mp4')
# 读取摄像头画面
ccap = cv2.VideoCapture(0)

对于摄像头编号,可以使用如下命令获取:

ls -al /dev/ | grep video

对于输出信息以video开头的其数字后缀即为可能的摄像头编号,如果一台电脑有多个摄像头设备,那么将会出现从0开始的多个摄像头编号。

2. 判断获取VideoCapture实例是否成功

如果传入无效的视频文件或摄像头编号,那么VideoCapture类将会在后续的read()接口返回(False,None),为了避免此类事件发生,可以通过VideoCapture类的isOpened()接口进行判断,该接口返回一个boolean值,正常获取实例返回True,否则返回False,其使用示例如下:

# 判断是否正确获取VideoCapture类实例
while fcap.isOpened():# next step operation

3. 获取视频流信息

一般视频流主要的帧信息包含画面宽高还有帧率,对于视频文件,则会多出整个视频流多少帧,因此,我们一般主要关注这四个视频流信息即可,而我们用到的则是VideoCapture类的get接口,其使用示例如下:

# 获取视频帧的宽
w = fcap.get(cv2.CAP_PROP_FRAME_WIDTH)
# 获取视频帧的高
h = fcap.get(cv2.CAP_PROP_FRAME_HEIGHT)
# 获取视频帧的帧率
fps = fcap.get(cv2.CAP_PROP_FPS)

获取到的帧率对于摄像头设备来说,如果所使用的终端不支持查询,那么将会返回0值,且该值也不是非常精确的。

# 获取视频流的总帧数
fcount = fcap.get(cv2.CAP_PROP_FRAME_COUNT)

注意这个是对视频文件才有意义,对于摄像头是没意义的,且以上获取到的返回信息均是浮点型的,注意转换为整型。

4. 获取帧画面

这个就相对简单,直接使用VideoCapture类的read接口即可,该接口会返回两个参数,第一个参数是读取成功与否标志位,成功为True否则为False,第二个参数则为具体的帧数据,其是一个numpy.ndarray的数组,其使用示例如下:

# 获取帧画面
success, frame = fcap.read()

但在读取过程中,有可能会存在失败的情况出现,一般我们是在第二次读取时放入一个while循环来保障整个读取顺利进行,如下:

# 判断读取视频流是否成功
while success:success, frame = fcap.read()# do something in here

5. 针对一组或多头摄像头特殊处理

当需要同步一组摄像头或一个多头(multihead)摄像头(例如立体摄像头或Kinect)时,read()方法就不太适用了,这时,一般使用grab()和retrieve()方法代替它。对于一组摄像头,其使用示例如下:

# 一组摄像头的特殊处理
success0 = fcap0.grab()
success1 = fcap1.grab()
if success0 and success1:frame0 = fcap0.retrieve()frame1 = fcap1.retrieve()

6. 跳到视频流某一帧

对于视频文件,有时候我们需要直接跳到某一个感兴趣的帧并从该帧开始读取数据,那么可以使用VideoCapture类的set接口,其使用示例如下:

# 跳到某一感兴趣帧并从此帧开始读取,如从第360帧开始读取
fcap.set(cv2.CAP_PROP_POS_FRAMES, 360)
success, frame = fcap.read()

7. 设置摄像头分辨率

opencv读取到的摄像头画面大小一般为默认的640x480,但这并不一定满足我们的日常使用要求,比如摄像头支持超高清画面,那么我们就希望能捕获到超高清1920x1080的画面,好在VideoCapture类的set接口为我们提供了相应的功能,其使用示例如下:

# 设置摄像头分辨率的高
fcap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
# 设置摄像头分辨率的宽
fcap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)

8. 获取VideoWriter类实例

不管是对视频文件的再存储还是对摄像头画面的保存,都是用到了VideoWriter类,且传入的形参意义是一致的,都需要我们传入保存的文件名包含视频格式、指定视频编解码器、保存视频的帧率以及保存视频的分辨率,一般来说,保存视频的帧率最好与读入的画面的帧率一致,但需要我们进行估计或使用计时器才会比较准确,而分辨率则可以更改,只是要求写入的帧其大小要与分辨率保持一致,其使用示例如下:

writer = cv2.VideoWriter('output.avi', cv2.VideoWriter_fourcc('X', 'V', 'I', 'D'), 30, (1080, 1920))

值得注意的是,我们必须要为VideoWriter类的构造函数传入所需的参数,且若指定的文件名已存在则会被直接覆盖。

9. VideoWriter类支持的视频编解码器

在构造VideoWriter类实例时,我们必须要指定视频编解码器,那么VideoWriter类都支持哪些视频编解码器呢?我们通过cv2.VideoWriter_fourcc来指定具体使用的编解码器:

'I','4','2','0':该选项是一个未压缩的YUV颜色编码,兼容性好,但产生文件较大,文件扩展名为.avi
'P','T','M','I':该选项是MPEG-1编码类型,文件扩展名为.avi
'X','V','T','D':该选项是MPEG-4编码类型,得到的视频大小处于平均值,文件扩展名为.avi
'T','H','E','O':该选项是Ogg Vorbis,文件扩展名为.ogv
'F','L','V','1':该选项是一个flash视频,文件扩展名为.flv

一般常用的是cv2.VideoWriter_fourcc('X','V','T','D'),mp4编码文件相对小一些,或cv2.VideoWriter_fourcc('I','4','2','0'),文件相对大一些,但为了缩小文件空间我们可能还需要用到ffmpeg工具进一步压缩文件。

10. 保存帧数据

这个也很简单,直接使用VideoWriter类的write接口即可,该接口一次可以保存一帧数据到制定文件中,其使用示例如下:

# 保存帧数据
writer.write(frame)

11. 释放资源

不管是VideoCapture类还是VideoWriter类,当我们使用完了它们之后,都应该将它们释放掉,避免资源一直被占用,而这两个类都有提供了release()接口给我们,我们只需直接调用即可释放资源,使用示例如下:

# 释放VideoCapture资源
fcap.release()
# 释放VideoWriter资源
writer.release()

12. 一个完整的示例代码

# -*- coding: utf-8 -*-
# /usr/bin/env/python3'''use opencv3 to capture video frame, show and save its stream.'''import cv2def stream_processing():# 获取VideoCapture类实例,读取视频文件fcap = cv2.VideoCapture('demo.mp4')# 设置摄像头分辨率的高fcap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)# 设置摄像头分辨率的宽fcap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)# 跳到某一感兴趣帧并从此帧开始读取,如从第360帧开始读取fcap.set(cv2.CAP_PROP_POS_FRAMES, 360)# 获取视频帧的宽w = fcap.get(cv2.CAP_PROP_FRAME_WIDTH)# 获取视频帧的高h = fcap.get(cv2.CAP_PROP_FRAME_HEIGHT)# 获取视频帧的帧率fps = fcap.get(cv2.CAP_PROP_FPS)# 获取视频流的总帧数fcount = fcap.get(cv2.CAP_PROP_FRAME_COUNT)# 获取VideoWriter类实例writer = cv2.VideoWriter('output.avi', cv2.VideoWriter_fourcc('X', 'V', 'I', 'D'), int(fps), (int(w), int(h)))# 判断是否正确获取VideoCapture类实例while fcap.isOpened():# 获取帧画面success, frame = fcap.read()while success:cv2.imshow("demo", frame)  ## 显示画面# 获取帧画面success,frame = fcap.read()# 保存帧数据writer.write(frame)if (cv2.waitKey(20) & 0xff) == ord('q'):  ## 等待20ms并判断是按“q”退出,相当于帧率是50hz,注意waitKey只能传入整数,break# 释放VideoCapture资源fcap.release()# 释放VideoWriter资源writer.release()cv2.destroyAllWindows()  ## 销毁所有opencv显示窗口if __name__ == "__main__":stream_processing()

好了,以上就是opencv对视频文件和摄像头画面的读写操作了,比较系统全面,掌握了这些内容,以后处理视频数据就会如鱼得水了!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/240860.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数运算·字符串相加·阶乘

大数,就是C/C中利用基本类型所不能存储的数字,少则数十位,大则几万位,如何存储和计算大数就是本文的内容。 在C和C中,没有存储大数的数据结构,就算 unsigned long long也只能表示19位的数字  如果我们用d…

PHP案例代码:PHP如何提供下载功能?

对Web开发人员来说,“下载”功能是一个非常常见的需求。在网站中提供文件下载,通常用于提供用户手册、软件升级、音乐、视频等各种资源文件。本教程将向您介绍如何实现一个PHP下载功能,同时告诉浏览器文件名称、文件大小、文件类型,并统计下载次数。 首先,我们需要了解一些…

排序算法——希尔排序

实际上是对插入排序的优化。在插入排序的基础上,引入步长的概念,将元素分为几个组,在组内进行插入排序,在各组内进行插入排序后,再逐渐缩短步长进而继续进行插入排序,直到步长为1停止排序,此时全…

免费PHP完美运营的最新短视频打赏系统学习版

免费PHP完美运营的最新短视频打赏系统学习版 一、介绍 免费PHP完美运营的最新短视频打赏系统学习版,是一款基于PHP开发的打赏系统,具有强大的功能和稳定的性能。相比于市面上的其他打赏系统,它更加完善,几乎无bug,能…

剑指offer题解合集——Week1day7

文章目录 剑指offerWeek1周日:旋转数组的最小数字AC代码思路:部分模拟 周日:矩阵中的路径AC代码思路: 剑指offerWeek1 周日:旋转数组的最小数字 题目链接:旋转数组的最小数字 把一个数组最开始的若干个…

openGauss学习笔记-171 openGauss 数据库运维-备份与恢复-导入数据-深层复制

文章目录 openGauss学习笔记-171 openGauss 数据库运维-备份与恢复-导入数据-深层复制171.1 使用CREATE TABLE执行深层复制171.1.1 操作步骤 171.2 使用CREATE TABLE LIKE执行深层复制171.2.1 操作步骤 171.3 通过创建临时表并截断原始表来执行深层复制171.3.1 操作步骤 openGa…

MATLAB ga函数的使用方法

一、ga句法结构 x ga(fitnessfcn,nvars) x ga(fitnessfcn,nvars,A,b) x ga(fitnessfcn,nvars,A,b,Aeq,beq) x ga(fitnessfcn,nvars,A,b,Aeq,beg,IB,UB) x ga(fitnessfcn,nvars,A,b,Aeq,beq,LB,UB,nonlcon) x ga(fitnessfcn,nvars,A,b,Aeq,beq,LB,UB,nonlcon,options) x …

vue的表单收集案例

Vue的表单收集案例 这只是最基础的表单收集&#xff0c;并未涉及到element-ui。 <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>收集表单数据</title><script type"text/javascript" src"../js…

LabVIEW的六轴工业机器人运动控制系统

LabVIEW开发六轴工业机器人运动控制系统 本项目开发了一个高效的工业机器人控制系统&#xff0c;重点关注于运动学算法和轨迹规划算法的实现和测试。LabVIEW作为一个关键技术&#xff0c;在项目中扮演了核心角色。 系统研究与算法开发&#xff1a;首先&#xff0c;项目围绕机…

IOS开发问题记录

1. xcode上传app store connect后testflight没有可构建版本的原因 查看你的邮箱, 里面有原因提示 一般为使用了某些权限, 但是plist没有声明 2. xcode 修改display name后名字并没有改变 原因是并没有修改到plist的CFBundleDisplayName的字段 将CFBundleDisplayName的值修改…

大IP时代文旅品牌如何用数字人玩转数字营销?

在大IP时代&#xff0c;有IP意味着话题、人气、流量以及变现能力&#xff0c;文旅品牌如何打造一个成功的、受欢迎的IP&#xff0c;拓宽文旅资源价值&#xff0c;成为文旅品牌营销的一大痛点。随着元宇宙概念兴起&#xff0c;数字人IP可以满足文旅品牌多元化需求&#xff0c;文…

React学习计划-React16--React基础(二)组件与组件的3大核心属性state、props、ref和事件处理

1. 组件 函数式组件&#xff08;适用于【简单组件】的定义&#xff09; 示例&#xff1a; 执行了ReactDOM.render(<MyComponent/>, ...)之后执行了什么&#xff1f; React解析组件标签&#xff0c;找到了MyComponent组件发现组件是使用函数定义的&#xff0c;随后调用该…

ARM 点灯

.text .global _start _start: led1设置GPIOE时钟使能 RCC_MP_AHB4ENSETR[4]->1 0X50000A28LDR R0,0X50000A28 指定寄存器地址LDR R1,[R0] 将寄存器数值取出来放在R1中ORR R1,R1,#(0x1<<4) 将第4位设置为1STR R1,[R0] 将修改后的值写回去设置PE10为输出 GPIOE…

Python 爬虫之下载视频(三)

批量下载某B主视频 文章目录 批量下载某B主视频前言一、基本思路二、确定遍历循环结构三、基本思路中第12步三、基本思路中第345步总结 前言 上一篇讲了如何去获取标题和视频链接。这篇就跟大家讲一下如何去下载这些视频。本篇会以标题和 视频链接 为突破口&#xff0c;来寻找…

GrayLog日志平台的基本使用-docker容器日志接入

1、/etc/docker/daemon.json中加入如下配置并重启服务 [rootlocalhost src]# cat /etc/docker/daemon.json { "registry-mirrors": ["https://dhq9bx4f.mirror.aliyuncs.com"], "log-driver": "gelf", "log-opts":…

验证时间段区间是否有交叉/重叠

点赞再看&#xff0c;养成习惯&#xff0c;大家好&#xff0c;我是辰兮&#xff01;今天介绍如何验证时间段区间是否有交叉/重叠 文章目录&#xff1a; 前言 一、引入库 二、使用步骤 总结 前言 在日常开发过程中&#xff0c;经常会有导入需要校验时间段区间是否有交叉/重叠&a…

CSS中页面的布局案例-利用浮动

&#xff08;接期末课程设计题目&#xff0c;支持定制&#xff09; 利用浮动完成页面布局 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title><style type"text/css">/*清除默认样式*/*{marg…

JavaScript 对象和 JSON 字符串的区别

JavaScript 对象和 JSON 字符串是两种不同的数据表示形式&#xff0c;它们有以下区别&#xff1a; 语法格式&#xff1a;JavaScript 对象是 JavaScript 语言中的一种数据类型&#xff0c;使用花括号 {} 包裹&#xff0c;属性和值之间使用冒号 : 分隔&#xff0c;并且使用逗号 …

在Jetpack Compose中使用ExoPlayer实现直播流和音频均衡器

在Jetpack Compose中使用ExoPlayer实现直播流和音频均衡器 背景 ExoPlayer与Media3的能力结合&#xff0c;为Android应用程序播放多媒体内容提供了强大的解决方案。在本教程中&#xff0c;我们将介绍如何设置带有Media3的ExoPlayer来支持使用M3U8 URL进行直播流。此外&#x…

PortSwigger Business Logic Vulnerabilities

lab1: Excessive trust in client-side controls 给了100块 买价值1337的货 在历史包里发现 尝试直接修改价格 lab2: High-level logic vulnerability 这里把加入购物车时价格可控的点修复了 但是数量可控 我们可以买负数的东西来加钱 但是返回Cart total price cannot be …