利用opencv讀取視訊的奇數幀,並以某種命名方式儲存在某一路徑
阿新 • • 發佈:2018-12-01
可直接使用:
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; }