zoukankan      html  css  js  c++  java
  • OpenCV的视频读取

    现在找一个能拍摄视频的设备真是太容易了。结果大家都用视频来代替以前的序列图像。视频可能由两种形式得到,一个是像网络摄像头那样实时视频流,或者由其他设备产生的压缩编码后的视频文件。幸运的是,OpenCV可以使用相同的C++类、用同一种方式处理这些视频信息。在接下来的教程里你将学习如何使用摄像头或者视频文件。

    • 如何打开和读取视频流
    • 两种检查相似度的方法:PSNR和SSIM

    如何读取一个视频流(摄像头或者视频文件)?

            总的来说,视频捕获需要的所有函数都集成在 VideoCapture C++ 类里面。虽然它底层依赖另一个FFmpeg开源库,但是它已经被集成在OpenCV里所以你不需要额外地关注它的具体实现方法。你只需要知道一个视频由一系列图像构成,我们用一个专业点儿的词汇来称呼这些构成视频的图像:“帧”(frame)。此外在视频文件里还有个参数叫做“帧率”(frame rate)的,用来表示两帧之间的间隔时间,帧率的单位是(帧/秒)。这个参数只和视频的播放速度有关,对于单独的一帧图像来说没有任何用途。

           你需要先定义一个 VideoCapture 类的对象来打开和读取视频流。具体可以通过 constructor 或者通过 open 函数来完成。如果使用整型数当参数的话,就可以将这个对象绑定到一个摄像机,将系统指派的ID号当作参数传入即可。例如你可以传入0来打开第一个摄像机,传入1打开第二个摄像机,以此类推。如果使用字符串当参数,就会打开一个由这个字符串(文件名)指定的视频文件。

    结构体 CvCapture

      CvCapture 是一个结构体,用来保存图像捕获所需要的信息。 opencv提供两种方式从外部捕获图像:

    一种是从摄像头中,
    一种是通过解码视频得到图像。
         两种方式都必须从第一帧开始一帧一帧的按顺序获取,因此每获取一帧后都要保存相应的状态和参数。
         比如从视频文件中获取,需要保存视频文件的文件名,相应的解码器类型,下一次如果要获取将需要解码哪一帧等。
     这些信息都保存在CvCapture结构中,每获取一帧后,这些信息都将被更新,获取下一帧需要将新信息传给获取的 api接口
    cvCreateFileCapture(char*name)
    通过输入要读取的avi文件的路径,然后,该函数返回一个指向 CvCapture结构体的指针。
    cvQueryFrame(capture)
    输入一个CvCapture 类型的指针,该函数主要功能是将视频文件的下一帧加载到内存。与 cvLoadImage的不同之处是,该函数不重新分配内存空间。
    C=cvWaitKey(33)
    当前帧被显示后,等待 33毫秒。如果用户触发了一个按键, c会被设置成这个按键的 ASCII码,否则会被设置成 -1。
    cvWaitKey(33) 在此处的另外一个作用是,控制帧率。
    cvReleaseCapture(&capture)
    释放为 CvCapture结构体开辟的内存空间
    关闭打开的 AVI文件相关的文件句柄
    VideoCapture类
    用于从视频文件或摄像机捕获视频.该类提供了用于从摄像机捕获视频或者读取视频文件的C++ API。
    
    注意:在C API中使用黑盒子结构CvCapture来代替VideoCapture。
    
    构造函数
    VideoCapture::VideoCapture()
    VideoCapture::VideoCapture(const string& filename)//filename – 文件名
    VideoCapture::VideoCapture(int device)//device – 捕获视频的编号. 如果只有一个设备,默认编号为0
    open函数
    打开视频文件或捕获设备进行视频捕获
    bool VideoCapture::open(const string& filename)//filename – 文件名
    bool VideoCapture::open(int device)//device – 捕获视频的编号. 如果只有一个设备,默认编号为0
    isopened函数
    如果视频捕获已经初始化,则返回true。
    bool VideoCapture::isOpened()
    release函数
    关闭视频文件或捕获设备
    void VideoCapture::release()
    grap函数
    从视频文件或捕获设备中捕获下一帧
    bool VideoCapture::grab()
    retrieve函数
    解码并返回抓取的视频帧
    bool VideoCapture::retrieve(Mat& image, int channel=0)
    read函数
    抓取,解码并返回下一个视频帧
    bool VideoCapture::read(Mat& image)
    get函数
    返回指定的VideoCapture属性
    double VideoCapture::get(int propId)//propId - 属性标识符
    CV_CAP_PROP_POS_MSEC - 视频文件的当前位置(以毫秒为单位)或视频捕获时间戳。
    CV_CAP_PROP_POS_FRAMES - 下一个要解码/捕获的帧的基于0的索引。
    CV_CAP_PROP_POS_AVI_RATIO - 视频文件的相对位置:0 - 电影的开始,1 - 电影的结束。
    CV_CAP_PROP_FRAME_WIDTH - 视频流中帧的宽度。
    CV_CAP_PROP_FRAME_HEIGHT - 视频流中帧的高度。
    CV_CAP_PROP_FPS - 帧速率。
    CV_CAP_PROP_FOURCC - 编解码器的4个字符代码。
    CV_CAP_PROP_FRAME_COUNT - 视频文件中的帧数。
    CV_CAP_PROP_FORMAT -  retrieve()返回的Mat对象的格式。
    CV_CAP_PROP_MODE - 指示当前捕获模式的后端特定值。
    CV_CAP_PROP_BRIGHTNESS - 图像的亮度(仅适用于相机)。
    CV_CAP_PROP_CONTRAST - 图像的对比度(仅适用于相机)。
    CV_CAP_PROP_SATURATION - 图像的饱和度(仅适用于相机)。
    CV_CAP_PROP_HUE - 图像的色调(仅适用于摄像机)。
    CV_CAP_PROP_GAIN - 图像的增益(仅适用于摄像机)。
    CV_CAP_PROP_EXPOSURE - 曝光(仅适用于相机)。
    CV_CAP_PROP_CONVERT_RGB - 指示图像是否应转换为RGB的布尔标志。
    CV_CAP_PROP_WHITE_BALANCE - 目前不支持
    CV_CAP_PROP_RECTIFICATION - 立体相机的校正标志(注意:目前仅由DC1394 v 2.x后端支持)
    set函数
    设置VideoCapture中的属性。
    bool VideoCapture::set(int propertyId, double value)//propId - 属性标识符,同get;value - 属性的值。
    
    

      

    简单的读写视频程序
    #include<opencv2/opencv.hpp>
    using namespace cv;
    
    
    void main() {
        VideoCapture cap;
        cap.open("E:\VS2015Opencv\vs2015\project\video\01.avi"); //打开视频,以上两句等价于VideoCapture cap("E://01.avi");
    
                               //cap.open("http://www.laganiere.name/bike.avi");//也可以直接从网页中获取图片,前提是网页有视频,以及网速够快
        if (!cap.isOpened())//如果视频不能正常打开则返回
            return ;
        Mat frame;
        while (1)
        {
            cap >> frame;//等价于cap.read(frame);
            if (frame.empty())//如果某帧为空则退出循环
                break;
            imshow("video", frame);
            waitKey(20);//每帧延时20毫秒
        }
        cap.release();//释放资源
    }

    #include<opencv2/opencv.hpp>
    #include<iostream>
    using namespace cv;
    using namespace std;
    
    void main() {
        VideoCapture cap;
        cap.open("E:\VS2015Opencv\vs2015\project\video\01.avi"); 
    
        if (!cap.isOpened())
            return;
    
        int width = cap.get(CV_CAP_PROP_FRAME_WIDTH);  //帧宽度
        int height = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //帧高度
        int frameRate = cap.get(CV_CAP_PROP_FPS);  //帧率 x frames/s
        int totalFrames = cap.get(CV_CAP_PROP_FRAME_COUNT); //总帧数
    
        cout << "视频宽度=" << width << endl;
        cout << "视频高度=" << height << endl;
        cout << "视频总帧数=" << totalFrames << endl;
        cout << "帧率=" << frameRate << endl;
        
    
        Mat frame;
        while (1)
        {
            cap >> frame;//等价于cap.read(frame);
            if (frame.empty())
                break;
            imshow("video", frame);
            if (waitKey(33) != 255)
                break;
        }
        cap.release();
    }

     

    将左边的waitkey(33)改成右边的if(waitKey(20)>0)break;

     程序会直接跳出,不放视频

    opencv学习之等待按键事件-waitKey函数

    waitkey(20) 如果不按键的时候是返回 oxff,这个无符号就是255,有符号就是-1

    windows vs 的环境默认了这个为非符号数 即255,而opencv的新手书中,往往作者环境会认为是-1

    解决方案:把原始代码中循环读取帧的

    if (waitKey(33)>=0)break;

    改为

    if (waitKey(33) != 255)break;

    或者把waitkey的返回值用有符号数去读取。

    参考:opencv学习之路(2)、读取视频,读取摄像头

  • 相关阅读:
    解决undefined reference to `__poll_chk@GLIBC_2.16' 错误
    交叉编译总结 libosscore.a libcurl.a libmysqlclient.a
    APUE环境配置
    UDT中epoll对CLOSE状态的处理
    查看ld搜索路径
    linux shell 比较文件夹内容 diff
    交互式makefile
    linux shell取文本最后一行
    linux 查看静态库,动态库是32位还是64位
    python学习day4之路
  • 原文地址:https://www.cnblogs.com/fcfc940503/p/11323464.html
Copyright © 2011-2022 走看看