在前一篇中已经实现了读取摄像头并实时显示,本文将重要讲述如何把它保存为视频文件。
关键代码
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自带的驱动比较弱,拿不到。
有一个笨办法,就是手动计算。在取一帧画面前后计时,算出其帧率。