视频处理
[编辑]
1、从视频流中捕捉一帧画面
[编辑]
(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);

注意由视频流捕捉器得到的图像是由捕捉器分配和释放内存的,不需要单独对图像进行释放内存的操作。
[编辑]
2、获取/设置视频流信息
[编辑]
(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);

注意此方法定位并不准确。
[编辑]
3、保存视频文件
[编辑]
(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);