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; }最后得到循环播放视频文件中的片段,并保持整个视频完整。