opencv-python 视频处理
视频是由图片组成的,视频的每一帧就是一幅图片,一般是30帧,表示一秒钟显示30张图片。
opencv中可以用 VideoCapture 来捕获摄像头,用数字表示不同的设备,比如0,1。如果是视频文件,直接指定路径即可。
VideoCapture 类提供了初始化,打开视频文件或设备,视频帧捕获,视频文件或设备关闭,属性设置或获取等功能。
其成员函数isOpened用来检查视频是否能成功打开。
其成员函数get用于获取视频的一些参数或属性,比如帧率(cv2.CAP_PROP_FPS),视频的宽(cv2.CAP_PROP_FRAME_WIDTH),视频的高(cv2.CAP_PROP_FRAME_HEIGHT),视频的总帧数(cv2.CAP_PROP_FRAME_COUNT)。
其成员函数read用于捕获,解码并返回下一帧的视频图像。
1 视频读取
首先用video = cv2.VideoCapture('test.mp4') 来捕获视频类,然后用video.isOpened() 判断是否打开成功,如果打开成功,用video.read() 来循环读取每一帧图片,然后依次显示图片,waitKey可以控制帧率。
import cv2 #打开/显示视频 video = cv2.VideoCapture('D:/05.OpenCV图像处理课程资料/第2-7章notebook课件/图像操作/test.mp4') #参数改成0可以直接打开设备的摄像头 if video.isOpened(): print('视频打开成功') while True: ret,frame = video.read() # ret 视频捕获成功的标志,没有视频帧时返回false;frame 返回视频帧图像 if ret == False: #只要视频帧还没结束就继续读取 break else: cv2.imshow('frame',frame) #显示视频帧 if cv2.waitKey(10) == ord('q'): #按q结束视频播放 break else: print('视频打开失败') video.release() #释放设备资源然后关闭显示窗口 cv2.destroyAllWindows()
如果要打开摄像头并显示图像的话,直接把代码中的捕获视频类改成 device = cv2.VideoCapture(0) 即可。
2 获取视频某些帧保存为图片
1)获取视频前两帧的图片
import cv2 video = cv2.VideoCapture('D:/05.OpenCV图像处理课程资料/第2-7章notebook课件/图像操作/test.mp4') #初始化视频类 if video.isOpened(): #video视频对象的成员函数,判断视频是否成功打开,返回bool类型 print('视频打开成功') fps = video.get(cv2.CAP_PROP_FPS) #获取视频的帧率 fcount = video.get(cv2.CAP_PROP_FRAME_COUNT) #获取视频的总帧数 width = video.get(cv2.CAP_PROP_FRAME_WIDTH) #获取视频的宽 height = video.get(cv2.CAP_PROP_FRAME_HEIGHT) #获取视频的高 print('fps:',fps,'fcount:',fcount,'width:',width,'height:',height) i=0 while True: if i==2: break #获取视频的前两帧 else: i=i+1 ret,frame = video.read() #读取视频 cv2.imshow('frame'+str(i),frame) #显示视频帧 cv2.waitKey(0) else: print('视频打开失败') cv2.destroyAllWindows()
2)截取视频的前n帧图像,保存到文件夹中
import cv2 #截取视频的前n帧图像,保存到文件夹中 frameNum=20 #需要截取的视频帧数 video = cv2.VideoCapture('D:/05.OpenCV图像处理课程资料/第2-7章notebook课件/图像操作/test.mp4') #初始化视频类 if video.isOpened(): #video视频对象的成员函数,判断视频是否成功打开,返回bool类型 print('视频打开成功') i=0 while True: if i==frameNum: break #获取视频的前两帧 else: i=i+1 ret,frame = video.read() #读取视频 # cv2.imshow('frame'+str(i),frame) #显示视频帧 cv2.imwrite('C:/Users/86188/Desktop/opencv/images/'+str(i)+'.png',frame) cv2.waitKey(0) else: print('视频打开失败') cv2.destroyAllWindows()
3)将视频分割为单帧图片并保存到指定文件夹,方法一(视频结束就停止读取保存图片,最终的图片数量时是609)
import cv2 video = cv2.VideoCapture('D:/05.OpenCV图像处理课程资料/第2-7章notebook课件/图像操作/test.mp4') #初始化视频类 if video.isOpened(): #video视频对象的成员函数,判断视频是否成功打开,返回bool类型 print('视频打开成功') i=0 while True: ret,frame = video.read() #读取视频 if ret==False: break #只要视频帧还没结束就继续读取 else: i=i+1 cv2.imwrite('C:/Users/86188/Desktop/opencv/images1/'+str(i)+'.png',frame) cv2.waitKey(0) print('i:',i) else: print('视频打开失败') cv2.destroyAllWindows()
4)将视频分割为单帧图片并保存到指定文件夹,方法二(先计算视频帧总数,将所有视频帧读取保存,最终的图片数量时是622,609之后的图像是空的)
import cv2 video = cv2.VideoCapture('D:/05.OpenCV图像处理课程资料/第2-7章notebook课件/图像操作/test.mp4') #初始化视频类 fcount = video.get(cv2.CAP_PROP_FRAME_COUNT) #获取视频的总帧数 if video.isOpened(): #video视频对象的成员函数,判断视频是否成功打开,返回bool类型 print('视频打开成功') i=0 while True: ret,frame = video.read() #读取视频 if i==fcount: break #只要视频帧还没结束就继续读取 else: i=i+1 cv2.imwrite('C:/Users/86188/Desktop/opencv/images2/'+str(i)+'.png',frame) cv2.waitKey(0) print('i:',i) else: print('视频打开失败') cv2.destroyAllWindows()
3 视频保存
opencv中提供了用于视频保存的类VideoWriter,该类可以将图像文件写入到视频文件中。
VideoWriter第一个参数filename表示目标存储的文件名或路径;第二个参数是fourcc,该参数由cv2.VideoWriter_fourcc返回。
VideoWriter_fourcc(c1, c2, c3, c4) -> retval
c1, c2, c3, c4 表示4字符 编码,表示视频编码格式,常用的有:
‘I’,‘4’,‘2’,‘0’ 或 *'I420':未压缩的YUV颜色编码,4:2:0色度子采样,兼容性好,但文件较大,文件扩展名.avi。
‘P’,‘I’,‘M’,‘1’ 或 *‘PIM1‘:MPEG-1编码类型,文件扩展名.avi。随机访问,灵活的帧率、可变的图像尺寸。
‘X’,‘V’,‘I’,‘D’ 或 *'XVID':MPEG-4编码类型,视频大小为平均值,MPEG4所需要的空间是MPEG1的1/10,它对运动物体可以保证有良好的清晰度,间/时间/画质具有可调性。文件扩展名.avi。
‘M’,‘P’,‘4’,‘V’ 或 *'MP4V':MPEG-4编码,这种编码器常用于存储和传输视频文件,例如MP4格式。
1)保存相机采集的视频
import cv2 device = cv2.VideoCapture(0) #用相机设备初始化视频捕获类 fourcc = cv2.VideoWriter_fourcc('I','4','2','0') #创建视频编解码器 fps = device.get(cv2.CAP_PROP_FPS) #没法直接获取摄像头的fps,只能逐步遍历每一帧并将当前帧数除以当前时间获得fps print(fps) width = device.get(cv2.CAP_PROP_FRAME_WIDTH) height = device.get(cv2.CAP_PROP_FRAME_HEIGHT) size = (int(width),int(height)) video = cv2.VideoWriter('./video_capture.avi',fourcc,25,size) #创建视频写入对象,这里直接用fps会报错,返回的fps为0 if video.isOpened(): if device.isOpened(): print('摄像头打开成功') while True: ret,frame = device.read() video.write(frame) cv2.imshow('device_frame',frame) if cv2.waitKey(1) == ord('q'): break device.release() cv2.destroyAllWindows() else: print('摄像头打开失败') else: print('视频保存失败') print(fps)
通过VideoWriter创建视频写入对象,然后循环中用write把每一帧图像保存到文件对象中。摄像头采集的视频保存到当前文件夹下,文件名为 video_capture,文件格式为avi类型。
可以自定义视频的尺寸,也可以保存为mp4格式:
import cv2 device = cv2.VideoCapture(0) fourcc = cv2.VideoWriter_fourcc(*'mp4v') #mp4格式的编码 video = cv2.VideoWriter('./output.mp4',fourcc,20,(640,480)) if device.isOpened(): print('success') while True: ret,frame = device.read() if ret == False: break else: video.write(frame) cv2.imshow('frame',frame) if cv2.waitKey(1) == ord('q'): break else: print('failed') device.release() video.release() cv2.destroyAllWindows()
2)用图片文件创建视频
方法一:知道图片路径和图片名,图片名命名规范(如1.png,2.png),可以直接根据图片文件名称依次读入到视频文件中。
import cv2 #将images2文件夹下的图像合并为视频,方法一 path = './images2/' fourcc = cv2.VideoWriter_fourcc('I','4','2','0') ##创建视频编解码器 fps = 2 #视频帧,每秒钟2帧图像 size = (960,544) #设置带转换图像的尺寸 video = cv2.VideoWriter('./images2/img2video.avi',fourcc,fps,size) #创建视频写入对象 if video.isOpened(): for item in range(622): #遍历图像并将其写入视频文件 item = str(item+1) item = path + item + '.png' #图片路径 img = cv2.imread(item) #把图片读取出来 video.write(img) #写入到视频对象中 print(item) video.release() print('sucess') else: print('video failed')
方法二:用listdir返回文件中的所有图片(注意:返回的list列表是按照二进制进行排序,所以对于其他字符来说可能是乱序的)。然后用sort函数对图片进行排序,最后根据图片文件名称依次读入到视频文件中。
import os #文件操作库 将images1文件夹下的图像合并为视频,方法二 import cv2 path = './images1/' filelist = os.listdir(path) #返回一个list列表,列表包含path中的所有文件,按照二进制进行排序,所以对于其他字符来说可能是乱序的 # filelist.remove('img2video.avi') #删除filelist中的avi视频,否则下面切片分割的时候,img2video没法转换成int会报错 filelist.sort(key=lambda x:int(x.split('.')[0])) #sort是排序函数,参数key可以自定义排序的标准,lambda是匿名函数,split()是分割函数,[0]取第一个切片 # filelist.sort(key=lambda x:int(x[:-4]) # x[:-4] 取倒数第四个之前的字符 print(filelist) fourcc = cv2.VideoWriter_fourcc('I','4','2','0') #创建视频编解码器 fps = 25 #视频帧,每秒钟25帧图像 size = (960,544) #设置带转换图像的尺寸 video = cv2.VideoWriter('./images1/img2video.avi',fourcc,fps,size) #创建视频写入对象 if video.isOpened(): for item in filelist: #遍历图像并将其写入视频文件 if item.endswith('.png'): #将后缀为png的图像写入视频 item = path + item img = cv2.imread(item) video.write(img) video.release() #释放资源 print('sucess') else: print('video failed')