OpenCv打开摄像头,显示图像,保存视频
OpenCv中的opencv_highgui244.lib库用于图像的输入输出(我这里用到的是2.4.4版本的OpenCv)。
OpenCv的库通常包含C导出函数及C++封装导出类,即是同一个功能既可以用C函数实现,也可以用
C++类实现,本文采用的是C函数实现;
highgui库的C及C++实现分别对应highgui_c.h和highgui.hpp头文件。
highgui库的主要功能有:读取图像文件(多种格式),输出图像文件(多种格式),显示图像,读取
视频文件,输出视频文件,打开摄像头设备,设置读取视频的属性等等。。。
#include "opencv2\opencv.hpp"//只要包含了该头文件及下面命名空间,所有的opencv头文件都被包含;
using namespace cv;
int main(int argc, char *argv[])
{
//打开摄像头设备,系统中的摄像头设备从“0”开始编号,PID越小,编号越小;
//参数也可以是一个视频文件的路径,例“video.avi”,此时打开的视频文件;
CvCapture *capture = cvCreateCameraCapture(0);
//攫取一帧,成功则判断打开成功。
int Rsl = cvGrabFrame(capture);
if (Rsl == 0)
{
return 0;
}
//设置视频流格式为MJPG(默认的格式为YUY2,分辨率1280*720的帧率只有8,MJPG可达25)。
//此设置必须在设置宽高之前才会有效,原因不明;
cvSetCaptureProperty(capture, CV_CAP_PROP_FOURCC, CV_FOURCC('M', 'J', 'P', 'G'));
//设置视频帧宽高;
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 1280);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 720);
//新建录制视频文件的对象,这里设定为输出.avi格式,帧率25,分辨率1280*720;
CvVideoWriter *writer = cvCreateVideoWriter("out.avi", CV_FOURCC('x','v','i','d'),25,cvSize(1280, 720));
int count = 0;
IplImage *pFrame;
char key;
double fps = 0;
while (1)
{
//获取系统当前时间总量(ms)
double time = (double)getTickCount();
//接收“Esc”键输入,用作跳出死循环;
key = (char)cvWaitKey(5);
if (key == 27)
{
break;
}
//获取一个帧;
pFrame = cvQueryFrame(capture);
if (pFrame)
{
//输出图像文件;
//char path[256] = {0};
//sprintf(path, "img\\%d.jpg", count);
//cvSaveImage(path, pFrame);
//新建命名为“123”的窗口,显示获取到的帧图像;
cvShowImage("123", pFrame);
//输出视频文件;
//cvWriteFrame(writer, pFrame);
//计算帧率
time = ((double)getTickCount() - time) /getTickFrequency();
fps += 1.0 / time;
count++;
printf("%.2f\n", fps/count);
}
}
//释放视频录制对象;只有释放了该对象视频才会正常生成;
cvReleaseVideoWriter(&writer);
//释放图像输入对象;
cvReleaseCapture(&capture);
return 0;
}
以上代码需包含opencv_core244.lib及opencv_highgui244.lib两个库
(此处用的是2.4.4版本)
注意问题:
1. 帧率fps :
最高帧率由设备决定,实际帧率由程序决定;
最高帧率:摄像头设备打开后会不断地刷新当前图像,这个刷新的频率即是最高帧率,在设备的硬件已经决定。
不同的摄像头可能不同,有的是25帧,有的可能只有5帧;
实际帧率:假设设备的最高帧率为25帧,那么每帧的时间间隔为40ms,当程序读取处理每帧耗费的时间超过
40ms时,帧率就会低于25帧;假设程序读取一帧并进行处理耗费100ms,则实际帧率为10。
关于实际帧率的计算,必须从获取获取一个帧开始,到获取下一帧结束。如果需要对图像进行复杂处理,而又
不希望影响到帧率,可以先把图像保存在内存中,另开线程进行处理。经验证,显示图像及保存视频文件函数
耗时较少,对帧率基本没有影响,保存图像文件函数耗时较多,会对帧率有影响。
2. 视频功能:
如果用到视频相关的功能,还需要在程序目录下添加“opencv_ffmpeg244.dll”,
此库没有.lib,所以编译时不需要包含。如果缺少这个库,则视频功能无效,但程序不会报任何错误,
所以很难找到问题所在。
3. 设备PID:
每个设备都有独一无二的PID,可以在设备管理中查看硬件ID获知。
当有多个usb摄像头设备时,以PID进行区分,PID越小,编号则越小,编号从0开始。但有一个例外,
就是笔记本会内置的摄像头设备编号是最小的。
如何查询当前所有的摄像头设备PID,并通过直接输入PID号打开相应的摄像头呢?这里就需要用到
Directshow,这个会在另一篇文章《Directshow获取摄像头信息,打开摄像头设备》中讲述。