1. 程式人生 > >OpenCV+VS 讀取、採集視訊、切割為序列影象

OpenCV+VS 讀取、採集視訊、切割為序列影象

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