在前一篇中已經實現了讀取攝像頭並實時顯示,本文將重要講述如何把它保存為視頻文件。
關鍵代碼
CvVideoWriter* writer = cvCreateVideoWriter(filePath,CV_FOURCC('P','I','M','1'),24,cvGetSize(frame)); cvWriteFrame(writer, frame); cvReleaseVideoWriter(&writer);
原理比較簡單,第一行cvCreateVideoWriter可創建一個writer,在創建時,可指定文件路徑、視頻編碼格式、幀率和大小等參數。第二行是向writer中寫入一幀圖片。當寫了很多幀,結束時,再調用cvReleaseVideoWriter釋放writer。
完整代碼
#include "cv.h" #include "highgui.h" int main(int argc, char** argv) { cvNamedWindow("win"); CvCapture* capture = cvCreateCameraCapture(0); IplImage* frame = cvQueryFrame(capture); char* writePath = "d:\\my.mpg"; CvVideoWriter* writer = cvCreateVideoWriter( writePath, CV_FOURCC('P','I','M','1'), 24, cvGetSize(frame) ); while(1) { frame = cvQueryFrame(capture); if(!frame) break; cvWriteFrame(writer, frame); cvShowImage("win", frame); char c = cvWaitKey(1000/24); if(c==27) break; } cvReleaseVideoWriter(&writer); cvReleaseCapture(&capture); cvDestroyWindow("win"); return 0; }
代碼比較簡單,無須解釋即可看明白。下面講幾個需要注意的地方。
編碼格式的選擇
cvCreateVideoWriter函數中需要指定一個編碼格式。在《學習OpenCV》的例子中,使用了CV_FOURCC('M','J','P','G')(即Motion JPEG)的格式。我本以為例子中推薦的編碼方式,肯定是最通用的,沒想到保存下來的視頻文件怎么都播放不了。后來改成CV_FOURCC('P','I','M','1')(即MPEG-1)才能正常播放。關於它支持的編碼格式還有很多,具體有哪些不記得了,因為我找不到那個網頁了
使用-1作為編碼格式
有資料說,在windows 32位系統上,可以使用-1作為編碼格式,這樣在程序運行時,會彈出一個對話框讓人選擇編碼方式。但在我的win7 x64上,沒有提示。(也有群友說他那里有提示)
關於幀率
在代碼中有兩個地方涉及幀率,一個是保存的視頻文件需要指定幀率,一個是從攝像頭讀取畫面時需要按一定的幀率。在我理解,如果這兩個幀率相同,保存的視頻文件中的畫面速度應該和正常速度是一樣的。於是我給視頻文件設了24,給讀取攝像頭的代碼設為每隔1000/24毫秒讀取一次。然而結果讓我很意外,因為不論我怎么調整,保存的視頻文件的播放速度都非常快。
經過思考與測試,最終發現,原來我的攝像頭每秒最多只能獲取6幀圖片。所以視頻文件的幀率也必須小於等於6。
如何獲取攝像頭的幀率
據說可以使用:
double fps = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
來取攝像頭的幀率,但我試了取不到,值總為0。
有群友說需要在前面先取一幀,再去取幀率,我試了還不行。可能攝像頭比較弱,或者windows自帶的驅動比較弱,拿不到。
有一個笨辦法,就是手動計算。在取一幀畫面前后計時,算出其幀率。
