OpenCV捕获视频和摄像头
從文件中捕獲視頻
其實使用OpenCV讀取視頻相當簡單,只需要初始化一個VideoCapture對象,打開視頻文件,逐幀讀取。
程序
下面是簡單的OpenCV代碼:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | #include <opencv2\highgui\highgui.hpp> #include <iostream> ? usingnamespace cv; usingnamespace std; ? intmain(intargc,?char**argv) { ????//打開視頻文件 ????VideoCapture cap("Girls'Generation.avi"); ????if(!cap.isOpened()) ????{ ????????cout <<?"不能打開視頻文件"<< endl; ????????return-1; ????} ????//從3000ms開始播放視頻 ????//cap.set(CV_CAP_PROP_POS_MSEC, 3000); ? ????//獲取視頻的幀速率 ????doublefps = cap.get(CV_CAP_PROP_FPS); ????cout <<?"幀/秒:"<< fps << endl; ? ????namedWindow("MyVideo",CV_WINDOW_AUTOSIZE); ????while(true) ????{ ????????Mat frame; ????????//從視頻中讀取一個幀 ????????boolbSuccess = cap.read(frame); ????????if(!bSuccess) ????????{ ????????????cout <<"不能從視頻文件讀取幀"<< endl; ????????????break; ????????} ????????//在MyVideo窗口上顯示當前幀 ????????imshow("MyVideo", frame); ????????//如果30ms沒有按下鍵,就返回-1,當按下ESC鍵返回27 ????????if(waitKey(30)==27) ????????{ ????????????cout <<?"按下ESC鍵"<< endl; ????????????break; ????????} ????} ? ????return0; } |
解釋
| 1 | VideoCapture::VideoCapture(conststring& filename) |
這是VideoCapture類為數不多的構造函數的一個。這個構造函數打開視頻文件并為讀取視頻流初始化VideoCapture對象。
這個類的析構函數會釋放對象關聯的所有內存。因此,不需要在程序中顯示的釋放內存。
| 1 | boolVideoCapture::IsOpened() |
如果調用VideoCapture構造函數成功,這個方法返回true,否則返回false。
檢查VideoCapture初始化是否成功是有必要的。如果失敗,程序應該退出,否則當從VideoObject中讀取幀的時候,程序就會崩潰了。
| 1 | boolVideoCapture::set(intpropId,?doublevalue) |
這個方法改變VideoObject對象的屬性,如果成功,返回true,否則返回false。你應該在你的代碼中嘗試修改視頻流的一些屬性。在我的代碼中,我改變了CV_CAP_PROP_POS_MSEC屬性。
它的參數:
- int propID –?這個參數指定你要更改的屬性。這個參數有很多可選項,這里列出一部分。
- CV_CAP_PROP_POS_MSEC – 視頻的當前位置(毫秒)
- CV_CAP_PROP_POS_FRAMES –?視頻的當前位置(幀)
- CV_CAP_PROP_FRAME_WIDTH – 視頻流的寬度
- CV_CAP_PROP_FRAME_HEIGHT – 視頻流的高度
- CV_CAP_PROP_FPS – 幀速率(幀/秒)
- CV_CAP_PROP_FOURCC?– 編碼器的四字符編碼
- double value – 給propID分配的值。
| 1 | doubleVideoCapture::get(intpropId) |
這個函數返回指定的propId的屬性值。它的可選項和set函數的propID一樣。
| 1 | boolVideoCapture::read(Mat& image); |
這個函數抓取視頻的下一幀,解碼并存儲在‘image’變量中。在這個函數內部會調用VideoCapture::grap()和VideoCapture::retrieve()。可以使用這2個函數代替VideoCapture::read()函數。如果操作成功,返回true,否則返回false。
| 1 | waitKey(30) |
這個函數等待30毫秒。如果在指定的時間按下鍵,它會返回鍵的ASCII值。如果這個值是27,程序就會執行if塊。如果在30毫秒內沒有按下鍵,程序返回-1,程序繼續while循環。
| 1 | VideoCapture::~VideoCapture() |
VideoCapture對象的析構函數會釋放對象所有關聯的內存。在程序退出main方法時,析構函數會隱式調用。
總結
首先,這個程序從文件中捕獲一個視頻,然后進入一個無限循環。在這個循環中,它從捕獲的視頻中連續地抓取幀,解碼,然后顯示在窗口中并等待30毫秒。如果視頻沒有更多的幀或按下了ESC鍵,程序就會跳出無限循環。
注意:使用waitKey(int)函數非常重要,因為imshow(string&, MAT)函數需要時間在窗口上繪制圖像,正是waitKey(int)提供了這個時間。
從攝像頭中采集視頻
程序
下面的程序和上面的最大不同是VideoCapture構造函數的參數。這里我給VideoCapture的構造函數提供攝像頭的編號來代替一個文件名。下面是OpenCV代碼:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | #include <opencv2\highgui\highgui.hpp> #include <iostream> ? usingnamespace cv; usingnamespace std; ? intmain(intargc,?char**argv) { ????// 打開第1個攝像頭 ????VideoCapture cap(0); ? ????if(!cap.isOpened()) ????{ ????????cout <<?"不能打開攝像頭!"<< endl; ????????return-1; ????} ? ????//獲取視頻幀的寬度 ????doubledWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); ????//獲取視頻幀的高度 ????doubledHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); ? ????cout <<?"視頻幀尺寸 : "<< dWidth <<?" x "<< dHeight << endl; ? ????namedWindow("MyVideo", CV_WINDOW_AUTOSIZE); ? ????while(1) ????{ ????????Mat frame; ? ????????boolbSuccess = cap.read(frame); ? ????????if(!bSuccess) ????????{ ????????????cout <<?"不能從視頻流中讀取幀!"<< endl; ????????????break; ????????} ? ????????imshow("MyVideo", frame); ? ????????if(waitKey(30) == 27) ????????{ ????????????cout <<?"ESC鍵被按下"<< endl; ????????????break; ????????} ????} ????return0; ? } |
解釋
| 1 | VideoCapture::VideoCapture(intdevice) |
這是VideoCapture 3個構造函數的一個。這個構造函數打開給定編號的攝像頭并為讀取攝像頭的視頻流初始化VideoCapture對象。這里的“0”表示使用編號為0的攝像頭。如果你的電腦上有多個攝像頭,可以使用1,2,3…代替0。
| 1 | doubledWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH) |
這個函數獲取攝像頭輸出幀的寬(像素)
| 1 | doubledHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT) |
這個函數獲取攝像頭輸出幀的高(像素)
其他所有的函數都跟第一個程序中一樣。
總結
以上是生活随笔為你收集整理的OpenCV捕获视频和摄像头的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 保存处理后的视频文件
- 下一篇: error C3861: “setw”: