OpenCV2学习笔记之视频流读取与处理_第1页
OpenCV2学习笔记之视频流读取与处理_第2页
OpenCV2学习笔记之视频流读取与处理_第3页
OpenCV2学习笔记之视频流读取与处理_第4页
OpenCV2学习笔记之视频流读取与处理_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第OpenCV2学习笔记之视频流读取与处理目录前言一.读取视频序列二.处理视频帧OpenCV:打开摄像头获取视频流总结

前言

由于项目需要,计划实现九路视频拼接,因此必须熟悉OpenCV对视频序列的处理。视频信号处理是图像处理的一个延伸,所谓的视频序列是由按一定顺序进行排放的图像组成,即帧(Frame)。在这里,主要记录下如何使用Qt+OpenCV读取视频中的每一帧,之后,在这基础上将一些图像处理的算法运用到每一帧上(如使用Canny算子检测视频中的边缘)。

一.读取视频序列

OpenCV提供了一个简便易用的框架以提取视频文件和USB摄像头中的图像帧,如果只是单单想读取某个视频,你只需要创建一个cv::VideoCapture实例,然后在循环中提取每一帧。新建一个Qt控制台项目,直接在main函数添加:

#includeQCoreApplication

#includeopencv2/core/core.hpp

#includeopencv2/imgproc/imgproc.hpp

#includeopencv2/highgui/highgui.hpp

#includeQDebug

intmain(intargc,char*argv[])

QCoreApplicationa(argc,argv);

//读取视频流

cv::VideoCapturecapture("e:/BrokeGirls.mkv");

//检测视频是否读取成功

if(!capture.isOpened())

qDebug()"NoInputImage";

return1;

//获取图像帧率

doublerate=capture.get(CV_CAP_PROP_FPS);

boolstop(false);

cv::Matframe;//当前视频帧

cv::namedWindow("ExtractedFrame");

//每一帧之间的延迟

intdelay=1000/rate;

//遍历每一帧

while(!stop)

//尝试读取下一帧

if(!capture.read(frame))

break;

cv::imshow("ExtractedFrame",frame);

//引入延迟

if(cv::waitKey(delay)=0)

stop=true;

returna.exec();

}

(注意:要正确打开视频文件,计算机中必须安装有对应的解码器,否则cv::VideoCapture无法理解视频格式!)运行后,将出现一个窗口,播放选定的视频(需要在创建cv::VideoCapture对象时指定视频的文件名)。

二.处理视频帧

为了对视频的每一帧进行处理,这里创建自己的类VideoProcessor,其中封装了OpenCV的视频获取框架,该类允许我们指定每帧调用的处理函数。

首先,我们希望指定一个回调处理函数,每一帧中都将调用它。该函数接受一个cv::Mat对象,并输出处理后的cv::Mat对象,其函数签名如下:

voidprocessFrame(cv::Matimg,cv::Matout);

作为这样一个处理函数的例子,以下的Canny函数计算图像的边缘,使用时直接添加在mian文件中即可:

//对视频的每帧做Canny算子边缘检测

voidcanny(cv::Matimg,cv::Matout)

//先要把每帧图像转化为灰度图

cv::cvtColor(img,out,CV_BGR2GRAY);

//调用Canny函数

cv::Canny(out,out,100,200);

//对像素进行翻转

cv::threshold(out,out,128,255,cv::THRESH_BINARY_INV);

}

现在我们需要创建一个VideoProcessor类,用来部署视频处理模块。而在此之前,需要先另外创建一个类,即VideoProcessor内部使用的帧处理类。这是因为在面向对象的上下文中,更适合使用帧处理类而不是一个帧处理函数,而使用类可以给程序员在涉及算法方面有更多的灵活度(书上介绍的)。将这个内部帧处理类命名为FrameProcessor,其定义如下:

#ifndefFRAMEPROCESSOR_H

#defineFRAMEPROCESSOR_H

#includeopencv2/core/core.hpp

#includeopencv2/highgui/highgui.hpp

classFrameProcessor

public:

virtualvoidprocess(cv::Matinput,cv::Matoutput)=0;

#endif//FRAMEPROCESSOR_H

现在可以开始定义VideoProcessor类了,以下为videoprocessor.h中的内容:

#ifndefVIDEOPROCESSOR_H

#defineVIDEOPROCESSOR_H

#includeopencv2/core/core.hpp

#includeopencv2/imgproc/imgproc.hpp

#includeopencv2/highgui/highgui.hpp

#includeQDebug

#include"frameprocessor.h"

classVideoProcessor

private:

//创建视频捕获对象

cv::VideoCapturecapture;

//每帧调用的回调函数

void(*process)(cv::Mat,cv::Mat

//FrameProcessor接口

FrameProcessor*frameProcessor;

//确定是否调用回调函数的bool信号

boolcallIt;

//输入窗口的名称

std::stringwindowNameInput;

//输出窗口的名称

std::stringwindowNameOutput;

//延迟

intdelay;

//已处理的帧数

longfnumber;

//在该帧停止

longframeToStop;

//是否停止处理

boolstop;

//当输入图像序列存储在不同文件中时,可使用以下设置

//把图像文件名的数组作为输入

std::vectorstd::stringimages;

//图像向量的迭加器

std::vectorstd::string::const_iteratoritImg;

//得到下一帧

//可能来自:视频文件或摄像头

boolreadNextFrame(cv::Matframe)

if(images.size()==0)

returncapture.read(frame);

else{

if(itImg!=images.end())

frame=cv::imread(*itImg);

itImg++;

returnframe.data!=0;

public:

//默认设置digits(0),frameToStop(-1),

VideoProcessor():callIt(false),delay(-1),

fnumber(0),stop(false),

process(0),frameProcessor(0){}

//创建输入窗口

voiddisplayInput(std::stringwt);

//创建输出窗口

voiddisplayOutput(std::stringwn);

//不再显示处理后的帧

voiddontDisplay();

//以下三个函数设置输入的图像向量

boolsetInput(std::stringfilename);

//若输入为摄像头,设置ID

boolsetInput(intid);

//若输入为一组图像序列时,应用该函数

boolsetInput(conststd::vectorstd::stringimgs);

//设置帧之间的延迟

//0意味着在每一帧都等待按键响应

//负数意味着没有延迟

voidsetDelay(intd);

//返回图像的帧率

doublegetFrameRate();

//需要调用回调函数

voidcallProcess();

//不需要调用回调函数

voiddontCallProcess();

//设置FrameProcessor实例

voidsetFrameProcessor(FrameProcessor*frameProcessorPtr);

//设置回调函数

voidsetFrameProcessor(void(*frameProcessingCallback)(cv::Mat,cv::Mat

//停止运行

voidstopIt();

//判断是否已经停止

boolisStopped();

//是否开始了捕获设备?

boolisOpened();

//返回下一帧的帧数

longgetFrameNumber();

//该函数获取并处理视频帧

voidrun();

#endif//VIDEOPROCESSOR_H

然后,在videoprocessor.cpp中定义各个函数的功能:

#include"videoprocessor.h"

//创建输入窗口

voidVideoProcessor::displayInput(std::stringwt)

windowNameInput=wt;

cv::namedWindow(windowNameInput);

//创建输出窗口

voidVideoProcessor::displayOutput(std::stringwn)

windowNameOutput=wn;

cv::namedWindow(windowNameOutput);

//不再显示处理后的帧

voidVideoProcessor::dontDisplay()

cv::destroyWindow(windowNameInput);

cv::destroyWindow(windowNameOutput);

windowNameInput.clear();

windowNameOutput.clear();

//设置输入的图像向量

boolVideoProcessor::setInput(std::stringfilename)

fnumber=0;

//释放之前打开过的视频资源

capture.release();

images.clear();

//打开视频

returncapture.open(filename);

//若输入为摄像头,设置ID

boolVideoProcessor::setInput(intid)

fnumber=0;

//释放之前打开过的视频资源

capture.release();

images.clear();

//打开视频文件

returncapture.open(id);

//若输入为一组图像序列时,应用该函数

boolVideoProcessor::setInput(conststd::vectorstd::stringimgs)

fnumber=0;

//释放之前打开过的视频资源

capture.release();

//输入将是该图像的向量

images=imgs;

itImg=images.begin();

returntrue;

//设置帧之间的延迟

//0意味着在每一帧都等待按键响应

//负数意味着没有延迟

voidVideoProcessor::setDelay(intd)

delay=d;

//返回图像的帧率

doubleVideoProcessor::getFrameRate()

if(images.size()!=0)return0;

doubler=capture.get(CV_CAP_PROP_FPS);

returnr;

//需要调用回调函数

voidVideoProcessor::callProcess()

callIt=true;

//不需要调用回调函数

voidVideoProcessor::dontCallProcess()

callIt=false;

//设置FrameProcessor实例

voidVideoProcessor::setFrameProcessor(FrameProcessor*frameProcessorPtr)

//使回调函数无效化

process=0;

//重新设置FrameProcessor实例

frameProcessor=frameProcessorPtr;

callProcess();

//设置回调函数

voidVideoProcessor::setFrameProcessor(void(*frameProcessingCallback)(cv::Mat,cv::Mat))

//使FrameProcessor实例无效化

frameProcessor=0;

//重新设置回调函数

process=frameProcessingCallback;

callProcess();

//以下函数表示视频的读取状态

//停止运行

voidVideoProcessor::stopIt()

stop=true;

//判断是否已经停止

boolVideoProcessor::isStopped()

returnstop;

//是否开始了捕获设备?

boolVideoProcessor::isOpened()

returncapture.isOpened()||!images.empty();

//返回下一帧的帧数

longVideoProcessor::getFrameNumber()

if(images.size()==0)

//得到捕获设备的信息

longf=static_castlong(capture.get(CV_CAP_PROP_POS_FRAMES));

returnf;

else//当输入来自一组图像序列时的情况

returnstatic_castlong(itImg-images.begin());

//该函数获取并处理视频帧

voidVideoProcessor::run()

//当前帧

cv::Matframe;

//输出帧

cv::Matoutput;

//打开失败时

if(!isOpened())

qDebug()"Error!";

return;

stop=false;

while(!isStopped())

//读取下一帧

if(!readNextFrame(frame))

break;

//显示输出帧

if(windowNameInput.length()!=0)

cv::imshow(windowNameInput,frame);

//调用处理函数

if(callIt)

//处理当前帧

if(process)

process(frame,output);

elseif(frameProcessor)

frameProcessor-process(frame,output);

//增加帧数

fnumber++;

else

output=frame;

//显示输出帧

if(windowNameOutput.length()!=0)

cv::imshow(windowNameOutput,output);

//引入延迟

if(delay=0cv::waitKey(delay)=0)

stopIt();

//检查是否需要停止运行

if(frameToStop=0getFrameNumber()==frameToStop)

stopIt();

定义好视频处理类,它将与一个回调函数相关联。使用该类,可以创建一个实例,指定输入的视频文件,绑定回调函数,然后开始对每一帧进行处理,要调用这个视频处理类,只需在main函数中添加:

//定义一个视频处理类处理视频帧

//首先创建实例

VideoProcessorprocessor;

//打开视频文件

processor.setInput("e:/BrokeGirls.mkv");

//声明显示窗口

//分别为输入和输出视频

processor.displayInput("InputVideo");

processor.displayOutput("OutputVideo");

//以原始帧率播放视频

processor.setDelay(1000./process

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论