处理视频帧

我们的目标是对于每个视频帧都应用一些处理函数,我们将自己的类中封装OpenCV的视频获取框架,它将允许我们指定每帧调用的处理函数。
下面的例子中的回调处理函数为Canny边缘提取

// ProcessFrame.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <opencv/highgui.h>
#include <opencv2/imgproc/imgproc.hpp>

using namespace cv;
using namespace std;

//定义视频处理类
class VideoProcessor
{
private:
    VideoCapture capture;//OpenCV视频捕获对象
    void(*canny)(Mat &,Mat &);//每帧调用的回调函数
    bool callIt;//确定是否调用回调函数的bool变量
    string windowNameInput;//输入窗口的名称
    string windowNameOutput;//输出窗口的名称
    int delay;//延迟
    long fnumber;//已处理的帧数
    long frameToStop;//在该帧数停止
    bool stop;//是否停止处理
    double rate;
public:
    VideoProcessor():callIt(true),delay(0),fnumber(0),stop(false),frameToStop(-1){}
    bool setInput(string filename);
    void displayInput(string wn);
    void displayOutput(string wn);
    void dontDisplay();
    void setFrameProcessor(void (*canny)(Mat &,Mat &));
    void run();
    void stopIt();
    bool isStopped();
    bool isOpened();
    void setDelay(int d);
    bool readNextFrame(Mat &frame);
    long getFrameNumber();
    double getFrameRate();
};

//设置视频文件的名称
bool VideoProcessor::setInput(string filename)
{
    fnumber=0;
    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()
{ 
    destroyWindow(windowNameInput);
    destroyWindow(windowNameOutput);
    windowNameInput.clear();
    windowNameOutput.clear();
}

//设置回调函数,即canny
void VideoProcessor::setFrameProcessor(void (*frameProcessingCallback)(Mat &,Mat &))
{
    canny=frameProcessingCallback;
}

//停止运行
void VideoProcessor::stopIt()
{
    stop=true;
}

//是否已停止?
bool VideoProcessor::isStopped()
{
    return stop;
}

//是否开始了捕获设备?
bool VideoProcessor::isOpened()
{
    return capture.isOpened();
}
//设置帧间的延迟
//0意味着在每帧都等待用户按键
//负数意味着没有延迟
void VideoProcessor::setDelay(int d)
{
    delay=d;
}

//得到下一帧
//可能是:视频文件或摄像头
bool VideoProcessor::readNextFrame(Mat &frame)
{
    return capture.read(frame);
}

//返回下一帧的帧数
long VideoProcessor::getFrameNumber()
{
    long fnumber=static_cast<long>(capture.get(CV_CAP_PROP_POS_FRAMES));//得到捕获设备的信息
    return fnumber;
}

//获取帧率
double VideoProcessor::getFrameRate()
{
    double rate=static_cast<double>(capture.get(CV_CAP_PROP_FPS));
    return rate;
}

//获取并处理序列帧
void VideoProcessor::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)//调用处理函数
        {
            canny(frame,output);//处理当前帧
            fnumber++;//增加帧数
        }
        else
        {
            output=frame;
        }
        if(windowNameOutput.length()!=0)//显示输出帧
            imshow(windowNameOutput,output);
        if(delay>=0&&waitKey(delay)>=0)//引入延迟
            stopIt();
        if(frameToStop>=0&&getFrameNumber()==frameToStop)//检查是否需要停止运行
            stopIt();
    }
}

void canny(Mat &img,Mat &out)
{
    if(img.channels()==3)//灰度转换
    {
        cvtColor(img,out,CV_BGR2GRAY);
    }
    Canny(out,out,100,200);//计算canny边缘
    threshold(out,out,128,255,THRESH_BINARY_INV);//反转图像
}

int _tmain(int argc, _TCHAR* argv[])
{
    VideoProcessor processor;
    processor.setInput("walk.avi");//打开视频文件
    processor.displayInput("Current Frame");//声明显示窗口
    processor.displayOutput("Output Frame");
    processor.setDelay(1000./processor.getFrameRate());//以原始帧率播放视频
    processor.setFrameProcessor(canny);//设置处理回调函数canny
    processor.run();//开始处理过程
    return 0;
}

边缘提取

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值