opencv 实践入门2 - 如何利用 VideoCapture截取视频中的图像

我只是一名搬砖工,无意侵犯各位大佬知识产权。
最近因项目组需要,开始学图像处理
所以记录一下这个过程以及经验,希望能帮到大家

学习参考资料:

  1. 《图像处理的数学修养》
  2. github 上的OpenCV-Python-Tutorial

若想系统地学习,麻烦移步到 github或买书啃一下


这部分主要讲两个函数

  1. cv2.VideoCapture 创建视频对象,负责获取视频内容
  2. cv2.VideoWriter() 创建视频写入对象,用来录制/保存视频

其他

  • cv2.cvtColor() 将 BGR 彩色图片转为 灰度图片
  • imwrite() 保存图片
  • cv2.VideoCapture().isOpened() 检测视频读取状态是否正常
  • cv2.VideoCapture().read() 获取视频某一帧,返回两个值,第一个是布尔值,表示“这一帧”是否获取正确;第二个值是这一帧的内容,是一个矩阵。

接下来看例子

cv2.VideoCapture()

  1. 如果传的参数是数字,表示使用摄像头。如 cv2.VideoCapture(0),表示使用计算机第一个摄像头。
  2. 如果传的是一个视频的地址,则表示读取本地视频。这里我只用第二种,给一个视频的绝对路径并读取它

比如:我希望读取一个视频,截取每一帧图像并将其转为灰度图像,并播放

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Ⅱ (我不知道这里说的对不对)

如果我想截取某个时间点的图片。
  1. 首先我们得知道,视频中的每一帧对应多少时间
    • 通过使用的函数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. 帧速,这个顾名思义,帧速越大,视频播放的速度越快,比如原本1秒是24帧,如果你改成240帧,相当于你1秒的时间播放了原本10秒时间的内容,将帧速改小同理。
  2. 分辨率, 别想了,只要改动分辨率,就会保存失败(空白文件),这也很容易懂,不可能让你那么容易就提高视频的清晰度嘛,(降低也不行 doge)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容