zoukankan      html  css  js  c++  java
  • OpenCV3 视频读写 cv::VideoCapture和cv::VideoWriter详解

    OpenCV3和OpenCV2类似,视频的读、写操作,分别通过cv::VideoCapture和cv::VideoWriter两个类来实现。

    1、视频的读取操作cv::VideoCapture

    cv::VideoCapture既支持视频文件的读取,也支持从摄像机中视频的读取。cv::VideoCapture对象的创建方式有以下三种:

    1     cv::VideoCapture capture(
    2     const string& filename, // 输入文件名
    3     );
    4     cv::VideoCapture capture(
    5     int device // 视频捕捉设备 id
    6     );
    7     cv::VideoCapture capture();

    第一种方式是从文件(.MPG或.AVI格式)中读取视频,对象创建以后,OpenCV将会打开文件并做好准备读取它,如果打开成功,我们将可以开始读取视频的帧,并且cv::VideoCapture的成员函数isOpened()将会返回true(建议在打开视频或摄像头时都使用该成员函数判断是否打开成功)。
    第二种方式是从摄像机中读取视频,这种情况下,我们会给出一个标识符,用于表示我们想要访问的摄像机,及其与操作系统的握手方式。对于摄像机而言,这个标志符就是一个标志数字——如果只有1个摄像机,那么就是0,如果系统中有多个摄像机,那么只要将其向上增加即可。标识符另外一部分是摄像机域(camera domain),用于表示摄像机的类型,这个域值可以是下面任一预定义常量。

    以这种方式创建视频捕获对象时,我们所传递的标识符是域索引和摄像机索引的和。例如:

    cv::VideoCapture capture(cv::CAP_IEEE1394 + 1);

    这个例子中cv::VideoCapture将尝试打开第2个(编号从0开始)1394摄像机。多数情况下,由于我们只有一个摄像机,因此没必要指定摄像机的域,此时使用cv::CAP_ANY是一种高效的方式(也即是0,所以不用特意指定)。
    第三种方式仅仅创建一个捕获对象,而不提供任何关于打开的信息。创建以后通过成员函数open()来设定打开的信息。open()操作也有以上两种方式。

    1     cv::VideoCapture cap;
    2     cap.open( "my_video.avi" );

    将视频帧读取到cv::Mat矩阵中,有两种方式:一种是read()操作;另一种是 “>>”操作。

    1     cv::Mat frame;
    2     cap.read(frame); //读取方式一
    3     cap >> frame; //读取方式二

    下面是读取视频并显示的示例代码:

     1 #include <opencv2/opencv.hpp>
     2 #include <iostream>
     3  
     4 void video_capture_test()
     5 {
     6     cv::VideoCapture capture("test.mp4");
     7  
     8     if (!capture.isOpened())
     9     {
    10         std::cout << "Read video Failed !" << std::endl;
    11         return;
    12     }
    13  
    14     cv::Mat frame;
    15     cv::namedWindow("video test");
    16  
    17     int frame_num = capture.get(cv::CAP_PROP_FRAME_COUNT);
    18     std::cout << "total frame number is: " << frame_num << std::endl;
    19  
    20     for (int i = 0; i < frame_num - 1; ++i)
    21     {
    22         capture >> frame;
    23         //capture.read(frame); 第二种方式
    24         imshow("video test", frame);
    25         if (cv::waitKey(30) == 'q')
    26         {
    27             break;
    28         }
    29     }
    30  
    31     cv::destroyWindow("video test");
    32     capture.release();
    33     return;
    34 }

    上面的代码,我们使用了cv::VideoCapture的成员函数get()并设定标识cv::CAP_PROP_FRAME_COUNT获取了读取视频的帧总数。同样,我们可以指定其他标识,来获取读取视频或摄像头的其他属性。另外,我们也可以使用成员函数set(),设定相应属性的值。cv::VideoCapture中提供的属性标识如下图所示。

    2、视频的写操作cv::VideoWriter

    cv::VideoWriter对象的创建有两种方式,第一种是使用构造函数的形式,第二种使用open()的方式,具体如下:

     1     cv::VideoWriter out(
     2         const string& filename, // 输入文件名
     3         int fourcc, // 编码形式,使用 CV_FOURCC()宏
     4         double fps, // 输出视频帧率
     5         cv::Size frame_size, // 单帧图片的大小
     6         bool is_color = true // 如果是false,可传入灰度图像 
     7     );
     8     
     9     cv::VideoWriter out;
    10     out.open(
    11         "my_video.mpg", //输出文件名
    12         CV_FOURCC('D','I','V','X'), // MPEG-4 编码
    13         30.0, // 帧率 (FPS)
    14         cv::Size( 640, 480 ), // 单帧图片分辨率为 640x480
    15         true // 只输入彩色图
    16     );

    同样,向创建后的cv::VideoWriter对象写入图像也有两种方式,即write()操作和“<<”操作:

    1     cv::VideoWriter::write(
    2         const Mat& image // 写入图像作为下一帧
    3     );
    4     
    5     my_video_writer << my_frame;
  • 相关阅读:
    报错:Failed to create BuildConfig class
    emulator control无法使用问题
    the import android cannot be resolved
    报错:init: Could not find wglGetExtensionsStringARB!
    Android SDK升级后报错error when loading the sdk 发现了元素 d:skin 开头无效内容
    Eclipse Android环境搭建
    android中导入低版本project可能会遇到的编译问题(转自: Victor@Beijing)
    22.9
    GIT文档
    机器学习的几个问题探讨
  • 原文地址:https://www.cnblogs.com/ybqjymy/p/14633250.html
Copyright © 2011-2022 走看看