OpenCV练习1:使用自定义类实现视频和帧处理的接口
来源:互联网 发布:西南交大网络教育网站 编辑:程序博客网 时间:2024/06/05 20:27
main文件
// 程序摘要:视频读取及自定义视频类处理/* 读取视频序列; 自定义视频处理类VideoProcessor:可以处理视频和独立的图像序列,前者用以前的帧处理函数(回调函数process), 后者用自定义的帧处理类(FrameProcessor类接口即对象->process方法);其中用到了canny函数,其中涉及把每帧图像彩色转灰度和用Canny和 threshold函数*/// 写入视频帧类VideoWriter,在VideoProcessor的方法中应用写入类实例的成员函数,也分为处理视频和独立的图像序列即用到成员函数重载// 以上描述为:程序后半段用自定义视频处理类封装视频捕捉类、帧处理类和视频帧写入类// 2016年10月 Created by孙立波(Visual Studio 2013+OpenCV2.4.9)#include <opencv2\opencv.hpp> #include <iostream>#include <string>#include <sstream>#include <vector>using namespace cv;using namespace std;#include "videoprocessor.h"void draw(const cv::Mat& img, cv::Mat& out) { img.copyTo(out); cv::circle(out, cv::Point(100, 100), 5, cv::Scalar(255, 0, 0), 2);}// processing function此函数定义用于真正的图像处理,为回调函数在main中注册后每次执行的函数处理,注意canny是封装了Canny函数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(){ // 打开视频文件 cv::VideoCapture capture("D:\\workplace\\opencv_training\\bike.avi"); //cv::VideoCapture capture("http://www.laganiere.name/bike.avi"); // 核实视频文件是否却是打开 if (!capture.isOpened()) return 1; // Get the frame rate double rate = capture.get(CV_CAP_PROP_FPS); std::cout << "Frame rate: " << rate << "fps" << std::endl; bool stop(false); cv::Mat frame; // current video frame cv::namedWindow("Extracted Frame"); // Delay between each frame // corresponds to video frame rate int delay = 1000 / rate;//视频播放按原始帧率,可设置使视频快进或倒退 long long i = 0; std::string b = "bike"; std::string ext = ".bmp"; // for all frames in video抽取视频帧保存到同一工程目录下!!!!!!!!! while (!stop) { // read next frame if any if (!capture.read(frame)) break; cv::imshow("Extracted Frame", frame); std::string name(b); // note: some MinGW compilers generate an error for this line // this is a compiler bug // try: std::ostringstream ss; ss << i; name+= ss.rdbuf(); i++; // name+=std::to_string(i++); std::ostringstream ss; ss << i; name += ss.str(); i++; name += ext; std::cout << name << std::endl; cv::imwrite(name, frame); // introduce a delay // or press key to stop if (cv::waitKey(delay) >= 0)//当超过指定时间,没有按键盘时,返回值-1 stop = true; } // Close the video file capture.release(); cv::waitKey(); //########################################################################################### // Now using the VideoProcessor class用自定义视频处理类封装视频捕捉类、帧处理类和视频帧写入类 // Create instance VideoProcessor processor; // Open video file processor.setInput("D:\\workplace\\opencv_training\\bike.avi"); // Declare a window to display the video注册窗口内存预备显示用 processor.displayInput("Input Video");//彩色图像 processor.displayOutput("Output Video");//灰度图像 // Play the video at the original frame rate processor.setDelay(1000. / processor.getFrameRate()); // 此为注册回调函数Set the frame processor callback function*****设置类的实例的回调函数方法为main前声明的canny()函数!!! processor.setFrameProcessor(canny); // output a video //传入值-1代表不采用与输入一致的编解码方式,而是提供MFC供选择,15代表帧的速率 processor.setOutput("D:\\workplace\\opencv_training\\bike1.avi", -1, 15); // stop the process at this frame,只处理前51帧并保存到内存 processor.stopAtFrameNo(51); // Start the process processor.run(); cv::waitKey(); return 0;}
自定义头文件
#if !defined VPROCESSOR#define VPROCESSOR#include <iostream>#include <iomanip>//流控制头文件#include <sstream>#include <string>#include <vector>#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>// The frame processor interfaceclass FrameProcessor {public: // processing method virtual void process(cv::Mat &input, cv::Mat &output) = 0;};class VideoProcessor {private: // the OpenCV video capture object cv::VideoCapture capture; // the callback function to be called // for the processing of each frame void(*process)(cv::Mat&, cv::Mat&); // the pointer to the class implementing // the FrameProcessor interface FrameProcessor *frameProcessor; // a bool to determine if the // process callback will be called bool callIt; // Input display window name std::string windowNameInput; // Output display window name std::string windowNameOutput; // delay between each frame processing int delay; // number of processed frames long fnumber; // stop at this frame number long frameToStop; // to stop the processing bool stop; // vector of image filename to be used as input std::vector<std::string> images; // image vector iterator std::vector<std::string>::const_iterator itImg; // the OpenCV video writer object cv::VideoWriter writer; // output filename std::string outputFile; // current index for output images int currentIndex; // number of digits in output image filename int digits; // extension of output images std::string extension; // to get the next frame // could be: video file; camera; vector of images bool readNextFrame(cv::Mat& frame) { if (images.size() == 0) return capture.read(frame); else { if (itImg != images.end()) { frame = cv::imread(*itImg); itImg++; return frame.data != 0; } return false; } } // to write the output frame // could be: video file or images void writeNextFrame(cv::Mat& frame) { if (extension.length()) { // then we write images std::stringstream ss; ss << outputFile << std::setfill('0') << std::setw(digits) << currentIndex++ << extension; cv::imwrite(ss.str(), frame); } else { // then write video file writer.write(frame); } }public: // Constructor setting the default values VideoProcessor() : callIt(false), delay(-1), fnumber(0), stop(false), digits(0), frameToStop(-1), process(0), frameProcessor(0) {} // set the name of the video file bool setInput(std::string filename) { fnumber = 0; // In case a resource was already // associated with the VideoCapture instance capture.release(); images.clear(); // Open the video file return capture.open(filename); } // set the camera ID bool setInput(int id) { fnumber = 0; // In case a resource was already // associated with the VideoCapture instance capture.release(); images.clear(); // Open the video file return capture.open(id); } // set the vector of input images bool setInput(const std::vector<std::string>& imgs) { fnumber = 0; // In case a resource was already // associated with the VideoCapture instance capture.release(); // the input will be this vector of images images = imgs; itImg = images.begin(); return true; } // set the output video file // by default the same parameters than input video will be used bool setOutput(const std::string &filename, int codec = 0, double framerate = 0.0, bool isColor = true) { outputFile = filename; extension.clear(); if (framerate == 0.0) framerate = getFrameRate(); // same as input char c[4]; // use same codec as input if (codec == 0) { codec = getCodec(c); } // Open output video return writer.open(outputFile, // filename codec, // codec to be used framerate, // frame rate of the video getFrameSize(), // frame size isColor); // color video? } // set the output as a series of image files // extension must be ".jpg", ".bmp" ... bool setOutput(const std::string &filename, // filename prefix const std::string &ext, // image file extension int numberOfDigits = 3, // number of digits int startIndex = 0) { // start index // number of digits must be positive if (numberOfDigits<0) return false; // filenames and their common extension outputFile = filename; extension = ext; // number of digits in the file numbering scheme digits = numberOfDigits; // start numbering at this index currentIndex = startIndex; return true; } // set the callback function that will be called for each frame void setFrameProcessor(void(*frameProcessingCallback)(cv::Mat&, cv::Mat&)) { // invalidate frame processor class instance frameProcessor = 0; // this is the frame processor function that will be called process = frameProcessingCallback; callProcess(); } // set the instance of the class that implements the FrameProcessor interface void setFrameProcessor(FrameProcessor* frameProcessorPtr) { // invalidate callback function process = 0; // this is the frame processor instance that will be called frameProcessor = frameProcessorPtr; callProcess(); } // stop streaming at this frame number void stopAtFrameNo(long frame) { frameToStop = frame; } // process callback to be called void callProcess() { callIt = true; } // do not call process callback void dontCallProcess() { callIt = false; } // to display the input frames void displayInput(std::string wn) { windowNameInput = wn; cv::namedWindow(windowNameInput); } // to display the processed frames void displayOutput(std::string wn) { windowNameOutput = wn; cv::namedWindow(windowNameOutput); } // do not display the processed frames void dontDisplay() { cv::destroyWindow(windowNameInput); cv::destroyWindow(windowNameOutput); windowNameInput.clear(); windowNameOutput.clear(); } // set a delay between each frame // 0 means wait at each frame // negative means no delay void setDelay(int d) { delay = d; } // a count is kept of the processed frames long getNumberOfProcessedFrames() { return fnumber; } // return the size of the video frame cv::Size getFrameSize() { if (images.size() == 0) { // get size of from the capture device int w = static_cast<int>(capture.get(CV_CAP_PROP_FRAME_WIDTH)); int h = static_cast<int>(capture.get(CV_CAP_PROP_FRAME_HEIGHT)); return cv::Size(w, h); } else { // if input is vector of images cv::Mat tmp = cv::imread(images[0]); if (!tmp.data) return cv::Size(0, 0); else return tmp.size(); } } // return the frame number of the next frame long getFrameNumber() { if (images.size() == 0) { // get info of from the capture device long f = static_cast<long>(capture.get(CV_CAP_PROP_POS_FRAMES)); return f; } else { // if input is vector of images return static_cast<long>(itImg - images.begin()); } } // return the position in ms double getPositionMS() { // undefined for vector of images if (images.size() != 0) return 0.0; double t = capture.get(CV_CAP_PROP_POS_MSEC); return t; } // return the frame rate double getFrameRate() { // undefined for vector of images if (images.size() != 0) return 0; double r = capture.get(CV_CAP_PROP_FPS); return r; } // return the number of frames in video long getTotalFrameCount() { // for vector of images if (images.size() != 0) return images.size(); long t = capture.get(CV_CAP_PROP_FRAME_COUNT); return t; } // get the codec of input video int getCodec(char codec[4]) { // undefined for vector of images if (images.size() != 0) return -1; union { 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]; return returned.value; } // go to this frame number bool setFrameNumber(long pos) { // for vector of images if (images.size() != 0) { // move to position in vector itImg = images.begin() + pos; // is it a valid position? if (pos < images.size()) return true; else return false; } else { // if input is a capture device return capture.set(CV_CAP_PROP_POS_FRAMES, pos); } } // go to this position bool setPositionMS(double pos) { // not defined in vector of images if (images.size() != 0) return false; else return capture.set(CV_CAP_PROP_POS_MSEC, pos); } // go to this position expressed in fraction of total film length bool setRelativePosition(double pos) { // for vector of images if (images.size() != 0) { // move to position in vector long posI = static_cast<long>(pos*images.size() + 0.5); itImg = images.begin() + posI; // is it a valid position? if (posI < images.size()) return true; else return false; } else { // if input is a capture device return capture.set(CV_CAP_PROP_POS_AVI_RATIO, pos); } } // Stop the processing void stopIt() { stop = true; } // Is the process stopped? bool isStopped() { return stop; } // Is a capture device opened? bool isOpened() { return capture.isOpened() || !images.empty(); } // to grab (and process) the frames of the sequence void run() { // current frame cv::Mat frame; // output frame cv::Mat output; // if no capture device has been set if (!isOpened()) return; stop = false; while (!isStopped()) { // read next frame if any if (!readNextFrame(frame)) break; // display input frame if (windowNameInput.length() != 0) cv::imshow(windowNameInput, frame); // calling the process function or method if (callIt) { // process the frame if (process) process(frame, output); else if (frameProcessor) frameProcessor->process(frame, output); // increment frame number fnumber++; } else { output = frame; } // write output sequence if (outputFile.length() != 0) writeNextFrame(output); // display output frame if (windowNameOutput.length() != 0) cv::imshow(windowNameOutput, output); // introduce a delay if (delay >= 0 && cv::waitKey(delay) >= 0) stopIt(); // check if we should stop if (frameToStop >= 0 && getFrameNumber() == frameToStop) stopIt(); } }};#endif
阅读全文
0 0
- OpenCV练习1:使用自定义类实现视频和帧处理的接口
- opencv学习系列:视频读取及自定义视频类处理
- opencv视频流的读取和处理
- OpenCV视频的处理
- 使用opencv在Qt中实现卡通化视频处理
- OpenCV处理视频序列的类
- Opencv使用自带的CameraGLSurfaceView实现相机帧处理
- opencv 视频和图片处理的一些不同
- 基于OPENCV的视频图像处理算法和应用
- OpenCV之处理视频帧
- Android中使用自定义的VideoController和MediaPlayer实现视频的窗口和全屏播放
- OPENCV视频处理,对视频帧进行复制并重新用帧复制和合成新视频
- 郭克华手机编程教学视频----我的练习源码(4)命令按钮监听1:使用匿名类实现
- Java接口和实现的异常处理
- OpenCV 课后练习-利用TrackBar实现视频的暂停与播放
- opencv视频处理和检测学习总结
- 基于opencv的简单视频处理类示例
- OpenCv学习笔记(五):使用VideoCapture类函数实现视频的播放
- 配置 struts-2.3.dtd 但一直无法提示
- 二叉树的广度优先搜索
- 【POJ】2378
- 人类社会与其发展规律
- 文档流
- OpenCV练习1:使用自定义类实现视频和帧处理的接口
- 树莓派更新源
- 代码面试指南学习记录-第一章02
- Onethink上传服务器后登录不了的问题
- GDAL裁剪tif图(保留经纬度)
- java 选择排序
- Linux 高级编程
- Java并发包中CyclicBarrier的工作原理、使用示例
- linux下SPI驱动