美文网首页
OpenCV视频篇——VideoCapture类和VideoWr

OpenCV视频篇——VideoCapture类和VideoWr

作者: WaitFoF | 来源:发表于2019-12-16 17:11 被阅读0次

    前面已经提到过一部分的视频读写:OpenCV--012:视频读写

    \color{#74d}{一、OpenCV视频I/O概述}

    来自:OpenCV视频I/O概述

    OpenCV视频I/O模块是一组用于读取和写入视频或图像序列的类和功能。

    基本上,该模块将cv :: VideoCapture和cv :: VideoWriter类作为2层接口提供给许多用作后端的视频I / O API。


    在这里插入图片描述
    • 某些后端,例如(DSHOW)Direct Show,Windows视频(VFW),Microsoft Media Foundation(MSMF),Video 4 Linux(V4L)等,是操作系统提供的视频I / O库的接口。
    • 其他一些后端,例如用于Kinect的OpenNI2,英特尔感知计算SDK,GStreamer,XIMEA相机API等,都是专有驱动程序或外部库的接口。

    notice:
    每个后端以不同的方式支持设备属性(cv::VideoCaptureProperties),或者可能根本不支持任何属性。

    运行时选择后端:
    OpenCV运行时自动选择并使用第一个可用的后端(apiPreference=cv::CAP_ANY);

    用于可以根据需要,选择要运行的后端。
    例如:

    1. 使用Dirtect Show作为后端从默认摄像头抓取:
      //声明一个捕获对象
      cv :: VideoCapture cap(0 + cv :: CAP_DSHOW);
      //或使用open指定apiPreference
      cap.open(0 + cv :: CAP_DSHOW);
      
    2. 如果要使用Direct Show作为后端从文件中抓取:
      //声明一个捕获对象
      cv :: VideoCapture cap(filename,cv :: CAP_DSHOW);
      //或使用open指定apiPreference
      cap.open(文件名,cv :: CAP_DSHOW);
      

    使用第三方驱动程序或照相机:
    许多工业相机或者某些视频I/O设备不提供操作系统的标准驱动程序接口。因此,不能再这些设备上直接使用VideoCapture或者VideoWriter。为了访问他们的设备,制造商提供了自己的C++ API和库。

    FFmpeg库:
    OpenCV可以使用FFmpeg库作为后端来记录,转换和流式传输音频和视频。FFMpeg是完整的交叉引用解决方案。如果在配置OpenCV时启用FFmpeg,则CMake将下载二进制文件并将其安装在OPENCV_SOURCE_CODE/3rdparty/ffmpeg/中。要在运行时使用FFMpeg,必须将FFMepg二进制文件与应用程序一起部署。

    \color{#74d}{二、VideoCapture结构体}

    VideoCapture结构体,可以读取文件视频、网页视频流和摄像头的数据。

    ❶先看一下构造函数:
    • 1、默认构造函数:
    VideoCapture() 
    
    • 2、使用API首选项打开视频文件或捕获设备或IP视频流以进行视频捕获。
    VideoCapture (const String &filename, int apiPreference=CAP_ANY)
    

    \color{red}{filename可选值}

    • 影片档案名称(例如video.avi)
    • 图片序列(例如img_%02d.jpg,将读取像这样的样本img_00.jpg, img_01.jpg, img_02.jpg, ...)
    • 视频流的网址(例如protocol://host:port/script_name?script_params|auth)。请注意,每个视频流或IP摄像机源均具有其自己的URL方案。请参考源流的文档以了解正确的URL。

      \color{red}{apiPreference:}
      首选使用的Capture API后端。如果有多个可用的读取器实现,则可以用于实施特定的读取器实现。
      设置读取的摄像头编号,默认CAP_ANY=0,自动检测摄像头。多个摄像头时,使用索引0,1,2,...进行编号调用摄像头。 apiPreference = -1时单独出现窗口,选取相应编号摄像头。
    • 3、打开相机进行视频拍摄。
    VideoCapture (int index, int apiPreference=CAP_ANY)
    

    \color{red}{index参数:}
    要打开的视频捕获设备的ID。要使用默认后端打开默认摄像头,只需传递0。
    ——> 当apiPreference为CAP_ANY时,使用camera_id + domain_offset(CAP_ *)向后兼容有效
    \color{red}{apiPreference:}
    首选使用的Capture API后端。如果有多个可用的读取器实现,则可用于实施特定的读取器实现:例如cv :: CAP_DSHOW或cv :: CAP_MSMF或cv :: CAP_V4L。

    \color{blue}{通常使用 `bool isOpened()`判断是否打开视频或摄像头成功。}

    VideoCaptureAPIs的取值:OpenCV视频篇——VideoCaptureAPIs

    ❷ VideoCapture中其他函数
    • 1、返回特殊的VIdeoCApture属性信息。
    virtual double  get (int propId) const
    

    \color{red}{propId:}
    来自cv :: VideoCaptureProperties的属性标识符(例如cv :: CAP_PROP_POS_MSEC,cv :: CAP_PROP_POS_FRAMES,...)或视频I / O API后端的附加标志中的一个。

    指定属性的值。查询VideoCapture实例使用的后端不支持的属性时,返回值0 。

    读/写属性涉及许多层。在此链上可能会发生一些意外的结果。
    VideoCapture- > API 后端 ->操作系统->设备驱动程序->设备硬件
    返回的值可能与设备实际使用的值不同,或者可以使用设备相关的规则(例如,步骤或百分比)对其进行编码。有效行为取决于设备驱动程序和API后端。

    VideoCaptureProperties的取值:OpenCV视频篇——VideoCaptureProperties

    • 2、在VideoCapture中设置属性。
    virtual bool cv::VideoCapture::set(int propId, double   value ) 
    

    \color{red}{ propId:}
    来自cv :: VideoCaptureProperties的属性标识符(例如cv :: CAP_PROP_POS_MSEC,cv :: CAP_PROP_POS_FRAMES,...)或视频I / O API后端的附加标志中的一个
    \color{red}{value:}
    属性的值。
    \color{red}{返回值:}
    如果该属性由VideoCapture实例使用的后端支持,则返回true。

    \color{blue}{即使返回true,也不能确保捕获设备已接受该属性值。}

    • 3、返回使用的后端API名称。
    String  getBackendName () const
    

    流应先打开。

    • 4、从视频文件或捕获设备中获取下一帧。
    virtual bool    grab ()
    

    该方法/函数从视频文件或摄像机中获取下一帧,并在成功的情况下返回true(非零)。

    该功能的主要用途是在多相机环境中,尤其是在相机没有硬件同步的情况下。也就是说,您为每个摄像机调用VideoCapture :: grab(),然后调用较慢的方法VideoCapture :: retrieve()解码并从每个摄像机获取帧。这样,消除了去马赛克或运动jpeg压缩等方面的开销,并且从不同摄像机检索到的帧将在时间上更近。

    \color{red}{返回:}
    true (非零)(如果成功)。

    另外,当连接的摄像机是多头摄像机(例如,立体摄像机或Kinect设备)时,从中检索数据的正确方法是先调用VideoCapture :: grab(),然后再调用VideoCapture :: retrieve()使用不同的channel参数值一次或多次。

    • 5、如果视频捕获已经初始化,则返回true。
    virtual bool    isOpened () const
    

    \color{blue}{如果先前对VideoCapture构造函数或VideoCapture :: open()调用成功,则该方法返回true。}

    • 6、打开视频文件或捕获设备或IP视频流以进行视频捕获。
    virtual bool    open (const String &filename, int apiPreference=CAP_ANY)
     
    virtual bool    open (int index, int apiPreference=CAP_ANY)
    

    参数与构造函数VideoCapture相同,此处不再重复。

    \color{red}{返回:}
    true:如果文件已成功打开

    \color{blue}{该方法首先调用VideoCapture :: release以关闭已打开的文件或摄像机。}

    • 7、抓取,解码并返回下一个视频帧。
    virtual bool    read (OutputArray image)
    

    该方法/函数在一次调用中将VideoCapture :: grab()和VideoCapture :: retrieve()组合在一起。这是读取视频文件或从解码捕获数据并返回刚抓取的帧的最方便的方法。如果没有抓取任何帧(相机已断开连接,或者视频文件中没有其他帧),则该方法返回false,并且该函数返回空图像(使用cv :: Mat,使用Mat :: empty()进行测试) 。

    \color{red}{image:}
    视频帧将返回此处。如果没有抓取帧,image将为空。
    \color{red}{返回:}
    false:如果没有抓取帧

    • 8、关闭视频文件或捕获设备。
    virtual void    release ()
    

    该方法由随后的VideoCapture :: open和VideoCapture析构函数自动调用。

    \color{blue}{C函数还会取消分配内存并清除* capture指针。}

    • 9、解码并返回抓取的视频帧。
    virtual bool    retrieve (OutputArray image, int flag=0)
    

    该方法解码并返回刚抓取的帧。如果没有抓取任何帧(摄像机已断开连接,或者视频文件中没有其他帧),则该方法返回false,并且该函数返回空图像(使用cv :: Mat,使用Mat :: empty()测试它)。

    \color{red}{image:}
    视频帧将返回此处。如果没有抓取帧,image将为空。
    \color{red}{flag:}
    它可以是帧索引或驱动程序特定标志。
    \color{red}{返回值:}
    false 如果没有抓取帧。

    • 10、流运算符读取下一个视频帧。
    virtual VideoCapture &  operator>> (Mat &image)
     
    virtual VideoCapture &  operator>> (UMat &image)
    
    ❸读取视频基本步骤
    1、读取视频

    一般采用构造函数进行视频或者摄像头的预处理。

    2、下一帧

    读取下一帧:

    • 使用重载运算符>>
    • 使用read 、grab 、retrieve函数

    视频帧读取的方式:

    读取方式 使用方式
    cap.read(frame) 结合grab和retrieve的功能,抓取下一帧并解码
    cap.grap() 从设备或视频获取下一帧,获取成功返回true否则false
    cap.retrieve(frame) 在grab后使用,对获取到的帧进行解码,也返回true或false

    \color{blue}{retrieve速度比grab慢很多,有时可以通过grab跳过不需要的帧,而不需要用read解码每一帧。}

    3、释放

    release()在使用完后进行手动释放VideoCapture对象。

    int main(int, char**)
    {
        Mat frame;
        //--- INITIALIZE VIDEOCAPTURE
        VideoCapture cap;
        // open the default camera using default API
        // cap.open(0);
        // OR advance usage: select any API backend
        int deviceID = 0;             // 0 = open default camera
        int apiID = cv::CAP_ANY;      // 0 = autodetect default API
        // open selected camera using selected API
        cap.open(deviceID + apiID);
        // check if we succeeded
        if (!cap.isOpened()) {
            cerr << "ERROR! Unable to open camera\n";
            return -1;
        }
        //--- GRAB AND WRITE LOOP
        cout << "Start grabbing" << endl
            << "Press any key to terminate" << endl;
        for (;;)
        {
            // wait for a new frame from camera and store it into 'frame'
            cap.read(frame);
            // check if we succeeded
            if (frame.empty()) {
                cerr << "ERROR! blank frame grabbed\n";
                break;
            }
            // show live and wait for a key with timeout long enough to show images
            imshow("Live", frame);
            if (waitKey(5) >= 0)
                break;
        }
        // the camera will be deinitialized automatically in VideoCapture destructor
        return 0;
    }
    

    \color{#74d}{ 三、VideoWriter类}

    ❶构造函数

    • 1、默认构造函数:
    VideoWriter ()
    
    • 2、构造函数
    VideoWriter (const String &filename, int fourcc, double fps, Size frameSize, bool isColor=true)
    

    \color{red}{filename:}
    输出视频文件的名称。
    \color{red}{fourcc:}
    用于压缩帧的编解码器的4个字符的代码。
    例如:
    VideoWriter :: fourcc('P','I','M','1')是MPEG-1编解码器;
    VideoWriter :: fourcc('M','J','P','G ')是动态jpeg编解码器等。
    可以在FOURCC页面的“ 视频编解码器”中获取代码列表。带有MP4容器的FFMPEG后端本机使用其他值作为fourcc代码:请参见ObjectType,因此您可能会从OpenCV收到有关fourcc代码转换的警告消息。
    \color{red}{fps:}
    创建的视频流的帧率。
    \color{red}{frameSize:}
    视频帧的大小。
    \color{red}{isColor:}
    如果它不为零,则编码器将期望并编码彩色帧,否则它将与灰度帧一起使用(仅Windows当前支持该标志)。

    • 3、构造函数
    VideoWriter (const String &filename, int apiPreference, int fourcc, double fps, Size frameSize, bool isColor=true)
    

    ❷ 成员函数

    • 1、返回指定的VideoWriter属性
    virtual double  get (int propId) const
    

    \color{red}{propId:}
    来自cv :: VideoWriterProperties的属性标识符或视频I / O API后端的其他标志之一。
    \color{red}{返回值:}
    指定属性的值。查询VideoWriter实例使用的后端不支持的属性时,返回值0 。

    • 2、 在VideoWriter中设置属性。
    virtual bool    set (int propId, double value)
    

    \color{red}{propId:}
    来自cv :: VideoWriterProperties的属性标识符或视频I / O API后端的其他标志之一。
    \color{red}{value:}
    属性的值。

    \color{red}{返回值:}
    true:如果该属性由VideoWriter实例使用的后端支持。

    • 3、 返回使用的后端API名称。。
    String  getBackendName () const
    

    注意:流应打开。

    • 4、 如果视频编写器已成功初始化,则返回true。
    virtual bool    isOpened () const
    
    • 5、 初始化或重新初始化视频编写器。
    virtual bool open(const String &filename,int fourcc, double fps,Size frameSize,bool isColor=true)
    
    bool open (const String &filename, int apiPreference, int fourcc, double fps, Size frameSize, bool isColor=true)
    

    参数与构造函数VideoWriter :: VideoWriter中的参数相同。

    \color{red}{返回值:}
    true:视频编写器是否已成功初始化

    \color{blue}{该方法首先调用VideoWriter :: release以关闭已打开的文件。}

    • 6.1、 流运算符写入下一个视频帧。
    virtual VideoWriter &operator<<(const Mat &image)
    virtual VideoWriter &operator<<(const UMat &image)
    
    • 6.2、 写入下一个视频帧。
    virtual void    write (InputArray image)
    

    该功能/方法将指定的图像写入视频文件。它的大小必须与打开视频编写器时指定的大小相同。

    \color{red}{image:}
    待写的帧。通常,彩色图像应采用BGR格式。

    • 7、 关闭视频编写器。
    virtual void    release ()
    

    此方法由随后的VideoWriter :: open和VideoWriter析构函数自动调用。

    相关文章

      网友评论

          本文标题:OpenCV视频篇——VideoCapture类和VideoWr

          本文链接:https://www.haomeiwen.com/subject/tepdnctx.html