思路
视频是由帧组成的,先读取视频,设置初始帧和结束帧,根据所需的帧数量,从视频对象中读取帧,然后写入指定目录
主要步骤代码
//视频对象capture读取文件
VideoCapture capture("/home/gzl/CLionProjects/detection_yolo/frame_read_demo/run.mp4");
//读取视频中帧,读取时是逐帧读取
Mat frame;
capture.read(frame);
//将读到的帧写入指定目录
String str="";
imwrite(str,frame);
完整代码
//
// Created by gzl on 20-6-9.
//
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(){
//打开视频文件
VideoCapture capture("/home/gzl/CLionProjects/detection_yolo/frame_read_demo/run.mp4");
//判断文件是否打开
if(!capture.isOpened())
cout<<"文件不存在"<<endl;
//获取视频帧的总数
long totalFrameNumber =capture.get(CV_CAP_PROP_FRAME_COUNT);
cout << "整个视频共" << totalFrameNumber << "帧" << endl;
//设置开始帧
long frameToStart =1;
capture.set(CV_CAP_PROP_POS_FRAMES,frameToStart);
//设置结束帧
long frameToStop=100;
if(frameToStart>frameToStop){
cout << "结束帧小于开始帧,程序错误,即将退出!" << endl;
return -1;
} else{
cout << "结束帧为:第" << frameToStop << "帧" << endl;
}
//获取帧率
double rate=capture.get(CV_CAP_PROP_FPS);
cout<<"帧率为:"<<rate<<endl;
bool stop=false; //定义一个用来控制读取视频循环结束的变量
Mat frame;//承载帧的图像
double delay = 1000 / rate;//两帧间的间隔时间:
long currentFrame = frameToStart;//currentFrame是在循环体中控制读取到指定的帧后循环结束的变量
String str="/home/gzl/CLionProjects/detection_yolo/test_p/";
//利用while循环读取帧
while(!stop)
{
if(!capture.read(frame)){
cout << "读取视频失败" << endl;
return -1;
}
//每隔3次保存一帧
if(currentFrame%3==0){
stringstream str;
str << "/home/gzl/CLionProjects/detection_yolo/test_p/run/" << currentFrame << ".png";//*图片存储位置*//*
cout << str.str( ) << endl;
imwrite( str.str( ), frame );
}
//waitKey(intdelay=0)当delay≤ 0时会永远等待;当delay>0时会等待delay毫秒
//当时间结束前没有按键按下时,返回值为-1;否则返回按键
int c = waitKey( 1 );
//按下ESC或者到达指定的结束帧后退出读取视频
if ( ( char )c == 27 || currentFrame > frameToStop )
{
stop = true;
}
//按下按键后会停留在当前帧,等待下一次按键
if ( c >= 0 )
{
waitKey( 0 );
}
currentFrame++;
}
//关闭视频文件
capture.release();
waitKey(0);
return 0;
}