opencv 实践入门2 - 如何利用 VideoCapture
2019-10-17 本文已影响0人
发哥的档案室
我只是一名搬砖工,无意侵犯各位大佬知识产权。
最近因项目组需要,开始学图像处理
所以记录一下这个过程以及经验,希望能帮到大家
学习参考资料:
- 《图像处理的数学修养》
- github 上的OpenCV-Python-Tutorial
若想系统地学习,麻烦移步到 github或买书啃一下
这部分主要讲两个函数
- cv2.VideoCapture 创建视频对象,负责获取视频内容
- cv2.VideoWriter() 创建视频写入对象,用来录制/保存视频
其他
- cv2.cvtColor() 将 BGR 彩色图片转为 灰度图片
- imwrite() 保存图片
- cv2.VideoCapture().isOpened() 检测视频读取状态是否正常
- cv2.VideoCapture().read() 获取视频某一帧,返回两个值,第一个是布尔值,表示“这一帧”是否获取正确;第二个值是这一帧的内容,是一个矩阵。
接下来看例子
cv2.VideoCapture()
- 如果传的参数是数字,表示使用摄像头。如 cv2.VideoCapture(0),表示使用计算机第一个摄像头。
- 如果传的是一个视频的地址,则表示读取本地视频。这里我只用第二种,给一个视频的绝对路径并读取它
比如:我希望读取一个视频,截取每一帧图像并将其转为灰度图像,并播放
import cv2
capture = cv2.VideoCapture('/Users/0.mp4') ##假设我有个视频放在(/Users/ 目录下,我是 mac 玩家,win 玩家自行修改)
while(capture.isOpened()): ## 检测视频打开是否有问题
ret,frame = capture.read() ## 逐帧读取视频
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) ## 灰度转换
cv2.imshow('frame', gray) ## (播放)看图
if cv2.waitKey(30) == ord('q'): ## 控制退出,选中窗口按'q' (大写不行)
break
capture.release() ## 清内存,好习惯
cv2.destroyAllWindows() ## 后面这两句不写,看图的窗口就关不了
cv2.waitKey(1)
### 为了上面好看点,我把注释写在下面了
### capture.isOpened()返回的是布尔值,如果成功读取这一帧,则为 True; 反之为 False
### ret 其实就是capture.isOpened(), 而 frame 这是获取的这一帧图像的内容,是矩阵格式
### cv2.cvtColor() 将 BGR 彩色图片转为 灰度图片
### cv2.imshow() 第一个参数是打开播放图像窗口的名字,自己随便命名;第二个参数是要看的图像名称,就是 gray
### cv2.waitKey(),它的参数表示暂停时间,所以这个值越大,视频播放速度越慢,反之,播放速度越快,通常设置为25或30。 ord 是转码,因为 opencv 内核是 C++,用的是 ASCⅡ (我不知道这里说的对不对)
如果我想截取某个时间点的图片。
- 首先我们得知道,视频中的每一帧对应多少时间,
- 通过使用的函数capture.get(propId),可以获取视频(/摄像头的一些属性),如 分辨率、亮度、对比度等,我们想知道的帧速度也在这里
- 传入的参数是数字或关键词都可以。propId是从0~18的数字,代表不同的属性,完整的属性列表可以参考: VideoCaptureProperties 。
- 如果想修改视频的属性,可以用 capture.set(propId,value)来修改属性值
github 大佬的经验之谈:某些摄像头设定分辨率等参数时会无效,因为它 有固定的分辨率大小支持,一般可在摄像头的资料页中找到。
import cv2
capture = cv2.VideoCapture('/Users/0.mp4')
timepoint = 10 ###(单位:秒) 想截取视频中 10s 那一帧
timer = 0 ### 用来计算帧数,
fps = round(capture.get(5)) ### 1 秒有多少帧, 使用的参数是5,表示帧速 (要用怎么自己查表)
### 一般来说,1 秒 约等于 24 帧,我这个视频是 23.976023976023978, 所以直接用round(), 四舍五入,将其约等于 24.
while(capture.isOpened()): ## 检测视频打开是否有问题
timer += 1 ## 开始计算过去了多少帧
ret,frame = capture.read() ## 逐帧读取视频
if timer == timepoint * fps: ## 10秒的时候,开始截图
cv2.imwrite('/Users/10s.jpg',frame) ## 存图,第一个参数递质,第二个要存的图是哪个
break ## 退出
capture.release() ## 清内存,好习惯
如果我看视频看到某一帧想截图 (这个更简答了是不是,和第一个很像)
我们来个暗号,比如 按下键盘 ‘s’ 就截图
import cv2
capture = cv2.VideoCapture('/Users/0.mp4')
while(capture.isOpened()): ## 检测视频打开是否有问题
ret,frame = capture.read() ## 逐帧读取视频
gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) ## 灰度转换
cv2.imshow('frame', gray) ## (播放)看图
if cv2.waitKey(30) == ord('s'): ## 控制退出,选中窗口按'q' (大写不行)
cv2.imwrite('/Users/10s.jpg',frame) ### 其实就多了这个
break
capture.release() ## 清内存,好习惯
cv2.destroyAllWindows() ## 后面这两句不写,看图的窗口就关不了
cv2.waitKey(1)
如果我觉得截图不过瘾,想截一段动画(gif) 或 截一段视频
这次要加上存视频的函数 cv2.VideoWriter()
思路还是一样,假设我们想截 第 5 秒到第 10 秒的视频
cv2.VideoWriter()
先说说这个函数,它需要四个参数
cv2.VideoWriter(filename, fourcc, fps, resolution)
- 第一个参数 是文件名,如‘output.avi’ (绝对路径,你保存文件的位置)
- 第二个参数 是编码方式,这里选的是 FourCC码 (我也没搞懂,反正先用着吧)
- 第三个参数是帧率 FPS (又叫帧速),一般和原视频一样,24,有兴趣的可以试试更大或更小的数字,发现新世界
- 第四个是分辨率 (每英寸像素Pixel per inch, ppi)
- 480P: 720×480 (宽 × 高
- 720p: 1280×720
- 1080p: 1920×1080
- 可以试试原画是 480P 转 1080P 输出会变什么样子 (查原视频分辨率用 .get(3) 宽,.get(4) 高
还有一个FourCC是用来指定视频编码方式的四字节码,所有的编码可参考 Video Codecs 。如MJPG编码可以这样写: cv2.VideoWriter_fourcc(*’MJPG’)或cv2.VideoWriter_fourcc(‘M’,’J’,’P’,’G’)
(这个我也不懂,先用着吧)
那开始干吧
import cv2
capture = cv2.VideoCapture('/Users/test.mp4')
time1 = 5 ###(单位:秒) 截取开始时间 第5秒
time2 = 10 ###(单位:秒) 截取结束时间 第10秒
timer = 0 ### 用来计算帧数,
fps = round(capture.get(5)) ### 获取 1 秒有多少帧
### 定义编码方式并创建VideoWriter对象
fourcc = cv2.VideoWriter_fourcc(*'MJPG')
outfile = cv2.VideoWriter('/Users/test_5s.avi',fourcc, 24, (640, 360)) ###我这边测试视频 帧频是24,分辨率是640×360, 可以分别用.get(5), .get(3)和.get(4)获取, 当然你也可以改动一下试试看什么效果
while(capture.isOpened()): ## 检测视频打开是否有问题
timer += 1 ## 开始计算过去了多少帧
ret,frame = capture.read() ## 逐帧读取视频
if time1 * fps >= timer: ## 小于 5 秒时,跳过 (为什么要? 因为没有这个会直接跳到 else,break 就结束了)
pass
elif time1 * fps < timer and timer < time2 * fps: ## 大于 5 秒,小于 10 秒时,开始截视频
outfile.write(frame) ## outfile 就是创建VideoWriter对象
else: ## 大于 10 秒的时候,停止
print('finished')
break ## 退出
capture.release() ## 清内存,好习惯
OK 啦,是不是很简单,快来试试吧
最后说说改变一些参数的结果
- 帧速,这个顾名思义,帧速越大,视频播放的速度越快,比如原本1秒是24帧,如果你改成240帧,相当于你1秒的时间播放了原本10秒时间的内容,将帧速改小同理。
- 分辨率, 别想了,只要改动分辨率,就会保存失败(空白文件),这也很容易懂,不可能让你那么容易就提高视频的清晰度嘛,(降低也不行 doge)