上篇我们说到HIGHGUI的一些基本应用,本文主要讲HIGHGUI对视频读取与写入的处理.由于opencv现在大部分已经由c++改写,我主要介绍c++下的一些函数
VideoCapture类
VideoCapture从视频文件或摄像机中扑捉视频信息,提供c++API借口。先来简单的熟悉下吧。
#include "opencv2/opencv.hpp"
using namespace cv;
int main(int, char**)
{
VideoCapture cap(0); // open the default camera
//VideoCapture cap("g:\\1.avi");
if(!cap.isOpened()) // check if we succeeded
return -1;
Mat edges;
namedWindow("edges",1);
for(;;)
{
Mat frame;
cap >> frame; // get a new frame from camera
cvtColor(frame, edges, CV_BGR2GRAY);
GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);
Canny(edges, edges, 0, 30, 3);
imshow("edges", edges);
if(waitKey(30) >= 0) break;
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
1 VideoCapture::VideoCapture (VideoCapture 构造函数 )
VideoCapture::VideoCapture()
VideoCapture::VideoCapture(const string & filename)
VideoCapture::VideoCapture(int device)
参数解释:
filename: 要打开的视频文件或者图像序列(比如:img_%02d.jpg,img_%03d.jpg.....)
device : 捕捉视频设备的ID号,如果只有一个相机时,输入0
2 VideoCapture::open
打开视频文件或者视频设备(比如摄像机)
bool VideoCapture::open(const string & filename)
bool VideoCapture::open(int device)
参数含义见上面
3 VideoCapture::isOpened
如果捕捉视频成功即返回true
bool VideoCapture::isOpened()
4 VideoCapture::release
关闭视频文件和关闭视频设备
void VideoCapture::release()
该方法会自动被VideoCapture::open()和构造函数调用
5 VideoCapture:;grab
获视频文件或视频设备的下一帧,如果成功就返回true。该函数将视频文件复制到了一个用户看不到的空间,获取的视频并没有经过处理。这样做的目的是为了快速将视频读入内存。
bool VideoCapture::grab()
6 VideoCapture::retrieve
解码工作并返回grab()读入的帧,实际上就是从内存中独处视频的帧图像。如果没有frame被grab(),返回false
bool VideoCapture::retrieve(Mat &image,int channel=0)
7 VideoCapture::read
捕获,解码,返回下一帧,是grab(),retrieve()的功能和。如果没有帧被获取,返回false
VideoCapture & VideoCapture::operator >> (Mat &image)
bool VideoCapture::read(Mat &image)
8 VideoCapture::get
返回特定的视频属性,如果没有支持的属性,返回0
double VideoCapture::get(int propId)
参数propId可以有以下属性
propId属性
CV_CAP_PROP_POS_MSEC | 值为0,指向视频的当前位置,以毫秒为单位 |
CV_CAP_PROP_POS_FRAMES | 值为1,以帧为单位的当前位置 |
CV_CAP_PROP_POS_AVI_RATIO | 值为2,视频文件的相对位置:0代表视频开始,1代表视频结束 |
CV_CAP_PROP_FRAME_WIDTH | 值为3,当前读取帧的宽度 |
CV_CAP_PROP_FRAME_HEIGHT | 值为4,当前读取帧的高度 |
CV_CAP_PROP_FPS | 值为5,记录了视频录入时每秒的帧数,实际上就是帧率 |
CV_CAP_PROP_FOURCC | 值为6,由四个字节组成,表示视频文件的压缩方法 |
CV_CAP_PROP_FRAME_COUNT | 视频文件的总帧数 |
|
当然,还有一些其他的属性,这里就不都写了,不过表格里的属性是经常用到的。
8 VideoCapture::set
设置视频属性
bool VideoCapture::set(int propId,double value)
参数解释:propId:见上面表格,
value :对应属性的值
好的,VideoCapture类基本介绍完了,下面开始介绍VideoWriter类。
VideoWriter 写入视频类
1 VideoWriter::VidoeWriter 类构造函数
VideoWriter::VideoWriter()
VideoWriter::VideoWriter(const string &filename,int fourcc,double fps,Size farmeSize,bool isColor=true)
参数解释:
finename: 输出的文件名
fourcc : 四个字节的视频文件压缩方法,比如,CV_FOURCC('P','I','M','L'),CV_FOURCC('M','P','E','G')
fps : 要创建视频流的帧率
frameSize:视频帧的大小
isColor: 如果为非0,编码器将要解码为颜色帧,否则为灰度帧
2 VideoWriter::open
初始化video writer
bool VideoWriter::open(const string &filename,int fourcc,double fps,Size frameSize,bool isColor=true)
类似构造函数
3 VideoWriter::isOpened
如果videowriter成功被初始化,返回true,否则返回0
bool VideoWriter::isOpened()
4 videoWriter::write
写入视频的下一帧给视频文件,所有的帧务必有相同的大小。
VideoWriter &VideoWriter::operator <<(const Mat & image)
void VideoWriter::write(const Mat & image)
参数解释:
image:被写入的帧
视频读取与写入就这些内容了,下面练习下吧。
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
//打开视频文件:其实就是建立一个VideoCapture结构
VideoCapture capture("D:/videos/PetsD2TeC2.avi");
//检测是否正常打开:成功打开时,isOpened返回ture
if(!capture.isOpened())
cout<<"fail to open!"<<endl;
//获取整个帧数
long totalFrameNumber = capture.get(CV_CAP_PROP_FRAME_COUNT);
cout<<"整个视频共"<<totalFrameNumber<<"帧"<<endl;
//设置开始帧()
long frameToStart = 300;
capture.set( CV_CAP_PROP_POS_FRAMES,frameToStart);
cout<<"从第"<<frameToStart<<"帧开始读"<<endl;
//设置结束帧
int frameToStop = 400;
if(frameToStop < frameToStart)
{
cout<<"结束帧小于开始帧,程序错误,即将退出!"<<endl;
return -1;
}
else
{
cout<<"结束帧为:第"<<frameToStop<<"帧"<<endl;
}
//获取帧率
double rate = capture.get(CV_CAP_PROP_FPS);
cout<<"帧率为:"<<rate<<endl;
//定义一个用来控制读取视频循环结束的变量
bool stop = false;
//承载每一帧的图像
Mat frame;
//显示每一帧的窗口
namedWindow("Extracted frame");
//两帧间的间隔时间:
//int delay = 1000/rate;
int delay = 1000/rate;
//利用while循环读取帧
//currentFrame是在循环体中控制读取到指定的帧后循环结束的变量
long currentFrame = frameToStart;
//滤波器的核
int kernel_size = 3;
Mat kernel = Mat::ones(kernel_size,kernel_size,CV_32F)/(float)(kernel_size*kernel_size);
while(!stop)
{
//读取下一帧
if(!capture.read(frame))
{
cout<<"读取视频失败"<<endl;
return -1;
}
//这里加滤波程序
imshow("Extracted frame",frame);
filter2D(frame,frame,-1,kernel);
imshow("after filter",frame);
cout<<"正在读取第"<<currentFrame<<"帧"<<endl;
//waitKey(int delay=0)当delay ≤ 0时会永远等待;当delay>0时会等待delay毫秒
//当时间结束前没有按键按下时,返回值为-1;否则返回按键
int c = waitKey(delay);
//按下ESC或者到达指定的结束帧后退出读取视频
if((char) c == 27 || currentFrame > frameToStop)
{
stop = true;
}
//按下按键后会停留在当前帧,等待下一次按键
if( c >= 0)
{
waitKey(0);
}
currentFrame++;
}
//关闭视频文件
capture.release();
waitKey(0);
return 0;
}
再来一个写入视频的,
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
VideoCapture capture;
capture.open("g:\\1.avi");
if(!capture.isOpened())
{
cout << "打开视频失败!";
return 0;
}
int FPS=capture.get(CV_CAP_PROP_FPS);
cout << "帧率为:" << FPS<<endl;
int count =capture.get(CV_CAP_PROP_FRAME_COUNT);
cout << "总帧数为:" << count << endl;
int width=capture.get(CV_CAP_PROP_FRAME_WIDTH);
int height=capture.get(CV_CAP_PROP_FRAME_HEIGHT);
Size size(width,height);
int framestart=100,framestop=300;
//设置开始帧
capture.set(CV_CAP_PROP_POS_FRAMES,framestart);
Mat frame;
namedWindow("yuan");
VideoWriter writer;
writer.open("g:\\jingwei.avi",CV_FOURCC('M','P','E','G'),FPS,size);
while(1)
{
if(capture.get(CV_CAP_PROP_POS_FRAMES)>framestop)
{
break;
}
capture >>frame;
imshow("yuan",frame);
writer <<frame;
waitKey(1000/FPS);
}
capture.release();
return 0;
}
好的,今天内容就到这里,下次再见哦!