赞
踩
一段视频是由很多张静态图片组成的,很多个静态图像组成一段视频。
一个静态图像我们称为一帧,每一帧都是一张静止图像。帧可以以固定的时间间隔从视频中提取,然后对其使用图像处理的方法进行处理,就达到了处理视频的目的。
帧数指每秒传输的静态画面的数量,也可以理解为图形处理器每秒刷新的次数,通常也称为帧率、刷新率,用fps(Frames Per Second)表示。
人类视觉系统每秒可处理10到12个图像并单独感知它们,当很多帧连续快速显示时,人类就会形成运动错觉。所以,帧数越高画面就越流畅,可以产生更平滑和更逼真的动画。当前我们的视频一般是24帧、30帧,就是一秒显示24张或者30张图片。如果玩游戏我们一般都追求4k60帧,就是一秒钟显示60张图片。
opencv提供了cv2.VideoCapture类和cv2.VideoWriter类来处理各种类型的视频文件
注意这两个API是类不是函数,所以名字的写法和函数不一样,全部单词的首字母都用大写,不仅是C、C++,几乎所有的语言写类的时候,类名的首字母都要大写。
一、读取视频
1、从摄像设备中实时读取视频流 cv=cv2.VideoCapture(0)
假如我们要捕获电脑摄像头视频,这个函数可以帮我们打开摄像头并完成摄像头的初始化工作。
函数参数用数字来表示不同的摄像设备(摄像头)的ID编号。默认值是-1,表示随机选择一个摄像头。如果你电脑上有多个摄像头,比如电脑自带一个,你又插了一个USB的摄像头,那么你电脑就会自动给USB的摄像头一个ID编号,如果0表示的是第一个电脑内置的摄像头,1就表示USB的摄像头,如果有多个就以此类推。如果只有一个摄像头就可以用0也可以用-1作为这个摄像头的ID号。
2、直接读取磁盘上已有视频文件 cv=cv2.VideoCapture('文件路径')
- #例19.1 从笔记本摄像头里读取视频
- import cv2
- #创建显示窗口
- cv2.namedWindow('my video', cv2.WINDOW_NORMAL) #可以更改窗口大小的
- cv2.resizeWindow('my video', 240, 280) #设置一个小窗口
-
- cap = cv2.VideoCapture(0) #打开摄像头并初始化,我笔记本就自带一个摄像头,所以参数填0
-
- #循环读取摄像头的每一帧
- while True: #C
- ret, frame = cap.read() #对象cap有一个.read()方法 A
- if not ret: #我们可以根据ret做一个判断,if not ret就是没读到数据,就是if true
- break #没读到数据就直接退出
- cv2.imshow('my video', frame) #如果读到数据就在窗口显示数据
- #设置退出
- key = cv2.waitKey(10) #这里参数不能填0,因为B
- if key == ord('q'):
- break
- cap.release() #释放资源,释放摄像头对象
- cv2.destroyAllWindows()
这个程序就是读取摄像头数据,可以自动打开你的摄像头设备,并读取视频数据,这个功能在物联网设备里用的很多,非常实用,现在很多摄像头都自带一些机器视觉的功能,比如拍到人就自动的把人脸框出来,这些功能都是通过opencv来做的。还有比如无人车、机械臂等如果安装了摄像头,我们都可以通过一行代码cap = cv2.VideoCapture()直接就打开它了。
A:这个方法可以帮我们读取一帧数据就返回一个标记和这帧数据本身(就是一幅图像数据),当这个标记是True就是读到了一帧数据,False就表示没读到数据
B:如果填0,while True第一轮循环,如果读了一帧数据,就会一直只显示这一帧数据,一直等键盘响应,键盘不响应就一直卡在这行代码上,这不是我们想要的结果。如果我们把参数设置为1,就是等待1毫秒就往下执行,这样视频就播放的非常快,如果我们设置为1000就是等待1秒再显示下一帧图片,这样视频就非常不流畅,所以我们这里取10这么一个间隔。一般情况下这个参数设置25即可。
C:这里也可以写成:while cap.isOpened():如果摄像头打开失败,cap.isOpened()就返回False, whiel false,就直接不循环了,直接跳过这个循环代码块直接执行cap.release()和cv2.destroyAllWindows()。所以如果读不出数据,窗口就闪退了。
- #例19.2 读取磁盘上已有的视频文件
- import cv2
- cv = cv2.VideoCapture(r'C:\Users\25584\Desktop\VID_20190106_114412.mp4') #直接打开已有视频文件
-
- while True:
- ret, frame = cv.read()
- if not ret:
- break
- cv2.imshow('my baby', frame)
-
- key = cv2.waitKey(1000//30) #设置不同的参数,视频播放的速度不一样 A
- if key == ord('q'):
- break
-
- cv2.destroyAllWindows()
A:假如我的视频是一秒钟30帧,那么我想正常速度展示这个视频,这个参数应该怎样设置呢,waitKey()里的参数只能设置为整数,所以要一秒显示30帧,就要设置为1000//30,表示整除,向下取整。
3、cv2.VideoCapture类小结
构造函数cv2.VideoCapture()是用来打开摄像头并完成摄像头的初始化工作。或者是用来初始化视频文件的。
函数的语法格式:捕获对象 = cv2.VidelCapture('摄像头ID编号') 或者是:捕获对象 = cv2.VidelCapture('文件路径')
cv2.VideoCapture.isOpened()函数
如果我们不知道初始化是否成功,我们可以使用cv2.VideoCapture.isOpened()函数来判断初始化是否成功。
语法格式:ret = cv2.VideoCapture.isOpened(),如果成功,返回值ret为True,反之为false。
cv2.VideoCapture.open()函数
如果初始化失败,我们还可以使用cv2.VideoCapture.open()函数去打开摄像头或者视频文件。
语法格式:ret = cv2.VideoCapture.open(index or filename),如果能成功打开,返回值ret为True。
摄像头成功打开后就可以从摄像头中捕获帧信息了,用函数cv2.VideoCapture.read()
语法格式:ret, image = cv2.VideoCapture.read(),如果捕获成功,ret为true,image为捕获的图像帧,如果捕获不成功,ret为False,image为空。
释放资源cv2.VideoCapture.release()函数
不需要摄像头时要关闭摄像头。
获取类对象属性
假设一个类对象cv = cv2.VideoCapture()
cv.get(cv2.CAP_PROP_FRAME_WIDTH) #就能获取当前帧对象的宽度,参数的默认值是3
cv.get(cv2.CAP_PROP_FRAME_HEIGHT) #就能获取当前帧对象的高度,参数的默认值是4
语法格式:cv2.VideoCapture.get(propID),参数propID对应着上面类对象cv的属性,当propID=cv2.CAP_PROP_FRAME_WIDTH,或者直接写cv2.VideoCapture.get(3),就可以获得帧的宽度。cv2.VideoCapture.get(4)就可以获得帧的高度。propID可以从0取到40,就是有41种属性,以后用到什么属性去百度查找即可。
设置类对象属性cv2.VideoCapture.set(propID,value)
ret = cv.set(cv2.CAP_PROP_FRAME_WIDTH, 640) #将当前帧对象的宽度设置为640个像素
ret = cv.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) #将当前帧对象的高度设置为480个像素
4、cv2.VideoCapture.grab()函数和cv2.VideoCapture.retrieve()函数
如果只需要读取一个摄像头的视频数据,用函数cv2.VideoCapture.read()就可以了。但是如果要同步一组或一个多头摄像头(multihead,比如立体摄像头或Kinect)的视频数据时,就不能用cv2.VideoCapture.read()了,就需要用cv2.VideoCapture.grab()函数和cv2.VideoCapture.retrieve()函数
二、保存视频
上面的操作是读取视频文件或者打开摄像头读取实时视频流,那读出的视频如何保存?opencv中的cv2.VideoWriter类可以帮我们将图片序列保存成视频文件,也可以修改视频的各种属性,还可以对视频类型进行转换。
- #例19.3 使用cv2.VideoWriter类保存摄像头视频文件
- import cv2
- cap = cv2.VideoCapture(0) #打开摄像头
- vw = cv2.VideoWriter(r'C:\Users\25584\Desktop\myvideo.mp4', cv2.VideoWriter_fourcc(*'mp4v'), 60, (640,480)) #实例化一个读取并保存视频的类 A
-
- while cap.isOpened(): #用循环去接受摄像头的每一帧
- ret, frame = cap.read() #读取每一帧
- if not ret: #如果没接受到就直接退出
- print('can not get the video, exit...')
- break
- vw.write(frame) #写入每一帧视频数据,但是要注意这里没有写到磁盘,入缓存里面去了
- cv2.imshow('my video', frame) #写的每一帧数据先展示一下
- if cv2.waitKey(1) == ord('q'):
- break
- cap.release()
- vw.release() #把缓存里面的数据写入磁盘,释放缓存。
- cv2.destroyAllWindows()
A:参数fourcc用的解码是mp4v,那么第一个参数filename就也要用.mp4格式的。- #例19.4 提取视频的Canny边缘检测结果
- import cv2
- cap = cv2.VideoCapture(r'C:\Users\25584\Desktop\myvideo.mp4')
- while True:
- ret, frame = cap.read()
- if not ret:
- break
- frame = cv2.Canny(frame, 100, 200)
- cv2.imshow('canny', frame)
- key = cv2.waitKey(25)
- if key == 27 : #ESC键
- break
- cap.release()
- vw.release()
- cv2.destroyAllWindows()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。