视频流读取与视频帧处理

背景引言

视频信号是视觉信息的一个主要源头,它由按序列排放的图像组成,即帧(Frame)。本节主要介绍视频读取和对视频帧处理知识。

读取视频序列

为了处理视频序列,需要读取每一Frame.用c++类封装VideoProcessor类视频读取处理的代码:

class VideoProcessor{
private:
    VideoCapture caputure; //The OpenCV Video capture object
   
    void (*process)(Mat &,Mat &); // the callback function to be called for the 
                                  // processing of each frame
    bool callIt;
    
	string WindowNameInput;	//Input display windnow name
    string WindowNameOutput; //Output display window name
   
    int delay;
    long fnumber; // number of processed frames

    long frameToStop; // stop at this frame number
    bool stop;
public:
    VideoProcessor() : callIt(true),delay(0),fnumber(0),stop(false),frameToStop(-1){}
    void setFrameProcess(void (*process)(Mat &,Mat &)){
        this->process = process;
    }

    bool setInput(string filename){
        fnumber = 0;

        caputure.release ();
        return caputure.open (filename);
    }

    void displayInput(string wn){
        WindowNameInput = wn;
        namedWindow (WindowNameInput);
    }

    void displayOutput(string wn){
        WindowNameOutput = wn;
        namedWindow (WindowNameOutput);
    }
 
    void dontDisplay(){
        destroyWindow (WindowNameInput);
        destroyWindow (WindowNameOutput);
        WindowNameInput.clear ();
        WindowNameOutput.clear ();
    }

    void run(){
        Mat frame;
        Mat output;
        if(!isOpened()) return;
        stop = false;
        while(!isStopped()){
            if(!readNextFrame(frame)) break;
            if(WindowNameInput.length ()!=0) imshow (WindowNameInput,frame);

            if(callIt) process(frame,output);
            else output = frame;
            if(WindowNameOutput.length ()!=0) imshow (WindowNameOutput,output);
            
            if(delay>=0&&waitKey (delay)>=0) waitKey(0);
            
            if(frameToStop>=0&&getFrameNumber()==frameToStop) stopIt();
        }
    }
  
    void stopIt(){
        stop = true;
    }
   
    bool isStopped(){
        return stop;
    }
  
    bool isOpened(){
       return  caputure.isOpened ();
    }

    void setDelay(int d){
        delay = d;
    }
 
    bool readNextFrame(Mat &frame){
        return caputure.read (frame);
     }

    void CallProcess(){
        callIt = true;
    }
    void  dontCallProcess(){
        callIt = false;
    }
 
    void stopAtFrameNo(long frame){
        frameToStop = frame;
    }

    long getFrameNumber(){
        long fnumber = static_cast<long>(caputure.get ((CV_CAP_PROP_POS_FRAMES)));
        return fnumber;
    }

    double getFrameRate(){
        return caputure.get(CV_CAP_PROP_FPS);
    }
};
目前,OpenCV2.x中用于操作video文件的类基于ffmpeg.所以,无需像OpenCV1.x那样安装第三方解码软件转换器,才能读取视频信息

处理视频帧

处理视频主要是对于每个视频帧都应用一些处理函数。将自己的类中封装OpenCV的视频获取框架,同时可以指定每帧调用函数。作为一个视频帧处理函数,如:canny函数计算输入图像的Canny边缘。代码如下所示:

void canny(cv::Mat& img, cv::Mat& out) {
    if (img.channels()==3)
        cvtColor(img,out,CV_BGR2GRAY);
    Canny(out,out,100,200);
    threshold(out,out,128,255,cv::THRESH_BINARY_INV);
}
接着,定义一个video处理类,将与一个回调函数相关联。使用此类,将创建一个实例并指定输入的video文件,绑定回调函数,然后开始处理过程。代码如下所示:

 VideoProcessor processor;
    processor.setInput ("test.avi");
    processor.displayInput ("Input Video");
    processor.displayOutput ("Output Video");
    processor.setDelay (2000./processor.getFrameRate ());
 
    processor.setFrameProcess (canny );
    processor.run ();
实验结果,当输入视频的一 ,对应的输出 如图所示:
视频流读取与视频帧处理_第1张图片

参考资料

[1] Robert Laganière, " OpenCV 2 Computer Vision Application Programming Cookbook" ,Packt Publishing  2011.


关于Image Engineering & Computer Vision的更多讨论与交流,敬请关注本博和新浪微博songzi_tea.



你可能感兴趣的:(opencv,视频流读取,视频帧处理)