- 從零開始:數字圖像處理的編程基礎與應用
- 彭凌西 彭紹湖 唐春明 陳統編著
- 1381字
- 2022-04-13 16:24:02
1.5 視頻讀取與輸出
OpenCV中視頻的讀和寫操作,分別是通過cv::VideoCapture和cv::VideoWriter兩個類來實現的。
· 1.5.1 視頻讀取
cv::VideoCapture類是讀取視頻的,cv::VideoCapture既支持視頻文件的讀取,也支持從視頻捕捉設備中讀取視頻。cv::VideoCapture類的對象創建方式有以下3種。
cv::VideoCapture capture(const string& filename,);
// 第一種:從輸入文件名對應的文件中讀取
cv::VideoCapture capture(int device);
// 第二種:從視頻捕捉設備 ID中讀取視頻
cv::VideoCapture capture();
//第三種:調用無參構造函數創建對象
第一種方式是從文件(AVI格式或者MP4格式等)中讀取視頻,對象創建完成以后,OpenCV將會打開文件并準備讀取它。如果打開成功,將可以開始讀取視頻的幀,通過cv::VideoCapture類的成員函數isOpened()返回的true結果可以判斷打開讀取對象成功(建議在打開視頻或攝像頭時都使用該成員函數,以判斷是否打開成功)。
第二種方式是從視頻捕捉設備中讀取視頻。這種情況下,可以給出一個標識符,用于表示想要訪問的視頻捕捉設備,及其與操作系統的握手方式。對于視頻捕捉設備而言,這個標識符就是一個標識數字——如果只有一臺視頻捕捉設備,那么就是0,如果系統中有多臺視頻捕捉設備,那么增加標識數字的值即可。
第三種方式僅創建一個捕獲對象,而不提供任何關于打開的信息。對象創建以后通過成員函數open()來設定打開的信息。open()操作也有以下兩種方式。
cv::VideoCapture cap;
cap.open( "my_video.avi"); //第一種方式打開視頻文件
cap.open(0); //第二種方式打開視頻捕捉設備
打開視頻后,需要將視頻幀讀取到cv::Mat矩陣中,共有兩種方式,一種是read()操作,另一種是>>操作。示例如下。
cv::Mat frame;
cap.read(frame); //讀取方式一
cap >> frame; //讀取方式二
綜上,視頻的讀取操作步驟如下。
(1)創建cv::VideoCapture的對象。
cv::VideoCapture capture("D:/images/test1.mp4");
參數類型為const string&,即從文件中讀取,若設置為0則讀取視頻捕捉設備。
(2)驗證視頻讀取是否成功。
if (!capture.isOpened())
{
std::cout << "Vidoe open failed!" << std::endl;
return -1;
}
(3)驗證完成,開始讀取視頻。
cv::Mat frame;
capture >> frame;
用戶可以將VideoCapture對象像流一樣讀入Mat類型的對象(即圖像)中。
下面將創建例1-4來展示視頻文件的讀取操作。
例1-4:視頻文件讀取。
項目完整代碼文件(main.cpp文件)如下(需在1-4.pro文件中加入OpenCV配置信息,此處不再重復,詳情可參考例1-3)。
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main()
{
VideoCapture capture("D:/images/test1.mp4");
if (!capture.isOpened())
{
cout << "Read video Failed !" << std::endl;
return -1;
}
Mat frame;
namedWindow("video test");
int frame_num = capture.get(cv::CAP_PROP_FRAME_COUNT);
cout << "total frame number is: " << frame_num << std::endl;
for (int i = 0; i < frame_num - 1; ++i)
{
capture >> frame;
//capture.read(frame); 第二種方式
imshow("video test", frame); //展示幀圖像
if (cv::waitKey(30) == 'q')
{
break;
}
}
destroyWindow("video test"); //銷毀窗口
capture.release(); //釋放對象
return 0;
}
注意,上面的代碼中使用cv::VideoCapture類的成員函數get()和設定標識cv::CAP_PROP_FRAME_COUNT獲取了讀取視頻的總幀數。同樣,可以通過指定其他標識來獲取讀取視頻或視頻捕捉設備的其他屬性。
程序運行結果如圖1-51所示。


圖1-51 例1-4程序運行結果
· 1.5.2 視頻輸出
cv::VideoWriter類用于寫入視頻,該類使用起來比cv::VideoCapture類稍微復雜一些。cv::VideoWriter類的對象的創建有兩種方式,第一種是使用構造函數,第二種是使用open()函數,具體示例如下。
第一種方式。
cv::VideoWriter out(
const string& filename, // 輸出文件名
int fourcc, // 編碼形式,使用 CV_FOURCC()宏
double fps, // 輸出視頻幀率
cv::Size frame_size, // 單幀圖像的大小
bool is_color = true // 如果是false,則可傳入灰度圖像,true為彩色圖像
);
第二種方式。
cv::VideoWriter out;
out.open(
"my_video.mpg", //輸出文件名
CV_FOURCC('D','I','V','X'), // MPEG-4 編碼
30.0, // 輸出視頻幀率
cv::Size( 640, 480 ), // 單幀圖像分辨率為 640像素×480像素
true // 只可傳入彩色圖像,false為灰度圖像
);
其中需要注意的是FOURCC編碼形式,操作時常用以下函數把4個字符連接起來形成一個FOURCC 碼,形式為cv::VideoWriter::fourcc(char c1,char c2,char c3,char c4)。
常用的格式有如下幾種。
- CV_FOURCC('P','I','M','1') = MPEG-1 codec。
- CV_FOURCC('M','J','P','G') = motion-jpg codec。
- CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec。
- CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec。
- CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec。
向創建的cv::VideoWriter對象寫入圖像也有兩種方式,即write()操作和<<操作,示例如下。
cv::VideoWriter::write(
const Mat& image // 寫入圖像作為下一幀
);
out << frame;
下面通過創建例1-5展示完整的視頻讀取(同例1-4,需要在1-5.pro文件中加入OpenCV配置信息)、處理及輸出操作。
例1-5: 讀取視頻。
具體代碼如下。
#include<stdio.h>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main()
{
Mat frame;
string filename = "D:/images/test1.mp4";
VideoCapture cap(filename);
VideoWriter out;
out.open("D:/images/out.mp4",
cv::VideoWriter::fourcc('D','I','V','X'),
cap.get(CAP_PROP_FPS),
Size(cap.get(CAP_PROP_FRAME_WIDTH),cap.get(CAP_PROP_FRAME_HEIGHT)),
true);
if (!cap.isOpened())
{
cout << "Video load failed!" << endl;
return -1;
}
while (1)
{
cap >> frame;
if (frame.empty())
{
cout << "Video process finished!" << endl;
return 0;
}
imshow("video",frame);
if (waitKey(10) == 'q') break;
out << frame;
}
cap.release();
return 0;
}
注意,上面的代碼中使用cv::VideoCapture類的成員函數get()和設定標識CAP_PROP_FPS獲取讀取視頻的幀率。標識CAP_PROP_FRAME_WIDTH和CAP_PROP_FRAME_HEIGHT分別表示獲取的視頻圖像的長度和寬度。
程序運行結果如圖1-52所示。


圖1-52 例1-5程序運行結果
- 演進式架構(原書第2版)
- Learning ROS for Robotics Programming(Second Edition)
- Android開發精要
- 單片機C語言程序設計實訓100例:基于STC8051+Proteus仿真與實戰
- 信息安全技術
- Flash CS6中文版應用教程(第三版)
- Learning Neo4j 3.x(Second Edition)
- C語言程序設計學習指導與習題解答
- AutoCAD 2009實訓指導
- Getting Started with Python and Raspberry Pi
- Java并發編程:核心方法與框架
- Simulation for Data Science with R
- Arduino電子設計實戰指南:零基礎篇
- MongoDB Cookbook(Second Edition)
- 零基礎學編程系列(全5冊)