现在找一个能拍摄视频的设备真是太容易了。结果大家都用视频来代替以前的序列图像。视频可能由两种形式得到,一个是像网络摄像头那样实时视频流,或者由其他设备产生的压缩编码后的视频文件。幸运的是,OpenCV可以使用相同的C++类、用同一种方式处理这些视频信息。在接下来的教程里你将学习如何使用摄像头或者视频文件。

  • 如何打开和读取视频流
  • 两种检查相似度的方法:PSNR和SSIM

如何读取一个视频流(摄像头或者视频文件)?

总的来说,视频捕获需要的所有函数都集成在 VideoCapture C++ 类里面。虽然它底层依赖另一个FFmpeg开源库,但是它已经被集成在OpenCV里所以你不需要额外地关注它的具体实现方法。你只需要知道一个视频由一系列图像构成,我们用一个专业点儿的词汇来称呼这些构成视频的图像:“帧”(frame)。此外在视频文件里还有个参数叫做“帧率”(frame rate)的,用来表示两帧之间的间隔时间,帧率的单位是(帧/秒)。这个参数只和视频的播放速度有关,对于单独的一帧图像来说没有任何用途。

你需要先定义一个 VideoCapture 类的对象来打开和读取视频流。具体可以通过 constructor 或者通过 open 函数来完成。如果使用整型数当参数的话,就可以将这个对象绑定到一个摄像机,将系统指派的ID号当作参数传入即可。例如你可以传入0来打开第一个摄像机,传入1打开第二个摄像机,以此类推。如果使用字符串当参数,就会打开一个由这个字符串(文件名)指定的视频文件。

结构体 CvCapture

CvCapture 是一个结构体,用来保存图像捕获所需要的信息。 opencv提供两种方式从外部捕获图像:

一种是从摄像头中,
一种是通过解码视频得到图像。
     两种方式都必须从第一帧开始一帧一帧的按顺序获取,因此每获取一帧后都要保存相应的状态和参数。
     比如从视频文件中获取,需要保存视频文件的文件名,相应的解码器类型,下一次如果要获取将需要解码哪一帧等。
 这些信息都保存在CvCapture结构中,每获取一帧后,这些信息都将被更新,获取下一帧需要将新信息传给获取的 api接口

cvCreateFileCapture(char*name)
通过输入要读取的avi文件的路径,然后,该函数返回一个指向 CvCapture结构体的指针。
cvQueryFrame(capture)
输入一个CvCapture 类型的指针,该函数主要功能是将视频文件的下一帧加载到内存。与 cvLoadImage的不同之处是,该函数不重新分配内存空间。
C=cvWaitKey(33)
当前帧被显示后,等待 33毫秒。如果用户触发了一个按键, c会被设置成这个按键的 ASCII码,否则会被设置成 -1。
cvWaitKey(33) 在此处的另外一个作用是,控制帧率。
cvReleaseCapture(&capture)
释放为 CvCapture结构体开辟的内存空间
关闭打开的 AVI文件相关的文件句柄
VideoCapture类
用于从视频文件或摄像机捕获视频.该类提供了用于从摄像机捕获视频或者读取视频文件的C++ API。 注意:在C API中使用黑盒子结构CvCapture来代替VideoCapture。 构造函数
VideoCapture::VideoCapture()
VideoCapture::VideoCapture(const string& filename)//filename – 文件名
VideoCapture::VideoCapture(int device)//device – 捕获视频的编号. 如果只有一个设备,默认编号为0
open函数
打开视频文件或捕获设备进行视频捕获
bool VideoCapture::open(const string& filename)//filename – 文件名
bool VideoCapture::open(int device)//device – 捕获视频的编号. 如果只有一个设备,默认编号为0
isopened函数
如果视频捕获已经初始化,则返回true。
bool VideoCapture::isOpened()
release函数
关闭视频文件或捕获设备
void VideoCapture::release()
grap函数
从视频文件或捕获设备中捕获下一帧
bool VideoCapture::grab()
retrieve函数
解码并返回抓取的视频帧
bool VideoCapture::retrieve(Mat& image, int channel=0)
read函数
抓取,解码并返回下一个视频帧
bool VideoCapture::read(Mat& image)
get函数
返回指定的VideoCapture属性
double VideoCapture::get(int propId)//propId - 属性标识符
CV_CAP_PROP_POS_MSEC - 视频文件的当前位置(以毫秒为单位)或视频捕获时间戳。
CV_CAP_PROP_POS_FRAMES - 下一个要解码/捕获的帧的基于0的索引。
CV_CAP_PROP_POS_AVI_RATIO - 视频文件的相对位置:0 - 电影的开始,1 - 电影的结束。
CV_CAP_PROP_FRAME_WIDTH - 视频流中帧的宽度。
CV_CAP_PROP_FRAME_HEIGHT - 视频流中帧的高度。
CV_CAP_PROP_FPS - 帧速率。
CV_CAP_PROP_FOURCC - 编解码器的4个字符代码。
CV_CAP_PROP_FRAME_COUNT - 视频文件中的帧数。
CV_CAP_PROP_FORMAT - retrieve()返回的Mat对象的格式。
CV_CAP_PROP_MODE - 指示当前捕获模式的后端特定值。
CV_CAP_PROP_BRIGHTNESS - 图像的亮度(仅适用于相机)。
CV_CAP_PROP_CONTRAST - 图像的对比度(仅适用于相机)。
CV_CAP_PROP_SATURATION - 图像的饱和度(仅适用于相机)。
CV_CAP_PROP_HUE - 图像的色调(仅适用于摄像机)。
CV_CAP_PROP_GAIN - 图像的增益(仅适用于摄像机)。
CV_CAP_PROP_EXPOSURE - 曝光(仅适用于相机)。
CV_CAP_PROP_CONVERT_RGB - 指示图像是否应转换为RGB的布尔标志。
CV_CAP_PROP_WHITE_BALANCE - 目前不支持
CV_CAP_PROP_RECTIFICATION - 立体相机的校正标志(注意:目前仅由DC1394 v 2.x后端支持)
set函数
设置VideoCapture中的属性。
bool VideoCapture::set(int propertyId, double value)//propId - 属性标识符,同get;value - 属性的值。

  

简单的读写视频程序
#include<opencv2/opencv.hpp>
using namespace cv; void main() {
VideoCapture cap;
cap.open("E:\\VS2015Opencv\\vs2015\\project\\video\\01.avi"); //打开视频,以上两句等价于VideoCapture cap("E://01.avi"); //cap.open("http://www.laganiere.name/bike.avi");//也可以直接从网页中获取图片,前提是网页有视频,以及网速够快
if (!cap.isOpened())//如果视频不能正常打开则返回
return ;
Mat frame;
while ()
{
cap >> frame;//等价于cap.read(frame);
if (frame.empty())//如果某帧为空则退出循环
break;
imshow("video", frame);
waitKey();//每帧延时20毫秒
}
cap.release();//释放资源
}

#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
using namespace std; void main() {
VideoCapture cap;
cap.open("E:\\VS2015Opencv\\vs2015\\project\\video\\01.avi"); if (!cap.isOpened())
return; int width = cap.get(CV_CAP_PROP_FRAME_WIDTH); //帧宽度
int height = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //帧高度
int frameRate = cap.get(CV_CAP_PROP_FPS); //帧率 x frames/s
int totalFrames = cap.get(CV_CAP_PROP_FRAME_COUNT); //总帧数 cout << "视频宽度=" << width << endl;
cout << "视频高度=" << height << endl;
cout << "视频总帧数=" << totalFrames << endl;
cout << "帧率=" << frameRate << endl; Mat frame;
while ()
{
cap >> frame;//等价于cap.read(frame);
if (frame.empty())
break;
imshow("video", frame);
if (waitKey() != )
break;
}
cap.release();
}

将左边的waitkey(33)改成右边的if(waitKey(20)>0)break;

程序会直接跳出,不放视频

opencv学习之等待按键事件-waitKey函数

waitkey(20) 如果不按键的时候是返回 oxff,这个无符号就是255,有符号就是-1

windows vs 的环境默认了这个为非符号数 即255,而opencv的新手书中,往往作者环境会认为是-1

解决方案:把原始代码中循环读取帧的

if (waitKey(33)>=0)break;

改为

if (waitKey(33) != 255)break;

或者把waitkey的返回值用有符号数去读取。

参考:opencv学习之路(2)、读取视频,读取摄像头

OpenCV的视频读取的更多相关文章

  1. 基于OpenCV之视频读取,处理和显示框架的搭建(一)

    主要包括以下内容: 1.使用的主要函数的说明. 2.两个实例:视频读取和显示.搭建视频读取和处理框架,调用canny函数提取边缘并显示. 3.一些注意事项和代码说明. 一.使用的主要函数 1.延时函数 ...

  2. OpenCV学习笔记(2)——如何用OpenCV处理视频

    如何用OpenCV处理视频 读取视频文件,显示视频,保存视频文件 从摄像头获取并显示视频 1.用摄像头捕获视频 为了获取视频,需要创建一个VideoCapature对象.其参数可以是设备的索引号,也可 ...

  3. python + opencv: 解决不能读取视频的问题

    博主一开始使用python2.7和Opencv2.4.10来获取摄像头图像,程序如下: cap = cv2.VideoCapture(0) ret, frame = cap.read() 使用这个程序 ...

  4. OpenCV视频读取播放,视频转换为图片

    转载请注明出处!!! http://blog.csdn.net/zhonghuan1992 OpenCV视频读取播放,视频转换为图片 介绍几个有关视频读取的函数: VideoCapture::Vide ...

  5. OpenCV计算机视觉学习(1)——图像基本操作(图像视频读取,ROI区域截取,常用cv函数解释)

    1,计算机眼中的图像 我们打开经典的 Lena图片,看看计算机是如何看待图片的: 我们点击图中的一个小格子,发现计算机会将其分为R,G,B三种通道.每个通道分别由一堆0~256之间的数字组成,那Ope ...

  6. 使用opencv显示视频的方法

    下面对使用opencv显示视频做一个简单的记录.当然,网上这方面的资料已经数不胜数了,我只是将其简单记录,总结一下. 在opencv中显示视频主要有: (1)从本地读取视频和调用摄像头读取视频 (2) ...

  7. 基于opencv将视频转化为字符串Java版

    基于opencv将视频转化为字符串Java版 opencv java  先上一个效果图吧 首先,弄清一下原理 我们要将视频转化为字符画,那么就需要获取画面的每一帧,也就是每一张图片,然后将图片进行转化 ...

  8. Atitit Java OpenCV 捕获视频

    Atitit Java  OpenCV 捕获视频 ,打开一段视频或默认的摄像头 有两种方法,一种是在定义类的时候,一种是用open()方法. 一. 读取视频序列 OpenCV提供了一个简便易用的框架以 ...

  9. OpenCV读写视频文件解析

    OpenCV读写视频文件解析 一.视频读写类 视频处理的是运动图像,而不是静止图像.视频资源可以是一个专用摄像机.网络摄像头.视频文件或图像文件序列. 在 OpenCV 中,VideoCapture ...

随机推荐

  1. Java设计模式(一)UML总结

    定义 统一建模语言(英语: Unified Modeling Language ,缩写UML)是非专利的第三代建模和规约语言. UML特点 UML是一种开放的方法 用于说明.可视化.构建和编写一个正在 ...

  2. Python分布式进程报错:pickle模块不能序列化lambda函数

    今天在学习到廖老师Python教程的分布式进程时,遇到了一个错误:_pickle.PicklingError: Can't pickle <function <lambda> at ...

  3. CentOS 7 部署 Redis(单机版)

    一.部署环境说明 软件 版本 安装包 CentOS 7.2 CentOS 7.2 Redis 4.0.14 redis-4.0.14.tar.gz 二.开始部署 安装gcc依赖 [root@bmsof ...

  4. html5的页面在IOS中,按钮 变成圆角怎么办?

      在button的css 中添加: -webkit-appearance: none;     border: none;     border-radius: 0; ok 的啦   文章来源:刘俊 ...

  5. C# ASCII码的转换、转义字符、对照表

    var splitStr = new byte[] { 0x05, 0x0D, 0x0A };//var splitStr = new byte[] { 5, 13, 10 };这样写也可以 var ...

  6. UVA122 二叉树的层次遍历

    题目链接 https://vjudge.net/problem/UVA-122 #include<bits/stdc++.h> using namespace std; #define l ...

  7. Mybatis的解析和运行原理

    Mybatis的解析和运行原理 Mybatis的运行过程大致分为两大步:第一步,读取配置文件缓存到Configuration对象,用以创建 SqlSessionFactory:第二步,SqlSessi ...

  8. D - Three Integers

    https://codeforces.com/contest/1311/problem/D 本题题意:给出a,b,c三个数,a<=b<=c: 可以对三个数中任意一个进行+1或-1的操作: ...

  9. H3C链路聚合

    以太网链路聚合通过将多条以太网物理链路捆绑在一起形成一条以太网逻辑链路,实现增加链路带宽的目的,同时这些捆绑在一起的链路通过相互动态备份,可以有效地提高链路的可靠性. 一.基本概念 1.聚合接口/聚合 ...

  10. 最近公共祖先 Lowest Common Ancestors

    基于深度的LCA算法:  对于两个结点u.v,它们的深度分别为depth(u).depth(v),对于其公共祖先w,深度为depth(w),u需要向上回溯depth(u)-depth(w)步,v需要d ...