基于OpenCV的视频流处理方法 您所在的位置:网站首页 opencv无法打开视频 基于OpenCV的视频流处理方法

基于OpenCV的视频流处理方法

2024-04-18 08:34| 来源: 网络整理| 查看: 265

分享人工智能技术干货,专注深度学习与计算机视觉领域!

又到了我们的OpenCV实战系列了,熟悉OpenCV的朋友会觉得这部分很简单,可以直接跳过,但是对于不熟悉OpenCV的朋友我觉得还是有必要了解一下,因为OpenCV是搞计算机视觉必须要掌握的基础,本篇文章,我们将一起了解基于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 cv2 def 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对视频文件和摄像头画面的读写操作了,比较系统全面,掌握了这些内容,以后处理视频数据就会如鱼得水了!



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有