視頻處理
[編輯]
一、從視頻流中捕捉一幀畫面
[編輯]
(1) OpenCV 支持從攝像頭或視頻文件(AVI格式)中捕捉幀畫面.
[編輯]
(2) 初始化一個攝像頭捕捉器:
CvCapture* capture = cvCaptureFromCAM(0); // capture from video device #0
[編輯]
(3) 初始化一個視頻文件捕捉器:
CvCapture* capture = cvCaptureFromAVI("infile.avi");
[編輯]
(4) 捕捉一幀畫面:
IplImage* img = 0;
if(!cvGrabFrame(capture)){ // capture a frame
printf("Could not grab a frame\n\7");
exit(0);
}
img=cvRetrieveFrame(capture); // retrieve the captured frame
若要從多個攝像頭中同步捕捉畫面,則須首先從每一個攝像頭中抓取一幀,緊接着要將被捕捉的幀畫面恢復到一個IplImage*型圖像中。(譯註:這一過程其實能夠用 cvQueryFrame() 函數一步完成)
[編輯]
(5) 釋放視頻流捕捉器:
cvReleaseCapture(&capture);
注意由視頻流捕捉器獲得的圖像是由捕捉器分配和釋放內存的,不須要單獨對圖像進行釋放內存的操做。
[編輯]
二、獲取/設置視頻流信息
[編輯]
(1) 獲取視頻流設備信息:
cvQueryFrame(capture); // 在讀取視頻流信息前,要先執行此操做
int frameH = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
int frameW = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
int fps = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
int numFrames = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);
統計總幀數僅對視頻文件有效,但彷佛不太準確(譯註:也許OpenCV2.0中此問題已解決)
[編輯]
(2) 獲取幀圖信息:
float posMsec = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_MSEC);
int posFrames = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES);
float posRatio = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO);
所抓取的幀的位置有三種表達方式:距離第一幀畫面的時間間隔(毫秒爲單位), 或者距離第一幀畫面(序列號爲0)的序列數. 第三種方式是按相對比率,第一幀的相對比率爲0,最後一幀的相對比率爲1. 此方式僅對讀取視頻文件時有效.
[編輯]
(3) 設置從視頻文件抓取的第一幀畫面的位置:
// start capturing from a relative position of 0.9 of a video file
cvSetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO, (double)0.9);
注意此方法定位並不許確。
[編輯]
三、保存視頻文件
[編輯]
(1) 初始化視頻編寫器:
CvVideoWriter *writer = 0;
int isColor = 1;
int fps = 25; // or 30
int frameW = 640; // 744 for firewire cameras
int frameH = 480; // 480 for firewire cameras
writer=cvCreateVideoWriter("out.avi",CV_FOURCC('P','I','M','1'),
fps,cvSize(frameW,frameH),isColor);
其它的編碼器代號包括: CV_FOURCC('P','I','M','1') = MPEG-1 codec CV_FOURCC('M','J','P','G') = motion-jpeg codec (does not work well) 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 若編碼器代號爲 -1,則運行時會彈出一個編碼器選擇框.
[編輯]
(2) 保持視頻文件:
IplImage* img = 0;
int nFrames = 50;
for(i=0;i<nFrames;i++){
cvGrabFrame(capture); // capture a frame
img=cvRetrieveFrame(capture); // retrieve the captured frame
// img = cvQueryFrame(capture);
cvWriteFrame(writer,img); // add the frame to the file
}
要查看所抓取到的幀畫面,能夠在循環中加入如下語句:
cvShowImage("mainWin", img);
key=cvWaitKey(20); // wait 20 ms
注意 cvWaitKey 參數應該不小於 20 ms,不然畫面的顯示可能出錯.
[編輯]
(3) 釋放視頻編寫器:
cvReleaseVideoWriter(&writer);ide