OpenCV入门(7):视频的读取与输出

一、视频的读取

(1)打开视频

cv::VideoCapture 类是读取视频的,cv::VideoCapture 既支持视频文件的读取,也支持从视频捕捉文件中读取视频,比如摄像头。cv::VideoCapture 类创建对象的方式如下三种:

cv::VideoCapture capture(const string& filename,);
// 第一种:从输入的文件名对应文件中读取
cv::VideoCapture capture(int device);
// 第二种:从视频捕捉设备ID中读取
cv::VideoCapture capture();
// 第三种:调用无参构造函数创建对象
  • 第一种方法是从文件(AVI 和 MP4 都可以)中逐帧读取视频。对象创建后,OpenCV 将会打开文件并准备读取它。如果打开成功,将可以开始读取视频的帧,通过 cv::VideoCapture 类的成员函数 isOpened()返回 True 的结果可以判断打开读取对象成功

  • 第二种是从视频捕捉设备中读取视频,一般电脑配套的摄像头 ID 号是 0,外接的 USB 摄像头 ID 号为 1

  • 第三种方式创建一个捕获对象,而不提供任何关于打开的信息。对象创建后通过成员函数 open() 来设定打开的信息。open() 操作也有以下两种方式

    cv::VideoCapture cap;
    cap.open("./test.mp4"); // 第一种路径方式打开视频
    

(2)获取视频属性

获取视频某些属性:

retval = cap.get(propId)

propId:从 0 到 18 的数字,每个数字表示视频的属性

索引 flags 意义
0 cv2::CAP_ PROP_POS_MSEC
1 cv2::CAP_PROP_POS_FRAMES 从0开始索引帧,帧位置
2 cv2::CAP_PROP_POS_AVI_RATIO 视频文件的相对位置(0表示开始,1表示结束)
3 cv2::CAP_PROP_FRAME_WIDTH 视频流的帧宽度
4 cv2::CAP_PROP_FRAME_HEIGHT 视频流的帧高度
5 cv2::CAP_PROP_FPS 帧率
6 cv2::CAP_PROP_FOURCC 编解码器四字符代码
7 cv2::CAP_PROP_FRAME_COUNT 视频文件的帧

(3)读取视频帧

打开之后需要将视频帧(其实就是把视频中的图像取出来)读取到 cv::Mat 矩阵中,共有两种方式,一种是 read 操作,一种是 >> 操作。示例如下:

cv::Mat frame;
cap.read(frame); // 读取方式一

cap>>frame; // 读取方式二

(4)读取视频示例

#include <QApplication>
#include <QDebug>

// 添加相关头文件和包
#include <opencv2/highgui/highgui.hpp>
using namespace cv;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 打开视频文件
    VideoCapture capture("./test.mp4");

    // 检查视频是否成功打开
    if(!capture.isOpened())
    {
        qDebug() <<"Open video Failed!";
        return -1;
    }

    // 获取视频的帧率、宽度和高度
    double fps = capture.get(CAP_PROP_FPS);
    int width = capture.get(CAP_PROP_FRAME_WIDTH);
    int height = capture.get(CAP_PROP_FRAME_HEIGHT);
    qDebug() << "fps:" << fps << "width:" << width << "height:" << height;

    // 创建输出视频文件
    VideoWriter writer("output.mp4", VideoWriter::fourcc('M', 'J', 'P', 'G'), fps, Size(width, height));

    // 检查视频文件是否成功创建
    if (!writer.isOpened())
    {
        qDebug() << "Create video Failed!";
        return -1;
    }

    // 读取每一帧显示
    Mat frame;
    int num = capture.get(cv::CAP_PROP_FRAME_COUNT); // 获取视频帧数目
    for(int i=0;i<num-1;++i)
    {
        // 将视频帧读取到cv::Mat矩阵
        capture.read(frame);

        // 显示每一帧图像
        imshow("test",frame);

        // 等待30ms后,按下q键即可退出播放
        if(waitKey(30) == 'q')
            break;
    }

    // 释放资源
    destroyWindow("test"); // 销毁窗口
    capture.release(); // 释放对象

    return a.exec();
}

效果图如下所示:

Blog_OpenCV_1.gif


二、视频的输出

(1)写入视频

cv::VideoWriter 类用于写入视频。该类较之 cv::VideoCapture 类要复杂一些。cv::VideoWrite 类的对象有两种创建方式。第一种是使用构建函数,第二种是使用 open() 函数,具体示例如下:
第一种方式:

cv::VideoWriter out(
  const string& filename, // 输出文件名
  int fourcc, // 编码形式,使用CV_FOURCC()宏
  double fps, // 输出视频帧率
  cv::Size frame_size, // 单帧图像大小
  bool is_color=true // 如果是false则可传入灰度图像,true是彩色的
)

第二种方式:

cv::VideoWriter out;
out.open(
  "my_video.mpg", // 输出文件名
  CV_FOURCC('D','I','V','X'), // MPEG-4编码
  30.0, // 输出视频帧率
  cv::Size(640,480), // 单帧图像分辨率为640像素*480像素
  true // 只可传入彩色图像,false为灰度图像
)

(2)编码格式

最需要注意的是 FOURCC 编码形式,操作时通常用以下 4 个字符连接起来形成一个 FOURCC 编码,形式为 cv::VideoWriter::fourcc(char c1,char c2,char c3,char c4)。常用格式有以下几种:

代码 含义
VideoWriter::fourcc('M', 'P', '4', 'V') MPEG-4编码,输出文件拓展名mp4
VideoWriter::fourcc( 'X' , '2' , '6' , '4' ) MPEG-4编码,输出文件拓展名mp4
VideoWriter::fourcc('P','I','M','1') MPEG-1编码,输出文件拓展名avi
VideoWriter::fourcc('X','V','I','D') MPEG-4编码,输出文件拓展名avi
VideoWriter::fourcc('I','4','2','0') YUV编码,输出文件拓展名avi
VideoWriter::fourcc('T','H','E','O') ogg vorbis编码,输出文件拓展名ogv
VideoWriter::fourcc('F',L','V','1') flash video编码,输出文件拓展名flv

(3)写入视频帧

像创建的 cv::VideoWrite 对象写入图像也有两种形式,即 write() 操作以及 << 操作。

cv::VideoWriter::write(const Mat& image); // 写入方式一

out<<frame; // 写入方式二

(4)输出视频示例

#include <QApplication>
#include <QDebug>

// 添加相关头文件和包
#include <opencv2/highgui/highgui.hpp>
using namespace cv;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 打开视频文件
    Mat frame;
    std::string filename="./test.mp4";
    VideoCapture cap(filename);

    // 配置输出视频属性
    VideoWriter out;
    out.open("./testOut.mp4",cv::VideoWriter::fourcc('D','I','V','X'), // MPEG-4编码
    cap.get(CAP_PROP_FPS),Size(cap.get(CAP_PROP_FRAME_WIDTH), // 输出视频帧率和分辨率
    cap.get(CAP_PROP_FRAME_HEIGHT)),true); // 只可传入彩色图像
    if(!cap.isOpened())
    {
        qDebug() << "Video load failed!";
        return -1;
    }

    // 循环遍历将视频帧写入到输出视频文件
    while(1)
    {
        cap>>frame;
        if(frame.empty())
        {
            qDebug() << "Video process finished!";
            return 0;
        }
        imshow("video",frame);
        if(waitKey(10) == 'q')
            break;
        out<<frame;
    }

    // 释放资源
    cap.release();

    /*
    在使用OpenCV进行视频处理时,通常会使用cv2.VideoCapture()函数来读取视频文件或者从摄像头获取视频流。当不再需要使用视频流时,
    可以通过调用cap.release()来释放资源,关闭视频流。
    类似地,当使用cv2.VideoWriter()函数将处理后的视频保存为文件时,可以通过调用out.release()来释放资源,关闭视频写入器。
    这些函数的调用可以确保在程序结束时,释放所有使用的资源,避免资源泄露和内存溢出等问题。
    */

    return a.exec();
}

生成的输出视频如下:

Blog_OpenCV_Learnl_13.png


参考:

OpenCv(C++)学习笔记二——视频的读取与输出_videocapture函数如何读取视频-CSDN博客


posted @ 2025-07-23 09:55  fengMisaka  阅读(46)  评论(0)    收藏  举报