学习目标
- 学习读取视频,显示视频和保存视频
- 学习从摄像头获取视频,并显示
- 要学习的函数: cv2.VideoCapture(), cv2.VideoWriter()
Capture Video from Camera
从摄像头中抓取视频流,OpenCV提供了非常简单的接口。现在学习从内置摄像头获取视频流,并逐帧显示。
为了抓取视频,首先需要创建 VideoCapture 对象。参数为设备索引(device index)或者视频文件名。设备索引是指向摄像头的数字编号,通常会连接到一个设备,传递参数 0 或者(-1)。如果传递 1,表示连接第二个摄像头。这样设置之后,可以逐帧获取视频流,最后不要忘了释放资源。
import numpy as np
import cv2
cap = cv2.VideoCapture(0) # 初始化对象 cap
while(True):
# Capture frame-by-frame
ret, frame = cap.read()
# Our operations on the frame come here
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# Display the resulting frame
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()
cap.read():返回布尔值(True/False)。如果成功读取到视频帧,返回True,所以可以检查返回值来确定视频是否结束。
cap.isOpened():判定初始化是否成功。当cap对象初始化失败,程序会报错。否则使用函数 cap.open() 打开。
cap.get(propld):获取视频的属性值,propld取值0-18。每个值代表该视频的一种属性,具体见下表。表格参考链接:https://blog.csdn.net/weixin_41010198/article/details/88535234
propld | 函数名 | 功能 |
---|---|---|
0 | cv.CAP_PROP_POS_MSEC | 以毫秒为单位获取视频现在的位置 |
1 | cv.CAP_PROP_POS_FRAMES | 基于0的索引将被解码/捕获下一帧 |
2 | cv.CAP_PROP_POS_AVI_RATIO | 视频文件的相对位置:0 - 视频的开始,1 - 视频的结束 |
3 | cv.CAP_PROP_FRAME_WIDTH | 帧的宽度 |
4 | cv.CAP_PROP_FRAME_HEIGHT | 帧的高度 |
5 | cv.CAP_PROP_FPS | 帧速 |
6 | cv.CAP_PROP_FOURCC | 4个字符表示的视频编码器格式 |
7 | cv.CAP_PROP_FRAME_COUNT | 帧数 |
8 | cv.CAP_PROP_FORMAT | byretrieve()返回的Mat对象的格式 |
9 | cv.CAP_PROP_MODE | 指示当前捕获模式的后端特定值 |
10 | cv.CAP_PROP_BRIGHTNESS | 图像的亮度(仅适用于相机) |
11 | cv.CAP_PROP_CONTRAST | 图像对比度(仅适用于相机) |
12 | cv.CAP_PROP_SATURATION | 图像的饱和度(仅适用于相机) |
13 | cv.CAP_PROP_HUE | 图像的色相(仅适用于相机) |
14 | cv.CAP_PROP_GAIN | 图像的增益(仅适用于相机) |
15 | cv.CAP_PROP_EXPOSURE | 曝光(仅适用于相机) |
16 | cv.CAP_PROP_CONVERT_RGB | 表示图像是否应转换为RGB的布尔标志 |
17 | cv.CAP_PROP_WHITE_BALANCE | 目前不支持 |
18 | cv.CAP_PROP_RECTIFICATION | 立体摄像机的整流标志 |
cap.set(propld,value):修改属性值。比如获取该帧的宽和高,cap.get(3),cap.get(4),返回640x480。但是如果修改为320x240,使用ret = cap.set(3, 320) 和 ret = cap.set(4, 240)。
Playing Video from file
与从摄像头获取视频的代码类似,仅仅需要将视频索引值改为视频文件名。如果要显示视频帧,需要使用合适的时间间隔,使用cv2.waitKey()。如果值太小,则视频播放很快,太大,播放很慢。通常设置为25毫秒。
import numpy as np
import cv2
cap = cv2.VideoCapture('../data/3.mp4')
while(cap.isOpened()):
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame',gray)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
注:保证ffmpeg和gstreamer的版本正确。
Saving a Video
可以逐帧读取视频,当然也可以逐帧保存视频。视频保存的基本步骤如下:
- 创建 VideoWriter 对象,指定保存视频名(output.avi);
- 指定视频流编码格式 FourCC;
- 指定帧率,帧大小,以及 isColor 标志,输出彩色或者灰度视频;
FourCC:四字符视频编码格式,与平台有关,具体如下:
函数:cv2.VideoWriter_fourcc(‘M’,‘J’,‘P’,‘G’) or cv2.VideoWriter_fourcc(*'MJPG) for MJPG。
- Fedora: DIVX, XVID, MJPG, X264, WMV1, WMV2. (XVID is more preferable. MJPG results in high size video. X264 gives very small size video);
- Windows:DIVX (More to be tested and added);
- OSX:(I don’t have access to OSX. Can some one fill this?);
使用实例:
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'XVID') # 测试发现*'XVID'在window下也可以成功保存视频
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
frame = cv2.flip(frame,0)
# write the flipped frame
out.write(frame)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
# Release everything if job is finished
cap.release()
out.release()
cv2.destroyAllWindows()