视频加载、处理、输出-----opencv2.0学习笔记4
2013-01-05 20:32
387 查看
一、加载播放视频
#include "stdafx.h" using namespace std; using namespace cv; int main() { //下面两种方法都可以打开视频 VideoCapture capture("../1.avi"); /*2、VideoCapture capture; capture.open("../1.avi");*/ if(!capture.isOpened()) return 1; double rate = capture.get(CV_CAP_PROP_FPS); bool stop(false); Mat frame; namedWindow("Extracted Frame"); //这个delay的单位是ms,若是秒,则delay为1/rate。 //rate为每秒播放的帧数 int delay = 1000/rate; //用于设置直接播放哪一帧 double position= 0.0; capture.set(CV_CAP_PROP_POS_FRAMES, position); while(!stop) { //以下三种方法都可以读取视频 if(!capture.read(frame)) break; /*2、capture>>frame;*/ /*3、capture.grab(); capture.retrieve(frame);*/ imshow("Extracted Frame",frame); if(waitKey(delay) >= 0) stop = true;//当delay==0时,将会暂停在该帧,不再执行下去,若不是0,则会等待键盘的消息输入,则结束 } //关闭视频文件,但是不是必须的,VideoCapture构造函数会默认调用它 capture.release(); }
二、对视频读入、处理、输出进行的封装
头文件代码:
#pragma once using namespace cv; class VideoProcessor { private://用于打开处理视频 //opencv 视频捕捉对象 VideoCapture capture; //回调函数将调用每帧处理函数 void (*process)(Mat&,Mat&); //是否调用回调函数的开关 bool callIt; //输入视频的播放窗口名字 string windowNameInput; //输入视频的播放窗口名字 string windowNameOutput; //播放每帧之间的暂停间隔 int delay; //已处理的帧数 long fnumber; //停止在某一帧 long frameToStop; //停止处理的开关 bool stop; //存储获得的视频每帧 Mat image; public: //设置回调函数,用于处理帧 void setFrameProcessor( void (*frameProcessingCallback)(Mat&,Mat&)) { process = frameProcessingCallback; } //打开一个视频文件 bool setInput(string filename); //创建一个窗口显示输入帧 void displayInput(string wn); //创建一个窗口显示输出帧 void displayOutput(string wn); //不显示帧 void dontDisplay(void); //抓取或处理帧序列 void run(void); //捕捉设备是否打开 bool isOpened(){ return capture.isOpened() || !images.empty();} //是否停止处理 bool isStopped(){ return stop; } //停止处理 void stopIt(){ stop = true; } //从视频或摄像头或图片文件读取下一帧 bool readNextFrame(Mat& frame); //设置播放延时 void setDelay(int d){ delay = d;} //设置调用回调函数 void callProcess(){ callIt = true; } //设置不调用回调函数 void dontCallProcess(){ callIt = false;} //设置停留在某帧 void stopAtFrameNo(long frame){ frameToStop = frame;} //返回视频总帧数 long getFrameNumber(void); //返回输入视频的帧频 long getFrameRate(){ return capture.get(CV_CAP_PROP_FPS); } private://用于输出视频或图片文件 //opencv用于视频输出类对象 VideoWriter writer; //输出文件名 string outputFile; //输出图片的当前索引值 int currentIndex; //输出图像的数字编号的位数 int digits; //扩展名 string extension; //保存图片文件名 vector<string> images; //遍历图片vector的迭代器 vector<string>::const_iterator itImg; public: //输出视频文件以原视频相同的参数 //还不能正确得到输入视频的codec格式,只能在codec==-1时,输出视频 bool setOutput(const string& filename, int codec=-1, double framerate=0.0, bool isColor=true); //用于输出每一帧 void writeNextFrame(Mat& frame); //用于以图片格式输出 bool setOutput(const string &filename,const string &ext,int numberOfDigits=3, int startIndex=0); //获得输入视频的编码格式 int getCodec(char codec[4]); //获得图片大小 cv::Size getFrameSize() { cv::Size S ; return S = Size((int) capture.get(CV_CAP_PROP_FRAME_WIDTH), //获取输入尺寸 (int) capture.get(CV_CAP_PROP_FRAME_HEIGHT)); } public: VideoProcessor(void); ~VideoProcessor(void); //设置输入图片向量 bool setInput(const vector<string>& imgs); };
相应cpp文件:
#include "StdAfx.h" #include "VideoProcessor.h" VideoProcessor::VideoProcessor(void): callIt(true), delay(0), fnumber(0), stop(false), frameToStop(-1), currentIndex(0), digits(0) { } VideoProcessor::~VideoProcessor(void) { } bool VideoProcessor::setInput(string filename) { fnumber = 0; //万一该VideoCapture对象已经关联了一个资源 capture.release(); //images.clear(); //打开视频文件 return capture.open(filename); } void VideoProcessor::displayInput(string wn) { windowNameInput = wn; namedWindow(windowNameInput); } void VideoProcessor::displayOutput(string wn) { windowNameOutput = wn; namedWindow(windowNameOutput); } void VideoProcessor::dontDisplay(void) { destroyWindow(windowNameInput); destroyWindow(windowNameOutput); windowNameInput.clear(); windowNameOutput.clear(); } void VideoProcessor::run(void) { //当前帧 Mat frame; //输出帧 Mat output; //判断是否打开成功 if(!isOpened()) return; stop = false; while(!isStopped()) { //若存在视频下一帧,则读取 if(!readNextFrame(frame)) break; //将当前帧存于image中 image = frame; //frame.copyTo(image); //显示输入帧 if(windowNameInput.length() != 0) imshow(windowNameInput,frame); //调用处理函数 if(callIt) { process(frame,output); fnumber++; }else{ output = frame; } //**写输出序列 if(outputFile.length() != 0) writeNextFrame(output); //显示输出帧 if(windowNameOutput.length() != 0) imshow(windowNameOutput,output); //延时 if(delay >= 0 && waitKey(delay) >= 0) stopIt(); if(frameToStop >= 0 && getFrameNumber() == frameToStop) stopIt(); } } bool VideoProcessor::readNextFrame(Mat& frame) { if(images.size() == 0) return capture.read(frame); else{ if(itImg != images.end()) { frame = imread(*itImg); itImg++; return frame.data != 0; }else{ return false; } } } long VideoProcessor::getFrameNumber(void) { long fnumber = static_cast<long>(capture.get(CV_CAP_PROP_POS_FRAMES)); return fnumber; } bool VideoProcessor::setOutput(const string& filename, int codec, double framerate, bool isColor) { outputFile = filename; extension.clear(); if(framerate == 0.0) framerate = getFrameRate(); char c[4]; //使用与输出视频相同的编码方式 if(codec == 0) { codec = getCodec(c); } writer.open(outputFile, codec=-1, framerate, getFrameSize(), isColor); if(writer.isOpened()) std::cout<<"dai kai cheng gong"<<std::endl; return true; } void VideoProcessor::writeNextFrame(Mat& frame) { if(extension.length()) { std::stringstream ss; //构成输出文件名 ss<<outputFile<<std::setfill('0') <<std::setw(digits) <<currentIndex++<<extension; imwrite(ss.str(),frame); }else//否则以视频格式写出 { writer.write(frame); } } bool VideoProcessor::setOutput(const string &filename,//文件前缀 const string& ext,//图片文件的扩展名 int numberOfDigits,//数据位 int startIndex) //开始索引值 { //数字必须为正 if(numberOfDigits<0) return false; //文件名及其扩展名 outputFile = filename; extension = ext; //输出图片的编号 digits = numberOfDigits; //图片数字编号的起始值 currentIndex = startIndex; return true; } int VideoProcessor::getCodec(char codec[4]) { // if(images.size() != 0) return -1; union{//4-char编码的数据结构 int value; char code[4]; }returned; //获得编码方式 returned.value = static_cast<int>( capture.get(CV_CAP_PROP_FOURCC)); //获得四个字符 codec[0] = returned.code[0]; codec[1] = returned.code[1]; codec[2] = returned.code[2]; codec[3] = returned.code[3]; /*std::cout << "Codec: " << codec[0] << codec[1] << codec[2] << codec[3] << std::endl;*/ return returned.value; } bool VideoProcessor::setInput(const vector<string>& imgs) { fnumber = 0; capture.release(); //将输入图片放入iamges中 images = imgs; itImg = images.begin(); return true; }
主函数对这个类的引用:
#include "stdafx.h" #include "VideoProcessor.h" using namespace std; using namespace cv; void canny(cv::Mat& img, cv::Mat& out) { // Convert to gray if (img.channels()==3) cv::cvtColor(img,out,CV_BGR2GRAY); // Compute Canny edges cv::Canny(out,out,100,200); // Invert the image cv::threshold(out,out,128,255,cv::THRESH_BINARY_INV); } int main() { VideoProcessor processor; processor.setInput("../1.avi"); processor.displayInput("Current Frame"); processor.displayOutput("Output Frame"); processor.setDelay(1000./processor.getFrameRate()); processor.setFrameProcessor(canny); processor.setOutput("../laneout.avi"); //processor.setOutput("../laneout",".bmp"); processor.stopAtFrameNo(300); processor.run(); }
代码注释:输出视频和输出图片一次只能设置一个。具体应用时,对处理函数的形式进行修改,使其适合相应程序的要求。
相关文章推荐
- openCV 视频读取、处理、输出操作 代码实例
- opencv 处理视频并使用Qt窗口作为输出
- OpenCV-Python learning-2.视频、相机简单处理
- zedboard中使用opencv对视频进行处理
- OpenCV处理视频的常用函数
- linux 下vlc读取rtsp视频,opencv处理
- OpenCV成长之路4:加载一个视频并且显示
- python opencv 入门 加载视频 (2)
- 【Python+OpenCV】视频流局部区域像素值处理-一种特征提取方法
- Opencv中的Bug(实现读入一个彩色视频文件并以灰度格式输出这个视频文件,学习opencv例2-10)
- openCV视频处理与图像转换
- opencv-视频处理-实时的前景检测-Vibe算法
- OpenCV中,将一个彩色视频文件以灰度格式输出
- Opencv 视频处理
- Python-OpenCV 图像与视频处理
- 【OP001】opencv强大的视频图形图像处理
- 利用Hadoop和opencv进行处理视频的原理
- Opencv3.0-python的那些事儿:(九)、Opencv关于如何读取大量视频帧进行处理的方法
- Linux的opencv教程之加载一段视频
- openCV 视频平滑处理 小程序