1. 程式人生 > >利用opencv讀取視訊的奇數幀,並以某種命名方式儲存在某一路徑

利用opencv讀取視訊的奇數幀,並以某種命名方式儲存在某一路徑

可直接使用: 

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;
}