【OpenCV】第十九章: 视频操作入门

这篇具有很好参考价值的文章主要介绍了【OpenCV】第十九章: 视频操作入门。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

第十九章: 视频操作入门

  • 一段视频是由很多张静态图片组成的,很多个静态图像组成一段视频。

  • 一个静态图像我们称为一帧,每一帧都是一张静止图像。帧可以以固定的时间间隔从视频中提取,然后对其使用图像处理的方法进行处理,就达到了处理视频的目的。

  • 帧数指每秒传输的静态画面的数量,也可以理解为图形处理器每秒刷新的次数,通常也称为帧率、刷新率,用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()函数

  • 函数cv2.VideoCapture.grab()用来指向下一帧,语法格式:ret = cv2.VideoCapture.grab(),如果该函数成功指向下一帧,则返回True。
  • 函数cv2.VideoCapture.retrieve()用来解码并返回cv2.VideoCapture.grab()捕获的视频帧。其语法格式是:ret, image = cv2.VideoCapture.retrieve(),
    如果解码失败,返回值ret=false,image为一个空图像, 否则,ret=true, image为解码成功的视频帧。

二、保存视频

上面的操作是读取视频文件或者打开摄像头读取实时视频流,那读出的视频如何保存?opencv中的cv2.VideoWriter类可以帮我们将图片序列保存成视频文件,也可以修改视频的各种属性,还可以对视频类型进行转换。文章来源地址https://www.toymoban.com/news/detail-777464.html

  • <VideoWriter object> = cv2.VideoWriter(filename, fourcc, fps, frameSize[, isColor])
    filename:指定输出目标视频的存放路径和文件名。如果指定的文件名已经存在,则会覆盖这个文件。
    fourcc:视频编/解码类型(格式)。这个参数用cv2.VideoWriter_fourcc()来指定视频编解码格式。通俗的说就是进行解包操作。
        cv2.VideoWriter_fourcc('I','4','2','0')表示未压缩的YUV颜色编码格式。生成的文件扩展名为.avi格式。
        cv2.VideoWriter_fourcc('P','I','M','I')表示MPEG-1编码类型。生成的文件扩展名为.avi格式。
        cv2.VideoWriter_fourcc(*'mp4v'),这种是简洁的写法,表示把mp4v格式的视频数据解包成'm'、'p'、'4'、'v',就是相当于把原来的视频数组分解成'm'、'p'、'4'、'v'
        其他更多的的参数自己上网查询。
        如果参数fourcc=-1,则呈现运行时会弹出一个对话框,在对话框中用户可以根据自己的需要选择合适的压缩程序和压缩质量。
    fps:帧速率。表示一秒钟保存20张图片。这个参数可以设置20,30都没问题。
    frameSize:每一帧的长和宽。也就是摄像头的分辨率。这个参数非常关键,如果写错就保存不成功。
    isColor:表示是否为彩色图像。
    #例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格式的。
    视频格式除了mp4格式外还有avi等格式,avi格式的文件比较大一些,早期的视频文件都是avi格式,后来才出现mp4技术,mp4技术的压缩比高一些,视频文件就比较小一些。
    如果是avi格式的视频,这里的参数fourcc=cv2.VideoWriter_fourcc(*'XVID')。如果fourcc是avi格式,参数filename就也得是avi格式,就是也要保存为avi格式。
    第4个参数,分辨率的设置,你可以先打开你的笔记本摄像头-设置-图片质量,可以看到你的摄像头是1280x720,但其实是640x480的。
    #例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()


     

到了这里,关于【OpenCV】第十九章: 视频操作入门的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 第十九章 Unity 其他 API

    本节介绍一些其他经常使用的Unity类。首先,我们回顾一下Vector3向量类,它既可以表示方向,也可以表示大小。它在游戏中可以用来表示角色的位置,物体的移动/旋转,设置两个游戏对象之间的距离。在我们之前的课程中,我们讲过向量的一些运算。例如向量的加法可以表示

    2024年02月05日
    浏览(42)
  • 第十九章:Linux中安装MySQL

    查看是否安装过 MySQL MySQL 卸载 关闭 ,ysql 服务 查询当前 mysql 安装状态 卸载上述命令【任意一条就行】查询出的已安装程序 注意:务必卸载干净,反复执行 rpm -qa | grep -i mysql 确认是否有卸载残留。 删除 mysql 相关文件 删除 my.cnf 【 MySQL 的配置文件】 检查 /tmp 临时目录权限

    2024年02月13日
    浏览(44)
  • 【Vue3 第十九章】插槽 slot

    数字化管理平台 Vue3+Vite+VueRouter+Pinia+Axios+ElementPlus 权限系统-商城 个人博客地址 在某些场景中,我们可能想要为子组件传递一些模板片段,让子组件在它们的组件中渲染这些片段。这就用到了插槽。 插槽是子组件中的提供给父组件使用的一个占位符,用 slot 表示,父组件可以

    2024年02月09日
    浏览(40)
  • OpenCV入门(十九)快速学会OpenCV 18 圆环检测

    作者:Xiou 霍夫变换除了用来检测直线外,也能用来检测其他几何对象。实际上,只要是能够用一个参数方程表示的对象,都适合用霍夫变换来检测。用霍夫圆变换来检测图像中的圆,与使用霍夫直线变换检测直线的原理类似。 在霍夫圆变换中,需要考虑圆半径和圆心(x坐标

    2024年02月16日
    浏览(50)
  • 第十九篇【传奇开心果系列】Python的OpenCV库技术点案例示例:文字识别与OCR

    OpenCV文字识别与OCR:用于识别图像中的文字内容,并进行光学字符识别。 OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库,提供了丰富的图像处理计算机视觉算法。虽然CV 本身并不包含专门的 OCR(Optical Character Recognition,光学字符识别)功能,但可以配合其他

    2024年02月20日
    浏览(55)
  • 【OpenCV学习笔记03】- 视频入门

    这是对于 OpenCV 官方文档的 GUI 功能的学习笔记。学习笔记中会记录官方给出的例子,也会给出自己根据官方的例子完成的更改代码,同样彩蛋的实现也会结合多个知识点一起实现一些小功能,来帮助我们对学会的知识点进行结合应用。 如果有喜欢我笔记的请麻烦帮我关注、

    2024年02月02日
    浏览(45)
  • TCP/IP网络编程 第十九章:Windows平台下线程的使用

    要想掌握Windows平台下的线程,应首先理解“内核对象”(Kernel Objects)的概念。如果仅介绍Windows平台下的线程使用技巧,则可以省略相对陌生的内核对象相关内容。但这并不能使各位深入理解Windows平台下的线程。 内核对象的定义 操作系统创建的资源有很多种,如进程、线程

    2024年02月16日
    浏览(54)
  • 【Linux命令行与Shell脚本编程】第十九章 正则表达式

    正则表达式基础 定义BRE模式 扩展正则表达式 在sed和gawk中创建正则表达式,以得到所需的数据。 正则表达式是一种可供Linux工具过滤文本的自定义模板,使用元字符来描述数据流中的一个或多个字符. Linux工具(比如sed或gawk)会在读取数据时使用正则表达式对数据进行模式匹配

    2024年02月13日
    浏览(57)
  • Hotspot源码解析-第十九章-ClassLoaderData、符号表、字符串表的初始化

    讲解本章先从一张图开始 众所周知,Java类的相关信息都是存储在元空间中的,但是是怎么存储的,相信很多读者是不清楚的,这里就不得不涉及到ClassLoaderDataGraph、classLoader、classLoaderData(简称CLD)和Klass的概念及他们四者的关系,这里简单描述下他们的概念,具体细节放到

    2024年01月17日
    浏览(47)
  • 第十九章 调用Callout Library函数 - 将 $ZF(-5) 与多个库和许多函数调用一起使用

    对 $ZF(-4,1) 的调用将标注库 inputlibrary.dll 和 outputlibrary.dll 加载到虚拟内存中,并为其返回系统定义的库 ID 。 对 $ZF(-4,3) 的调用使用库 ID 和函数名称来获取库函数的 ID 。返回的函数 ID 实际上是 ZFEntry 表序列号(请参阅上一章中的“创建 ZFEntry 表”)。 第一个循环使用 $ZF(-5

    2024年01月16日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包