上一篇文章介紹了OpenCV對於圖像的處理方法,然而目前對視頻的處理分析越來越成爲計算機視覺的主流,視頻中包含的信息量要遠遠大於圖片,而本質上視頻是由一幀幀的圖像組成,所以視頻處理最終還是要歸結於圖像處理,但在視頻處理中,有更多的時間維的信息可以利用。本文主要介紹OpenCV在處理視頻時的一些基本函數
1、視頻的讀取(cv::VIdeoCpature)
視頻讀取,主要利用VideoCapture類下的方法打開視頻並獲取視頻中的幀,其操作有很多,這裏只提及最普遍的用法
具體可見:https://docs.opencv.org/3.1.0/d8/dfe/classcv_1_1VideoCapture.html
1.1使用構造函數獲取視頻文件
//在該構造函數中,輸入正確的視頻文件的文件路徑即可,OpenCV會打開對應的視頻文件
cv::VideoCapture::VideoCapture(const string& filename);
打開視頻文件有兩種方法
//方法一
VideoCapture cap("E:/myFile/video/ty.mp4");//獲取E:/myFile/video路徑下的ty.mp4視頻文件
//方法二
VideoCapture cap;
cap.open("E:/myFile/video/ty.mp4");//使用open方法
//在該構造函數中,輸入攝像頭ID,則可打開對應的攝像頭,默認攝像頭爲0
cv::VideoCapture::VideoCapture(int device);
VideoCapture cap(0);//讀取默認攝像頭
1.2驗證視頻是否讀入成功
若成功讀取視頻文件則放回True,否則返回False
if (!cap.isOpened())
{
cout << "無法打開視頻文件!" << endl;
return -1;
}
1.3獲取視頻幀
獲取視頻幀有以下多種方法
Mat frame;
//方法一
capture.read(frame);
//方法二
capture.grab();
capture.retrieve(frame);
//方法三
capture>>frame;
1.4獲取視頻的參數
一個視頻有很多參數,如:幀率、總幀數、尺寸、格式等,VideoCapture的get方法可以獲取大量的這些參數
參數表如下表所示
參數 |
對應宏 | 說明 |
VideoCapture.get(0) | CV_CAP_PROP_POS_MSEC | 視頻文件的當前位置(播放)以毫秒爲單位 |
VideoCapture.get(1) | CV_CAP_PROP_POS_FRAMES | 基於以0開始的被捕獲或解碼的幀索引 |
VideoCapture.get(2) | CV_CAP_PROP_POS_AVI_RATIO | 視頻文件的相對位置(播放):0=電影開始,1=影片的結尾 |
VideoCapture.get(3) | CV_CAP_PROP_FRAME_WIDTH | 在視頻流的幀的寬度 |
VideoCapture.get(4) | CV_CAP_PROP_FRAME_HEIGHT | 在視頻流的幀的高度 |
VideoCapture.get(5) | CV_CAP_PROP_FPS | 幀速率/幀數/fps |
VideoCapture.get(6) | CV_CAP_PROP_FOURCC | 編解碼的4字-字符代碼 |
VideoCapture.get(7) | CV_CAP_PROP_FRAME_COUNT | 視頻文件中的幀數 |
VideoCapture.get(8) | CV_CAP_PROP_FORMAT | 返回對象的格式 |
VideoCapture.get(9) | CV_CAP_PROP_MODE | 返回後端特定的值,該值指示當前捕獲模式 |
VideoCapture.get(10) | CV_CAP_PROP_BRIGHTNESS | 圖像的亮度(僅適用於照相機) |
VideoCapture.get(11) | CV_CAP_PROP_CONTRAST | 圖像的對比度(僅適用於照相機) |
VideoCapture.get(12) | CV_CAP_PROP_SATURATION | 圖像的飽和度(僅適用於照相機) |
VideoCapture.get(13) | CV_CAP_PROP_HUE | 色調圖像(僅適用於照相機) |
VideoCapture.get(14) | CV_CAP_PROP_GAIN | 圖像增益(僅適用於照相機)(Gain在攝影中表示白平衡提升) |
VideoCapture.get(15) | CV_CAP_PROP_EXPOSURE | 曝光(僅適用於照相機) |
VideoCapture.get(16) | CV_CAP_PROP_CONVERT_RGB | 指示是否應將圖像轉換爲RGB布爾標誌 |
VideoCapture.get(17) | CV_CAP_PROP_WHITE_BALANCE | × 暫時不支持 |
VideoCapture.get(18) | CV_CAP_PROP_RECTIFICATION | 立體攝像機的矯正標註(目前只有DC1394 v.2.x後端支持這個功能) |
示例如下圖所示
1.5設置視頻幀的讀取位置
VideoCapture類的set方法可以允許我們取出視頻中某個位置的幀
它有一些參數,可以按時間,也可以按幀號,還可以按視頻長短的比例
//第100幀
double position=100.0;
capture.set(CV_CAP_PROP_POS_FRAMES,position);
//第1e6毫秒
double position=1e6;
capture.set(CV_CAP_PROP_POS_MSEC,position);
//視頻1/2位置
double position=0.5;
capture.set(CV_CAP_PROP_POS_AVI_RATIO,position);
同時set方法還可以設置視頻的幀率、亮度
2、視頻的寫入(cv::VIdeoWriter)
視頻的寫入與讀取類似,使用VideoWriter類來實現,這個類有幾個方法,除了構造函數外,提供了open、IsOpen、write、和重載操作符<<
cv::VideoWriter(const string& path,int fourcc,double fps, Size framesize, bool isColor=true)
- 第一個參數表示保存的文件路徑和文件名
- 第二個參數表示編碼格式
- 第三個參數表示幀率
- 第四個參數表示視頻尺寸大小
- 第五個參數表示視頻圖像類型(true彩色,false灰度)
需要注意的是fourcc的常用格式有
- CV_FOURCC('P','I','M','1') = MPEG-1 codec
- CV_FOURCC('M','J','P','G') = motion-jpeg codec
- CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec
- CV_FOURCC('D', 'I', 'V', '3') = MPEG-4.3 codec
- CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec
- CV_FOURCC('U', '2', '6', '3') = H263 codec
- CV_FOURCC('I', '2', '6', '3') = H263I codec
- CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec
3、視頻讀寫程序示例
視頻讀取
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
VideoCapture cap("E:/myFile/video/ty.mp4");
Mat frame;
if (!cap.isOpened())
{
cout << "無法打開視頻文件!" << endl;
return -1;
}
namedWindow("video", CV_WINDOW_AUTOSIZE);
while (cap.read(frame))
{
imshow("video", frame);
waitKey(10);
}
cap.release();
waitKey(0);
return 0;
}
視頻寫入
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
VideoCapture cap("E:/myFile/video/ty.mp4");
Mat frame, gray;
if (!cap.isOpened())
{
cout << "無法打開視頻文件!" << endl;
return -1;
}
//獲取視頻幀的長和寬
Size size = Size(cap.get(CV_CAP_PROP_FRAME_WIDTH), cap.get(CV_CAP_PROP_FRAME_HEIGHT));
VideoWriter writer("E:/myFile/video/ty_g.mp4", CV_FOURCC('M', 'J', 'P', 'G'), 24, size, true);
namedWindow("video", CV_WINDOW_AUTOSIZE);
while (cap.read(frame))
{
//imshow("video", frame);
//轉換爲黑白圖像
cvtColor(frame, gray, COLOR_BGR2GRAY);
//二值化處理
threshold(gray, gray, 0, 255, THRESH_BINARY | THRESH_OTSU);
cvtColor(gray, gray, COLOR_GRAY2BGR);
imshow("video", gray);
writer.write(gray);
waitKey(10);
}
waitKey(0);
cap.release();
return 0;
}
歡迎大家補充學習!!!