現在找一個能拍攝視頻的設備真是太容易了。結果大家都用視頻來代替以前的序列圖像。視頻可能由兩種形式得到,一個是像網絡攝像頭那樣實時視頻流,或者由其他設備產生的壓縮編碼后的視頻文件。幸運的是,OpenCV可以使用相同的C++類、用同一種方式處理這些視頻信息。在接下來的教程里你將學習如何使用攝像頭或者視頻文件。
- 如何打開和讀取視頻流
- 兩種檢查相似度的方法:PSNR和SSIM
如何讀取一個視頻流(攝像頭或者視頻文件)?
總的來說,視頻捕獲需要的所有函數都集成在 VideoCapture C++ 類里面。雖然它底層依賴另一個FFmpeg開源庫,但是它已經被集成在OpenCV里所以你不需要額外地關注它的具體實現方法。你只需要知道一個視頻由一系列圖像構成,我們用一個專業點兒的詞匯來稱呼這些構成視頻的圖像:“幀”(frame)。此外在視頻文件里還有個參數叫做“幀率”(frame rate)的,用來表示兩幀之間的間隔時間,幀率的單位是(幀/秒)。這個參數只和視頻的播放速度有關,對於單獨的一幀圖像來說沒有任何用途。
你需要先定義一個 VideoCapture 類的對象來打開和讀取視頻流。具體可以通過 constructor 或者通過 open 函數來完成。如果使用整型數當參數的話,就可以將這個對象綁定到一個攝像機,將系統指派的ID號當作參數傳入即可。例如你可以傳入0來打開第一個攝像機,傳入1打開第二個攝像機,以此類推。如果使用字符串當參數,就會打開一個由這個字符串(文件名)指定的視頻文件。
CvCapture 是一個結構體,用來保存圖像捕獲所需要的信息。 opencv提供兩種方式從外部捕獲圖像:
VideoCapture類 用於從視頻文件或攝像機捕獲視頻.該類提供了用於從攝像機捕獲視頻或者讀取視頻文件的C++ API。 注意:在C API中使用黑盒子結構CvCapture來代替VideoCapture。 構造函數 VideoCapture::VideoCapture() VideoCapture::VideoCapture(const string& filename)//filename – 文件名 VideoCapture::VideoCapture(int device)//device – 捕獲視頻的編號. 如果只有一個設備,默認編號為0 open函數 打開視頻文件或捕獲設備進行視頻捕獲 bool VideoCapture::open(const string& filename)//filename – 文件名 bool VideoCapture::open(int device)//device – 捕獲視頻的編號. 如果只有一個設備,默認編號為0 isopened函數 如果視頻捕獲已經初始化,則返回true。 bool VideoCapture::isOpened() release函數 關閉視頻文件或捕獲設備 void VideoCapture::release() grap函數 從視頻文件或捕獲設備中捕獲下一幀 bool VideoCapture::grab() retrieve函數 解碼並返回抓取的視頻幀 bool VideoCapture::retrieve(Mat& image, int channel=0) read函數 抓取,解碼並返回下一個視頻幀 bool VideoCapture::read(Mat& image) get函數 返回指定的VideoCapture屬性 double VideoCapture::get(int propId)//propId - 屬性標識符 CV_CAP_PROP_POS_MSEC - 視頻文件的當前位置(以毫秒為單位)或視頻捕獲時間戳。 CV_CAP_PROP_POS_FRAMES - 下一個要解碼/捕獲的幀的基於0的索引。 CV_CAP_PROP_POS_AVI_RATIO - 視頻文件的相對位置:0 - 電影的開始,1 - 電影的結束。 CV_CAP_PROP_FRAME_WIDTH - 視頻流中幀的寬度。 CV_CAP_PROP_FRAME_HEIGHT - 視頻流中幀的高度。 CV_CAP_PROP_FPS - 幀速率。 CV_CAP_PROP_FOURCC - 編解碼器的4個字符代碼。 CV_CAP_PROP_FRAME_COUNT - 視頻文件中的幀數。 CV_CAP_PROP_FORMAT - retrieve()返回的Mat對象的格式。 CV_CAP_PROP_MODE - 指示當前捕獲模式的后端特定值。 CV_CAP_PROP_BRIGHTNESS - 圖像的亮度(僅適用於相機)。 CV_CAP_PROP_CONTRAST - 圖像的對比度(僅適用於相機)。 CV_CAP_PROP_SATURATION - 圖像的飽和度(僅適用於相機)。 CV_CAP_PROP_HUE - 圖像的色調(僅適用於攝像機)。 CV_CAP_PROP_GAIN - 圖像的增益(僅適用於攝像機)。 CV_CAP_PROP_EXPOSURE - 曝光(僅適用於相機)。 CV_CAP_PROP_CONVERT_RGB - 指示圖像是否應轉換為RGB的布爾標志。 CV_CAP_PROP_WHITE_BALANCE - 目前不支持 CV_CAP_PROP_RECTIFICATION - 立體相機的校正標志(注意:目前僅由DC1394 v 2.x后端支持) set函數 設置VideoCapture中的屬性。 bool VideoCapture::set(int propertyId, double value)//propId - 屬性標識符,同get;value - 屬性的值。
#include<opencv2/opencv.hpp> using namespace cv; void main() { VideoCapture cap; cap.open("E:\\VS2015Opencv\\vs2015\\project\\video\\01.avi"); //打開視頻,以上兩句等價於VideoCapture cap("E://01.avi"); //cap.open("http://www.laganiere.name/bike.avi");//也可以直接從網頁中獲取圖片,前提是網頁有視頻,以及網速夠快 if (!cap.isOpened())//如果視頻不能正常打開則返回 return ; Mat frame; while (1) { cap >> frame;//等價於cap.read(frame); if (frame.empty())//如果某幀為空則退出循環 break; imshow("video", frame); waitKey(20);//每幀延時20毫秒 } cap.release();//釋放資源 }


#include<opencv2/opencv.hpp> #include<iostream> using namespace cv; using namespace std; void main() { VideoCapture cap; cap.open("E:\\VS2015Opencv\\vs2015\\project\\video\\01.avi"); if (!cap.isOpened()) return; int width = cap.get(CV_CAP_PROP_FRAME_WIDTH); //幀寬度 int height = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //幀高度 int frameRate = cap.get(CV_CAP_PROP_FPS); //幀率 x frames/s int totalFrames = cap.get(CV_CAP_PROP_FRAME_COUNT); //總幀數 cout << "視頻寬度=" << width << endl; cout << "視頻高度=" << height << endl; cout << "視頻總幀數=" << totalFrames << endl; cout << "幀率=" << frameRate << endl; Mat frame; while (1) { cap >> frame;//等價於cap.read(frame); if (frame.empty()) break; imshow("video", frame); if (waitKey(33) != 255) break; } cap.release(); }


將左邊的waitkey(33)改成右邊的if(waitKey(20)>0)break;
程序會直接跳出,不放視頻
opencv學習之等待按鍵事件-waitKey函數
waitkey(20) 如果不按鍵的時候是返回 oxff,這個無符號就是255,有符號就是-1
windows vs 的環境默認了這個為非符號數 即255,而opencv的新手書中,往往作者環境會認為是-1
解決方案:把原始代碼中循環讀取幀的
if (waitKey(33)>=0)break;
改為
if (waitKey(33) != 255)break;
或者把waitkey的返回值用有符號數去讀取。
