第一步:opencv打开摄像头并显示到qt界面上;
关键代码:
CvCapture *m_camera; //视频获取结构 作为视频获取函数的返回值
IplImage *m_imgFrame; //IplImage结构指针 存放每一帧的图像
//...
m_camera = cvCreateCameraCapture(0);
//...使用qt定时器定时抓取一帧
m_imgFrame = cvQueryFrame(m_camera);// 从摄像头中抓取并返回每一帧
//...处理一帧数据
//...转为qImage数据并显示
在用cvCreateCameraCapture(0)打开摄像头的时候,如果硬件设备为**多个摄像头**时请注意。opencv库里没有提供获取摄像头设备列表的函数接口。此时cvCreateCameraCapture(0)打开的不一定是你想要的设备。
**配置摄像头**参数:函数cvSetCaptureProperty();
cvSetCaptureProperty(m_camera,CV_CAP_PROP_FPS,25);
cvSetCaptureProperty(m_camera,CV_CAP_PROP_FOURCC,CV_FOURCC('M','J','P','G'));//CV_FOURCC('M','J','P','G')
cvSetCaptureProperty(m_camera, CV_CAP_PROP_FRAME_WIDTH , size.width);
cvSetCaptureProperty(m_camera, CV_CAP_PROP_FRAME_HEIGHT , size.height);
opencv默认摄像头分辨率为640*480如果没有特别需求以上参数可不必配置。
在界面显示时用到了opencv**图像缩放算法**参照http://www.cnblogs.com/wangguchangqing/p/4011892.html,感谢这个仁兄的分享,代码亲测可用。
第二步:存储摄像头视频到本地;
关键代码:
cv::VideoWriter *writer;
if(frameFlage==0){//第一帧,设置writer参数
QString str;
int w,h;
QDateTime time;
time = QDateTime::currentDateTime();
QString strBuffer= time.toString("yyyy-MM-dd-hh-mm");
w=m_imgFrame->width;
h=m_imgFrame->height;
strBuffer.append(QString::number(w));
strBuffer.append("#");
strBuffer.append(QString::number(h));
str.append("./cameraFile/");
str.append(strBuffer);
str.append(".avi");
writer->open(str.toLatin1().data(),CV_FOURCC('X','V','I','D'),25,cvSize(w,h));
frameFlage=1;
}else{
//cvGrabFrame(m_camera); // 抓取帧
//m_imgFrame1=cvRetrieveFrame(m_camera); // 恢复图像
// cvWriteFrame(writer,m_imgFrame); // 将帧添加入视频文件
writer->write(m_imgFrame);
}
存储操作强烈建议放到单独线程,笔者亲身被虐。刚开始仅仅是显示640*480像素的视频,没有出现卡顿的情形,就没有使用分线程操作。后来录制1080p直接卡出翔。笔者中间因为卡顿还突发奇想换了ffmpeg命令行模式进行录制摄像头视频,卡倒是不卡了,但是不能和opencv显示摄像头同时用。(同一个设备,不知道能不能同时被opencv喝ffmpeg使用),至于全部换成ffmpeg操作,暂时功力不够,不得不重新回到opencv写操作优化上。新建线程类,瞬间飞起来。
我只能说,好习惯需要慢慢养成。