[CV2] 读取视频
[注:文章里的CV2均为小写]
OpenCV的VideoCapture类和VideoWriter类提供了视频处理功能,支持各种格式的视频文件。
读取并显示视频步骤:
将视频文件或者摄像头作为数据源来创建VideoCapture对象
调用VideoCapture对象的read()方法获取视频中的帧,每一帧都是一幅图像
调用VideoWriter对象的write()方法将帧写入视频文件,或者调用CV2.imshow()函数在窗口中显示帧(即播放视频)
播放视频的实质是逐帧读取和显示帧图像
仅能读取视频画面,无法获得视频声音
播放视频
import CV2 as cv # 导入库换名为cv
bga=cv.VideoCapture('star.mpg') # 创建对象,导入视频
fps=int(bga.get(cv.CAP_PROP_FPS)) # 读取视频的帧速率
# 读取视频的高和宽,看起来麻烦,不过是get()方法和参数罢了
size=(int(bga.get(cv.CAP_PROP_FRAME_HEIGHT)),int(bga.get(cv.CAP_PROP_FRAME_WIDTH)))
print('帧速率:',fps) # 帧速率: 30
print('大小:',size) # 大小: (512, 512)
success,frame=bga.read() # 读取第一帧作为开始
print(success) # True
print(type(frame)) # <class 'numpy.ndarray'>
while success: # 循环读视频帧,直到视频结束,用True代替会在播放完毕后报错
cv.imshow('BGA',frame) #在'BGA'窗口中显示帧图像
success,frame=bga.read() #读下一帧
key=cv.waitKey(fps) #设定了刷新率,决定了视频时长和速度 单位为毫秒
if key==27: #按【Esc】键结束播放
break
bga.release() #播放完毕自动关闭视频,点击X关掉的是一帧帧图像
fps和size都不能带小数点,所以需要int()转化为整数
经测试如果设定尺寸和原视频不一样,或大或小都无法播放
success是布尔类型,如果有读取到帧返回True,没读取到帧返回False
frame是的值是一个NumPy数组,也就是一帧的图像信息

[拖动窗口时播放会暂停,松开会从暂停处开始继续播放,直至最后一帧]
读取显示并写入视频
只需要在上面代码的基础上加上红色代码即可
import CV2 as cv
bga=cv.VideoCapture('star.mpg')
fps=int(bga.get(cv.CAP_PROP_FPS))
size=(int(bga.get(cv.CAP_PROP_FRAME_HEIGHT)),int(bga.get(cv.CAP_PROP_FRAME_WIDTH)))
success,frame=bga.read()
while success:
vw.write(frame) #将帧写入文件
cv.imshow('BGA',frame)
success,frame=bga.read()
key=cv.waitKey(fps)
if key==27:
break
bga.release()
提前按Esc终止播放写入的视频会截止到终止播放时刻
写入视频的帧率和设定的fps参数值有关,和播放帧率无关

常用的解码器格式:
XVID的MPEG-1编码格式,视频文件扩展名为.avi
cv.VideoWriter_fourcc('P','I','M','1')
Microsoft的MPEG-4编码格式,视频文件扩展名为.avi
cv.VideoWriter_fourcc('M','P','4','2')
XVID的MPEG-4编码格式,视频文件扩展名为.avi
cv.VideoWriter_fourcc('X','V','I','D')
XVID的MPEG-4编码格式,视频文件扩展名为.flv
cv.VideoWriter_fourcc('F','L','V','1')
总结:
读取并显示视频:
创建VideoCapture对象
???=cv.VideoCapture('XXX.xxx')
用VideoCapture对象read()方法获取视频中的帧
B,F=???.read()
调用cv.imshow()函数在窗口中显示帧图像
cv.imshow('窗口名',F)
读取并转存视频:
创建VideoWriter对象,参数都不能省略
???=cv.VideoWriter('XXX.xxx',cv.解码器格式,fps,size)
用VideoCapture对象read()方法获取视频中的帧
B,F=???.read()
用VideoWriter对象write()方法把读取到的帧写入文件
???.write(F)

本文章出现的视频源自BOFXVII比赛中的《Firmament Star》