OpenCV+VS 讀取、採集視訊、切割為序列影象
阿新 • • 發佈:2018-11-15
-
VideoCapture讀取視訊
cv::VideoCapture capture(const string& filename); // 輸入檔名
cv::VideoCapture capture(0); // 視訊捕捉裝置
將視訊幀讀取到cv::Mat矩陣中,有兩種方式:一種是read()操作;另一種是 “>>”操作。
cv::Mat frame;
cap.read(frame); //讀取方式一
cap >> frame; //讀取方式二
呼叫攝像頭採集影象
#include "opencv2/opencv.hpp" using namespace cv; int main() { //從攝像頭讀入影象 VideoCapture capture(0); while (1)//迴圈顯示每一幀 { Mat frame;//Mat變數儲存每一幀影象 capture >> frame;//讀取當前幀 imshow("讀取視訊", frame);//顯示當前幀 waitKey(30);//延時30秒 } return 0; }
注:需要開啟某個現成視訊影象時,將0替換為"./xxx.avi"即可。
實時處理視訊
其實就是對每一幀進行處理,frame作為影象,進行處理即可。
-
VideoWriter 視訊的寫操作
cv::VideoWriter out( "my_video.avi", //視訊檔名和路徑 CV_FOURCC('M','J','P','G'), // MPEG-4 編碼 30.0, // 幀率 (FPS) cv::Size( 640, 480 ), // 單幀圖片解析度為 640x480 true // 只輸入彩色圖,如果是false,可傳入灰度影象 );
向建立後的VideoWriter物件寫入影象也有兩種方式,即write()操作和“<<”操作
out.write(const Mat& image); // 寫入影象作為下一幀
my_video_writer << my_frame;
呼叫相機生成視訊並儲存
#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 = vcap.get(CV_CAP_PROP_FRAME_WIDTH); int frame_height = vcap.get(CV_CAP_PROP_FRAME_HEIGHT); //儲存視訊 VideoWriter video("out.avi", CV_FOURCC('M', 'J', 'P', 'G'), 30, Size(frame_width, frame_height), true); //需要for迴圈可以Ctrl+C終端錄製 for (;;){ Mat frame; vcap >> frame; video.write(frame); imshow("Frame", frame); char c = (char)waitKey(33); if (c == 27) break; } return 0; }
切割視訊為影象序列
#include <iostream>
#include <vector>
#include "opencv2\highgui\highgui.hpp"
using namespace std;
using namespace cv;
void video2image(string video, string path)
{
VideoCapture capture(video);
long totalFrameNumber = capture.get(CV_CAP_PROP_FRAME_COUNT);
cout << "total frames is:" << totalFrameNumber << "." << endl;
//設定開始幀
long frameToStart = 1;
capture.set(CV_CAP_PROP_POS_FRAMES, frameToStart);
cout << "from" << frameToStart << "read" << endl;
//設定結束幀
int frameToStop = 10;
//獲取幀率
double rate = capture.get(CV_CAP_PROP_FPS);
cout << "rate is:" << rate << endl;
double delay = 1000 / rate;
//定義一個用來控制讀取視訊迴圈結束的變數
bool stop = false;
long currentFrame = frameToStart;
if (!capture.isOpened())
{
cerr << "Failed to open a video" << endl;
return;
}
Mat frame;
int num = 1;
string filename;
char temp_file[15];
while (!stop)
{
capture >> frame;
if (frame.empty())
break;
_itoa_s(num, temp_file, 4, 10); //4表示字元長度,10表示十進位制,_itoa_s實現整型轉字串
filename = temp_file;
filename = path + filename + ".jpg";
cout << "now is reading" << currentFrame << "." << endl;
imshow("Extractedframe", frame);
cout << "now is writing" << currentFrame << "." << endl;
imwrite(filename, frame);
int c = waitKey(delay);
//按下ESC或者到達指定的結束幀後退出讀取視訊
if ((char)c == 27 || currentFrame > frameToStop)
{
stop = true;
}
//按下按鍵後會停留在當前幀,等待下一次按鍵
if (c >= 0)
{
waitKey(0);
}
num++;
currentFrame++;
}
capture.release();
waitKey(0);
}
int main(int argc, char** argv)
{
string videoFromfile = ".\\out.avi"; //讀取視訊
string Imagespath = ".\\image\\"; // 儲存圖片的資料夾路徑一定要有,因為OpenCV不會自動建立資料夾
video2image(videoFromfile, Imagespath);
return 0;
}
接下考慮實際使用時應該是呼叫攝像頭直接生成影象序列,並不是先生成視訊再切割為影象序列的。
下面的程式碼是自己修改的,只能產生了視訊,並沒有同時產生影象序列,有待完善
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
/*------------------採集儲存視訊avi--------------------*/
//開啟電腦攝像頭
VideoCapture cap(0);
if (!cap.isOpened()){
cout << "Error opening video stream or file" << endl;
return -1;
}
int frame_width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
int frame_height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);
//儲存視訊格式為avi, 編碼為MJPG
VideoWriter video("image1.avi", CV_FOURCC('M', 'J', 'P', 'G'), 30, Size(frame_width, frame_height), true);
//需要for迴圈可以Ctrl+C終止錄製
for (;;){
Mat frame;
cap >> frame;
video << frame;
imshow("Frame", frame);
waitKey(30);
}
/*------------------裁剪為影象序列--------------------*/
//讀取視訊
VideoCapture cap0("image1.avi");
if (!cap0.isOpened())
cout << "no video" << endl;
Mat frame0;
int num = 1;
string filename;
char temp_file[15];
string path = ".\\image1";
for (int i = 1;; i++)
{
cap0 >> frame0;
if (frame0.empty())
break;
_itoa_s(num, temp_file, 4, 10);//整型轉字串
filename = temp_file;
filename = path + filename + ".jpg";
num++;
imwrite(filename, frame0);
}
cap0.release();
return 0;
}