【基础】VideoCapture类
cv2.VideoCapture类的常用函数包括初始化、打开、帧捕获、释放、属性设置等,下面对这些函数进行简单的介绍。
1). 初始化
OpenCV为cv2.VideoCapture类提供了构造函数cv2.VideoCapture(),用于打开摄像头并完成摄像头的初始化工作。该函数的语法格式为:
捕获对象 = cv2.VideoCapture('摄像头ID号')
● “摄像头ID号”就是摄像头的ID号码。需要注意的是,这个参数是摄像设备(摄像头)的ID编号,而不是文件名。其默认值为-1,表示随机选取一个摄像头;如果有多个摄像头,则用数字“0”表示第1个摄像头,用数字“1”表示第2个摄像头,以此类推。所以,如果只有一个摄像头,既可以使用“0”,也可以使用“-1”作为摄像头ID号。
● “捕获对象”为返回值,是cv2.VideoCapture类的对象。
例如,要初始化当前的摄像头,可以使用语句:
cap = cv2.VideoCapture(0)
在使用函数cv2.VideoCapture()时,要记得:视频处理完以后,释放摄像头对象。
该构造函数也可以用于初始化视频文件,初始化视频文件时,参数为文件名。此时函数的形式为:
捕获对象 = cv2.VideoCapture('视频文件名')
例如,打开当前目录下文件名为“test.mp4”的视频文件,可以使用语句:
cap = cv2.VideoCapture('test.mp4')
2).cv2.VideoCapture.open()函数和cv2.VideoCapture.isOpened()函数
一般情况下,使用cv2.VideoCapture()函数即可完成摄像头的初始化。有时,为了防止初始化发生错误,可以使用函数cv2.VideoCapture.isOpened()来检查初始化是否成功。该函数的语法格式为:
retval = cv2.VideoCapture.isOpened()
该函数会判断当前的摄像头是否初始化成功:
● 如果成功,则返回值retval为True。
● 如果不成功,则返回值retval为False。
如果摄像头初始化失败,可以使用函数cv2.VideoCapture.open()打开摄像头。该函数的语法格式为:
retval = cv2.VideoCapture.open(index)
●index为摄像头ID号。
● retval为返回值,当摄像头(或者视频文件)被成功打开时,返回值为True。
同样,函数cv2.VideoCapture.isOpened()和函数cv2.VideoCapture.open()也能用于处理视频文件。在处理视频文件时,函数cv2.VideoCapture.open()的参数为文件名,其语法格式为:
retval = cv2.VideoCapture.open(filename)
3). 捕获帧
摄像头初始化成功后,就可以从摄像头中捕获帧信息了。捕获帧所使用的是函数cv2.VideoCapture.read()。该函数的语法是:
retval, image = cv2.VideoCapture.read()
● image是返回的捕获到的帧,如果没有帧被捕获,则该值为空。
● retval表示捕获是否成功,如果成功则该值为True,不成功则为False。
4). 释放
在不需要摄像头时,要关闭摄像头。关闭摄像头使用的是函数cv2.VideoCapture.release()。该函数的语法是:
cv2.VideoCapture.release()
例如,当前有一个VideoCapture类的对象cap,要将其释放,可以使用语句:
cap.release()
5). 属性设置
有时,我们需要获取cv2.VideoCapture类对象的属性,或是更改该类对象的属性。函数cv2.VideoCapture.get()用于获取cv2.VideoCapture类对象的属性,该函数的语法格式是:
retval = cv2.VideoCapture.get(propId)
式中,参数propId对应着cv2.VideoCapture类对象的属性。例如,有一个cv2.VideoCapture类对象cvc,则:
● 通过cvc.get(cv2.CAP_PROP_FRAME_WIDTH),就能获取当前帧对象的宽度。
● 通过cvc.get(cv2.CAP_PROP_FRAME_HEIGHT),就能获取当前帧对象的高度。
函数cv2.VideoCapture.set()用来设置cv2.VideoCapture类对象的属性。该函数的语法是:
retval = cv2.VideoCapture.set(propId, value)
式中,propId对应cv2.VideoCapture类对象的属性,value对应属性propId的值。
例如,有一个cv2.VideoCapture类对象cvc,则:
● 语句ret=cvc.set(cv2.CAP_PROP_FRAME_WIDTH, 640)将当前帧对象的宽度设置为640像素。
● 语句ret=cvc.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)将当前帧对象的高度设置为480像素。cv2.VideoCapture类对象的属性值及含义如下表所示:

6). cv2.VideoCapture.grab()函数和cv2.VideoCapture.retrieve()函数
一般情况下,如果需要读取一个摄像头的视频数据,最简便的方法就是使用函数cv2.VideoCapture.read()。但是,如果需要同步一组或一个多头(multihead)摄像头(例如立体摄像头或Kinect)的视频数据时,该函数就无法胜任了。可以把函数cv2.VideoCapture.read()理解为是由函数cv2.VideoCapture.grab()和函数cv2.VideoCapture.retrieve()组成的。函数cv2.VideoCapture.grab()用来指向下一帧,函数cv2.VideoCapture.retrieve()用来解码并返回一帧。因此,可以使用函数cv2.VideoCapture.grab()和函数cv2.VideoCapture.retrieve()获取多个摄像头的数据。
函数cv2.VideoCapture.grab()用来指向下一帧,其语法格式是:
retval = cv2.VideoCapture.grab()
如果该函数成功指向下一帧,则返回值retval为True。
函数cv2.VideoCapture.retrieve()用来解码,并返回函数cv2.VideoCapture.grab()捕获的视频帧。该函数的语法格式为:
retval, image = cv2.VideoCapture.retrieve()
● image为返回的视频帧,如果未成功,则返回一个空图像。
● retval为布尔型值,若未成功,返回False;否则,返回True。
对于一组摄像头,可以使用如下代码捕获不同摄像头的视频帧:
success0 = cameraCapture0.grab()
success1 = cameraCapture1.grab()
if success0 and success1:
frame0 = cameraCapture0.retrieve()
frame1 = cameraCapture1.retrieve()
与VideoCapture类内的其他函数一样,cv2.VideoCapture.grab()和cv2.VideoCapture.retrieve()也能用来读取视频文件。
捕获摄像头视频
OpenCV通过cv2.VideoCapture类提供了非常方便的捕获摄像头视频的方法。可以使用如下代码捕获摄像头的视频流。
import cv2
cap = cv2.VideoCapture(0)
while cap.isOpened():
ret, frame = cap.read()
cv2.imshow('frame', frame)
if cv2.waitKey(1) == 27: # ESC键
break
cap.release()
cv2.destroyAllWindows()
请自行测试。
播放视频文件
播放视频文件时,需要将函数cv2.VideoCapture()的参数值设置为视频文件的名称。在播放视频时,可以通过设置函数cv2.waitKey()中的参数值,来设置播放视频时每一帧的持续(停留)时间。
如果函数cv2.waitKey()中的参数值:
● 较小,则说明每一帧停留的时间较短,视频播放速度会较快。
● 较大,则说明每一帧停留的时间较长,视频播放速度会较慢。
该参数的单位是ms,通常情况下,将这个参数的值设置为25即可。
程序演示:使用cv2.VideoCapture类播放视频文件,并尝试更改cv2.waitKey()参数值查看效果。
import cv2
cap = cv2.VideoCapture('video.mp4')
t = 25 # ms
while cap.isOpened():
ret, frame = cap.read()
cv2.imshow('frame', frame)
if cv2.waitKey(t) == 27: # ESC键
break
cap.release()
cv2.destroyAllWindows()