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
原创粉丝点击