利用opencv读取视频的奇数帧,并以某种命名方式保存在某一路径

本文介绍了一种从视频中抓取特定帧并将其存储为图片的方法,详细展示了如何使用OpenCV库在C++环境下实现视频帧的读取、选择与保存。通过设定开始和结束帧数,该程序能精确地捕获所需帧,并将图像区域感兴趣部分以jpg格式存储在指定目录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

可直接使用: 

bool CapPic(string fileName, long start, long end)
{
	_mkdir("D:\\workspace\\capPic\\20170504_A");//建立文件夹

	//打开视频文件:其实就是建立一个VideoCapture结构  
	VideoCapture capture("fileName");
	//检测是否正常打开:成功打开时,isOpened返回ture  
	if (!capture.isOpened())
	{
		cout << "fail to open!";
		return false;
	}

	//获取整个帧数  
	long totalFrameNumber = capture.get(CV_CAP_PROP_FRAME_COUNT);
	cout << "整个视频共" << totalFrameNumber << "帧" << endl;


	//设置开始帧()  
	long frameToStart = start; //1;
	size_t frameToEnd = end; //totalFrameNumber;

	//只要奇数帧
	if (frameToStart % 2 == 0)
	{
		frameToStart++;
	}
	if (frameToEnd % 2 == 0)
	{
		frameToEnd--;
	}
	//Sets a property in the VideoCapture:0-based index of the frame to be decoded/captured next.
	capture.set(CV_CAP_PROP_POS_FRAMES, frameToStart);
	cout << "从第" << frameToStart << "帧开始读" << endl;
	cout << "第" << frameToEnd << "帧结束" << endl;

	//获取帧率:Returns the specified VideoCapture property.
	//帧率:一秒多少帧
	double rate = capture.get(CV_CAP_PROP_FPS);
	cout << "帧率为:" << rate << endl;

	//定义一个用来控制读取视频循环结束的变量  
	bool stop = false;

	//承载每一帧的图像  
	Mat frame;

	//显示每一帧的窗口  
	//namedWindow("Extractedframe");

	//两帧间的间隔时间:ms
	//int delay = 1000/rate;  
	double delay = 1000 / rate;

	//利用while循环读取帧  
	//currentFrame是在循环体中控制读取到指定的帧后循环结束的变量  
	long currentFrame = frameToStart;

	while (currentFrame <= frameToEnd)
	{
		//读取下一帧  
		if (!capture.read(frame))
		{
			cout << "读取视频失败" << endl;
			return false;
		}

		//cout << "正在写第" << currentFrame << "帧" << endl;
		stringstream str;
		str << "./20170504_A/" << currentFrame << ".jpg";
		//cout << str.str() << endl;

		Mat roi = frame(Rect(1040, 200, 880, 880));   //get region of interesting 
		imwrite(str.str(), roi);
		currentFrame += 2;
        capture.read(frame);//奇数帧呢,空流
	}
	//关闭视频文件  
	capture.release();
	cout << "Done!" << endl;
}

完整程序:获取某一帧到另外一帧的所有图片,并存在对应的文件夹内,图片以帧,jpg命名,可在vs2015下运行:

涉及文件的读取,stringstream、string、const char*之间的转换、目录的建立等等,值得阅读。

#include <iostream>
#include <cstdlib>
#include <direct.h>
#include "opencv2/opencv.hpp"
#include <Windows.h>
#include <string>
#include <sstream>//stringstream
using namespace std;
using namespace cv;

bool CapPic(string fileName, long start, long end);
vector<vector<int>> ReadFile(string dataFile);

int main(int argc, char * argv[])
{
	string fileName = "D:\\workspace\\capPic\\20170504_A.MP4";
	string dataFile = "test.txt";
	
	vector<vector<int>> range = ReadFile(dataFile);
	int n = range.size();
	for (int i = 0; i < n; i++)
	{
		CapPic(fileName, range[i][0], range[i][1]);
	}
	return 0;
}

bool CapPic(string fileName, long start, long end)
{
	_mkdir("D:\\workspace\\capPic\\20170504_A");//建立文件夹

	//打开视频文件:其实就是建立一个VideoCapture结构  
	VideoCapture capture(fileName);
	//检测是否正常打开:成功打开时,isOpened返回ture  
	if (!capture.isOpened())
	{
		cout << "fail to open!";
		return false;
	}

	//获取整个帧数  
	long totalFrameNumber = capture.get(CV_CAP_PROP_FRAME_COUNT);
	cout << "整个视频共" << totalFrameNumber << "帧" << endl;


	//设置开始帧()  
	long frameToStart = start; //1;
	size_t frameToEnd = end; //totalFrameNumber;

	//只要奇数帧
	if (frameToStart % 2 == 0)
	{
		frameToStart++;
	}
	if (frameToEnd % 2 == 0)
	{
		frameToEnd--;
	}
	//Sets a property in the VideoCapture:0-based index of the frame to be decoded/captured next.
	capture.set(CV_CAP_PROP_POS_FRAMES, frameToStart);
	cout << "从第" << frameToStart << "帧开始读" << endl;
	cout << "第" << frameToEnd << "帧结束" << endl;

	//获取帧率:Returns the specified VideoCapture property.
	//帧率:一秒多少帧
	double rate = capture.get(CV_CAP_PROP_FPS);
	cout << "帧率为:" << rate << endl;

	//定义一个用来控制读取视频循环结束的变量  
	bool stop = false;

	//承载每一帧的图像  
	Mat frame;

	//显示每一帧的窗口  
	//namedWindow("Extractedframe");

	//两帧间的间隔时间:ms
	//int delay = 1000/rate;  
	double delay = 1000 / rate;

	//利用while循环读取帧  
	//currentFrame是在循环体中控制读取到指定的帧后循环结束的变量  
	long currentFrame = frameToStart;

	while (currentFrame <= frameToEnd)
	{
		//读取下一帧  
		if (!capture.read(frame))
		{
			cout << "读取视频失败" << endl;
			return false;
		}

		//cout << "正在写第" << currentFrame << "帧" << endl;
		
		stringstream dirStr;
		dirStr << "D:\\workspace\\capPic\\20170504_A\\" << frameToStart << "_" << frameToEnd;
		string dirStrTmp = dirStr.str();
		const char* constDirStr = dirStrTmp.c_str();//string转为const char*
		_mkdir(constDirStr);
		stringstream str;
		str << dirStrTmp << "\\" << currentFrame << ".jpg";
		string picName = str.str();
		//cout << str.str() << endl;

		Mat roi = frame(Rect(1040, 200, 880, 880));   //get region of interesting 
		imwrite(str.str(), roi);
		currentFrame += 2;
        capture.read(frame);空流,不存
	}
	//关闭视频文件  
	capture.release();
	cout << "Done!" << endl;
}

vector<vector<int>> ReadFile(string dataFile)
{
	vector<vector<int>> outData;
	vector<int> oneRowData;
	ifstream inFile;
	inFile.open(dataFile, ios::in);
	if (!inFile.is_open())
	{
		cout << "Error open file" << endl;
	}
	while (!inFile.eof())
	{
		string buffTmp;
		int nTmp = 0;
		while (getline(inFile, buffTmp))
		{
			stringstream stringIn(buffTmp);//使用串流实现对string的输入输出操作
			oneRowData.clear();
			while (stringIn >> nTmp)
			{
				oneRowData.push_back(nTmp);
			}
			outData.push_back(oneRowData);
		}
	}
	return outData;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值