OpenCV中使用摄像头录像并保存并不难实现,本文针对摄像头实时帧画面进行记录,并重复播放
视频文件的读取和处理方法类似,首先,本文对摄像头进行采集和实时帧画面显示。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(){
VideoCapture vcap(0);
if(!vcap.isOpened()){
cout << "Error opening video stream or file" << endl;
return -1;
}
int frame_width = (int)vcap.get(CV_CAP_PROP_FRAME_WIDTH);
int frame_height = (int)vcap.get(CV_CAP_PROP_FRAME_HEIGHT);
VideoWriter video("out.avi",CV_FOURCC('M','J','P','G'),10, Size(frame_width,frame_height),true);
while (1)
{
Mat frame;
vcap >> frame;
video.write(frame);
imshow( "Frame", frame );
char c = (char)waitKey(33);
if( c == 27 ) break;
}
return 0;
}
具体不明白的细节请自行查找。。
接下来对记录的视频画面进行处理。
读取视频文件
本文实现的功能是,对一段实时画面中的某一个片段循环播放,并能够保证前后播放流畅。具体如下:
初次尝试:
固定视频中的某一帧。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(){
VideoCapture vcap("out.avi");
if(!vcap.isOpened()){
cout << "Error opening video stream or file" << endl;
return -1;
}
int frame_width = (int)vcap.get(CV_CAP_PROP_FRAME_WIDTH);
int frame_height = (int)vcap.get(CV_CAP_PROP_FRAME_HEIGHT);
int fps = vcap.get(CV_CAP_PROP_FPS);
int frame_size = vcap.get(CV_CAP_PROP_FRAME_COUNT);
cout<<frame_size<<endl;
int i = 0;
Mat frame;
while (vcap.read(frame))
{
if (frame.empty())break;
i++;
if (i == 100 )waitKey(10*1000);
imshow( "Frame", frame );
char c = (char)waitKey(33);
if( c == 27 ) break;
}
return 0;
}
本段代码实现将第一百帧延时10s,其他画面保持不变。
更进一步的说:
//
// //
// //
// Edit by Call_Me_Yang Date: 2014-12-02 //
// //
// //
//
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(){
VideoCapture vcap("out.avi"); //建立VidepCapture结构,打开视频文件。
if(!vcap.isOpened()){ //打开视频文件
cout << "Error opening video stream or file" << endl;
return -1;
}
int frame_width = (int)vcap.get(CV_CAP_PROP_FRAME_WIDTH);
int frame_height = (int)vcap.get(CV_CAP_PROP_FRAME_HEIGHT);
int rate = vcap.get(CV_CAP_PROP_FPS); //视频的帧率
int frame_size = vcap.get(CV_CAP_PROP_FRAME_COUNT); //视频的帧数
cout<<frame_size<<endl;
int i = 0; //计算当前的帧数
Mat frame;
while (vcap.read(frame)) //读取当前帧图像
{
if (frame.empty())break; //判断当前帧是否为空,结束时自动跳出while循环
i++; //当前帧自动加一
if ( i < 100) //前面100帧图像保持不变,顺序播放
{
imshow( "Frame", frame );
char c = (char)waitKey(33);
if( c == 27 ) break;
}
if (i == 100) //第100帧时
{
for (int j = 0; j < 3; j++) //循环播放次数,这里循环播放3次
{
//vcap.release();
long frameToStart = 100; //设置开始帧
vcap.set( CV_CAP_PROP_POS_FRAMES,frameToStart);
cout<<"从第"<<frameToStart<<"帧开始读"<<endl;
int frameToStop = 200; //设置结束帧
if(frameToStop < frameToStart)
{
cout<<"结束帧小于开始帧,程序错误,即将退出!"<<endl;
return -1;
}
else
{
cout<<"结束帧为:第"<<frameToStop<<"帧"<<endl;
}
bool stop = false; //定义一个用来控制读取视频循环结束的变量
Mat frame; //承载每一帧的图像
int delay = 1000/rate; //两帧间的时间间隔
long currentFrame = frameToStart; //currentFrame是在循环体中控制读取到指定的帧后循环结束的变量
while(!stop)
{
if(!vcap.read(frame)) //读取下一帧
{
cout<<"读取视频失败"<<endl;
break;
}
cv::imshow("Frame",frame);
cout<<"正在读取第"<<currentFrame<<"帧"<<endl;
int c = waitKey(delay);
if((char) c == 27 || currentFrame >= frameToStop)
{
stop = true;
}
if( waitKey(delay) >= 0) //按下按键后会停留在当前帧,等待下一次按键
{
waitKey(0);
}
currentFrame++;
}
}
}
if ( i >= 200 )
{
if(!vcap.isOpened()){ //打开视频文件
cout<<"fail to open!"<<endl;
return -1;
}
double rate = vcap.get(CV_CAP_PROP_FPS); //获取整个帧数
int delay = 1000/rate;
long frameToStart = 200;
vcap.set( CV_CAP_PROP_POS_FRAMES,frameToStart);
bool stop = false;
Mat frame;
while(!stop)
{
if(!vcap.read(frame))
{
cout<<"读取视频失败"<<endl;
break;
}
if (frame.empty())break;
imshow("Frame",frame);
int c = waitKey(delay);//waitKey(int delay=0)当delay ≤ 0时会永远等待;当delay>0时会等待delay毫秒
//当时间结束前没有按键按下时,返回值为-1;否则返回按键
if((char) c == 27 ) //按下ESC或者到达指定的结束帧后退出读取视频
{
stop = true;
}
if( c >= 0) //按下按键后会停留在当前帧,等待下一次按键
{
waitKey(0);
}
} //while循环结束
} //if(i >= 200)循环结束
} //while循环结束
return 0;
}
最后得到循环播放视频文件中的片段,并保持整个视频完整。