视频数据的读取
虽然视频文件是由多张图片组成的,但是imread()函数并不能直接读取视频文件,需要由专门的视频读取函数进行视频读取,并将每一帧图像保存到Mat类矩阵中,下面的代码中给出了VideoCapture类在读取视频文件时的构造方式。
cv :: VideoCapture :: VideoCapture(); //默认构造函数
cv :: VideoCapture :: VideoCapture(const String& filename,int apiPreference =CAP_ANY)
- filename:读取的视频文件或者图像序列名称
- apiPreference:读取数据时设置的属性,例如编码格式、是否调用OpenNI等,详细参数及含义在表2-5给出。
该函数是构造一个能够读取与处理视频文件的视频流,在代码清单2-27中的第一行是VideoCapture类的默认构造函数,只是声明了一个能够读取视频数据的类,具体读取什么视频文件,需要在使用时通过open()函数指出,例如cap.open(“1.avi”)是VideoCapture类变量cap读取1.avi视频文件。
第二种构造函数在给出声明变量的同时也将视频数据赋值给变量。可以读取的文件种类包括视频文件(例如video.avi)、图像序列或者视频流的URL。其中读取图像序列需要将多个图像的名称统一为“前缀+数字”的形式,通过“前缀+%02d”的形式调用,例如在某个文件夹中有图片img_00.jpg、img_01.jpg、img_02.jpg……加载时文件名用img_%02d.jpg表示。函数中的读取视频设置属性标签默认的是自动搜索合适的标志,所以在平时使用中,可以将其缺省,只需要输入视频名称即可。与imread()函数一样,构造函数同样有可能读取文件失败,因此需要通过isOpened()函数进行判断,如果读取成功则返回值为true,如果读取失败,则返回值为false。
通过构造函数只是将视频文件加载到了VideoCapture类变量中,当我们需要使用视频中的图像时,还需要将图像由VideoCapture类变量里导出到Mat类变量里,用于后期数据处理,该操作可以通过“>>”运算符将图像按照视频顺序由VideoCapture类变量复制给Mat类变量。当VideoCapture类变量中所有的图像都赋值给Mat类变量后,再次赋值的时候Mat类变量会变为空矩阵,因此可以通过empty()判断VideoCapture类变量中是否所有图像都已经读取完毕。
VideoCapture类变量同时提供了可以查看视频属性的get()函数,通过输入指定的标志来获取视频属性,例如视频的像素尺寸、帧数、帧率等,常用标志和含义在表2-5中给出。
#include<iostream>
//#include <stdio.h>
#include <opencv2/opencv.hpp>
#include "opencv/highgui.h"
using namespace std;
using namespace cv;
int main(int argc,char** argv) {
cout<<"OpenCv Version: "<<CV_VERSION<<endl;
VideoCapture video("/home/wyh/Documents/C++demo/project_video.mp4");
if(video.isOpened()){
cout<<"视频中图像的宽度 = "<<video.get(CAP_PROP_FRAME_WIDTH)<<endl;
cout<<"视频中图像的高度 = "<<video.get(CAP_PROP_FRAME_HEIGHT)<<endl;
cout<<"视频帧率 = "<<video.get(CAP_PROP_FPS)<<endl;
cout<<"视频的总帧数 = "<<video.get(CAP_PROP_FRAME_COUNT)<<endl;
}
else{
cout<<"请确认视频文件名称是否正确"<<endl;
return -1;
}
while(1){
Mat frame;
video>>frame;
if(frame.empty()){
break;;
}
imshow("video",frame);
waitKey(1000/video.get(CAP_PROP_FPS));
}
waitKey();
return 0;
}
摄像头的直接调用
VideoCapture类还可以调用摄像头,构造方式如代码清单2-29中所示。
cv :: VideoCapture :: VideoCapture(int index,int apiPreference = CAP_ANY)
调用摄像头与读取视频文件相比,只有第一个参数不同。调用摄像头时,第一个参数为要打开的摄像头设备的ID,ID的命名方式从0开始。从摄像头中读取图像数据的方式与从视频中读取图像数据的方式相同,通过“>>”符号读取当前时刻相机拍摄到的图像。并且读取视频时VideoCapture类具有的属性同样可以使用。