主要包括以下内容:

      1.使用的主要函数的说明。

      2.两个实例:视频读取和显示。搭建视频读取和处理框架,调用canny函数提取边缘并显示。

      3.一些注意事项和代码说明。

一.使用的主要函数

1.延时函数cv::waitKey

函数原型

          intwaitKey(int delay=0)

参数说明:

          1). delay<=0代表相对无限等待一个按键;delay>0的时候,函数延时delay毫秒(milliseconds)。但延时是相对的最小延时,        延时不会超过操作系统的a minimumtime between switching threads。在延时的时候,如有按键读入,那么返回按键的ASCII编          码;否则返回-1;

          2).至少应该有一个窗口正在使用(Active)。如果有多个,那么延时的对象是所有有效的窗口。

使用范例:

          1).if(waitKey(200)>=0) return true;//如果在200毫秒内有按键时间,则返回

          2).if (char(waitKey(200))=='q') return true;//如果在200毫秒内按下了‘q’键,则返回

2.返回视频文件的性质函数VideoCapture::get()

        视频文件的性质包括比如帧率,下一帧的序列号等等

函数原型:C++: doubleVideoCapture::get(int propId)

参数说明:

        参数为实际为枚举类型,如下图

opencv得到当前时间 opencv获取视频时长_canny边缘提取

使用范例

           VideoCapture capture(“traffic.avi”);

           Long count=capture.get(CV_CAP_PROP_FRAME_COUNT)//返回视频文件的帧总数。

3.判断视频文件是否打开成功函数VideoCapture::Isopen()

二.使用实例

1.实例1:基本视频文件的读取和显示


// VideoCapture.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include"opencv2/core/core.hpp"
#include"opencv2/highgui/highgui.hpp"
#include"iostream"
using namespace std;
using namespace cv;
int _tmain(int argc, _TCHAR* argv[])
{
	VideoCapture capture("traffic.avi");
	if(!capture.isOpened())
		return true;
	double rate=capture.get(CV_CAP_PROP_FPS);
	int delay=1000/rate;
	bool stop=false;
	Mat cframe;
	namedWindow("视频获取框",2);
	while(!stop)
	{
		if(!capture.read(cframe))
			break;
		imshow("视频获取框",cframe);
		if(waitKey(delay)>=0)
			stop=true;
	}
	capture.release();
	return 0;
}


2.实例2:搭建视频文件读取处理显示框架,调用canny算子提取边缘


//VideoProc.h

#include"opencv2/core/core.hpp"
#include"opencv2/highgui/highgui.hpp"
#include "cv.h"
using namespace std;
using namespace cv;
class VideoProc{
	VideoCapture capture;//视频文件指针
	string InputWindow,OutputWindow;//输入输出窗口名
	void(*process)(Mat&,Mat&);//回调处理函数指针,指向返回类型为void参数为(Mat&,Mat&)的函数
	long Fnumber;//已经处理的帧数合计
	long FrameToStop;//需要停止的帧序号
	bool callIt;//是否调用回调处理函数标志位,true->call , false->donnt call
	bool stop_flag;//是否停止处理标准位,true->stop , false->donnt stop
	int delay;//延时参数
public:
	VideoProc():process(NULL),Fnumber(0),FrameToStop(-1),callIt(true),stop_flag(false),delay(0){}
   
	/*******************参数设置/初始化函数************************/
	bool InputVideo(const string);//读取视频
	void setProcess(void (*)(Mat&,Mat&));//设置回调函数
	void Window_ShowInput(const string);//创建原始视频显示窗口
    void Window_ShowOutput(const string);//创建处理过的视频显示窗口
	void dontDisplay(void);//不再显示处理后的帧
	long getNextFrame();//返回下一帧的序号

	/********************处理过程控制函数**************************/
	void run(void);

	double getFrameRate(){return capture.get(CV_CAP_PROP_FPS);}//返回每秒显示的帧数
	void setStopFlag(bool flag){stop_flag=flag;}//停止整个过程运行标志位设置
	void setDelay(int d){delay=d;}//设置延迟参数
	void setcallProcesss(bool flag){callIt=flag;}//是否调用回调函数,不调用回调函数输出未经处理的视频文件
	void stopAtFrameNumber(long frame){FrameToStop=frame;}//停止在特定帧设置
	bool readNextFrame(Mat& frame){return capture.read(frame);}//读取下一帧
};
bool VideoProc::InputVideo(const string filename)//打开视频文件
{
	Fnumber=0;
	capture.release();
	return capture.open(filename);
}
void VideoProc::setProcess(void(*freamProccessingCallback)(Mat&,Mat&))//传递回调函数地址
{
	process=freamProccessingCallback;
}
void VideoProc::Window_ShowInput(const string filename)//创建原始视频显示窗口
{
	InputWindow=filename;
	namedWindow(InputWindow,2);
}
void VideoProc::Window_ShowOutput(const string filename)//创建处理过的视频显示窗口
{
	OutputWindow=filename;
	namedWindow(OutputWindow,2);
}
void VideoProc::dontDisplay()
{
	destroyWindow(InputWindow);
	destroyWindow(OutputWindow);
	InputWindow.clear();
    OutputWindow.clear();
}
long VideoProc::getNextFrame()//返回下一帧的序号
{
	long fsquence=static_cast
   
   
    
    (capture.get(CV_CAP_PROP_POS_FRAMES));
	return fsquence;
}
void VideoProc::run(void)
{
	Mat CurrentFrame,OutputFrame;//分别为当前帧和输出帧
	if(!capture.isOpened()) return;
	long FrameCount=static_cast
    
    
     
     (capture.get(CV_CAP_PROP_FRAME_COUNT))-1;//视频文件帧总数
	while(!stop_flag)
	{
		if(!readNextFrame(CurrentFrame))//读取下一帧不成功
			break;
		if(InputWindow.length()!=0)//字符串的长度不为0代表已经有窗口创建
			imshow(InputWindow,CurrentFrame);
		if(callIt)
		{process(CurrentFrame,OutputFrame);
			Fnumber++;}
		else
			OutputFrame=CurrentFrame;
	   if(OutputWindow.length()!=0)
			imshow(OutputWindow,OutputFrame);
	   if((delay>=0&&waitKey(delay)>=0))
		   setStopFlag(true);//有任意按键按下则停止整个处理过程
	   if(FrameToStop>=0&&FrameToStop<=FrameCount&&getNextFrame()==FrameToStop)//到达设定需要暂停的帧,始终等待按键按下
			waitKey(0);
	}
}

//VideoProc.cpp
#include "stdafx.h"
#include"iostream"
#include"VideoProc.h"
void canny(Mat& in,Mat& out)
{
	if(in.channels()==3) cvtColor(in,out,CV_BGR2GRAY);//转变为灰度图像,即3通道转变为1通道
	Canny(out,out,100,200);//计算Canny边缘
	threshold(out,out,128,255,THRESH_BINARY_INV);//反转图像
}
int _tmain(int argc, _TCHAR* argv[])
{
	VideoProc sv;//定义对象
	sv.InputVideo("traffic.avi");//视频读取
	sv.Window_ShowInput("inputWindow");//创建原始视频显示窗口
	sv.Window_ShowOutput("outputWindow");//创建处理过的视频显示窗口
	sv.setDelay(1000./sv.getFrameRate());//设置延迟参数,设置为"0"表示每帧均需要用户按键,
	                                                          //1000./sv.getFrameRate()表示此时的播放速率和原始视频的频率相同
	sv.setProcess(canny);//帧处理函数调用接口
	sv.stopAtFrameNumber(25);//在25帧处暂停
	sv.setcallProcesss(false);//不调用处理函数
	sv.run();//视频处理过程控制函数
	return 0;
}


三.注意事项和代码说明

但是请注意:在函数声明时形参也被设置同类型的函数指针。

也就是说,视频处理的实质是单张图片的处理;而视频处理的多态性体现在函数指针指向不同的处理函数。

         2.实例二实现的目标如下:设置某个帧index即帧序列号(本文中为25),处理过程将在这里暂停,但是按任意键后,处理过程将继续。在整个处理过程中,按下任意键,处理过程将结束。

并不是意味在命令行窗口或者DOS窗口输出某个字符,而是当光标停留在所创建的窗口上的时候的按键事件。

         4.成员函数setcallProcesss(false);设置是否调用处理函数标志位。若设为false->callIt=0,意味输入输出文件一样,即视频文件没有经过处理。设为true->callIt=1,则输出文件经过了处理。

         5.注意延时参数设置,假设源视频文件的帧率为FPS,设置延时参数1000/FPS,则经过处理后的视频以相同的帧率播放,注意延时参数为毫秒级,故分子为1000。


@工程及源码点击此处下载