代码改变世界

九、OpenCV中视频的录制 - 指南

2025-10-22 20:20  tlnshuju  阅读(7)  评论(0)    收藏  举报

一、OpenCV 视频录制概述

在 OpenCV 中,视频录制主要靠 cv::VideoWriter 类。它可以把连续的 cv::Mat 帧写入一个视频文件(如 .avi、.mp4 等)。

VideoWriter类
构造函数:

VideoWriter::VideoWriter(const String &filename,
int fourcc,
double fps,
Size frameSize,
bool isColor = true);

参数说明:

  • filename:保存的视频文件名,例如 “output.avi”
  • fourcc:视频编码方式,如 CV_FOURCC(‘M’,‘J’,‘P’,‘G’) 或 VideoWriter::fourcc(‘M’,‘J’,‘P’,‘G’)
  • fps:帧率(帧每秒)
  • frameSize:视频每帧的尺寸,Size(width, height)
  • isColor:是否为彩色视频,true 彩色,false 灰度

常用编码(fourcc):

int fourcc = VideoWriter::fourcc('M','J','P','G');
// AVI 常用
int fourcc_mp4 = VideoWriter::fourcc('a','v','c','1');
// MP4 H264

二、示例代码

示例 1:从摄像头录制视频

#include <opencv2/opencv.hpp>
  #include <iostream>
    using namespace cv;
    using namespace std;
    int main() {
    VideoCapture cap(0);
    // 打开摄像头
    if (!cap.isOpened()) {
    cout <<
    "Cannot open camera" << endl;
    return -1;
    }
    // 视频参数
    int frame_width = static_cast<
    int>
    (cap.get(CAP_PROP_FRAME_WIDTH));
    int frame_height = static_cast<
    int>
    (cap.get(CAP_PROP_FRAME_HEIGHT));
    VideoWriter writer("output.avi",
    VideoWriter::fourcc('M','J','P','G'),
    30, Size(frame_width, frame_height));
    Mat frame;
    while (true) {
    cap >> frame;
    if (frame.empty()) break;
    writer.write(frame);
    // 写入视频
    imshow("Camera", frame);
    if (waitKey(1) == 27) break;
    // 按 ESC 停止
    }
    cap.release();
    writer.release();
    destroyAllWindows();
    return 0;
    }

示例 2:将视频文件处理后保存

#include <opencv2/opencv.hpp>
  #include <iostream>
    using namespace cv;
    using namespace std;
    int main() {
    VideoCapture cap("opencv_demo.mp4");
    if (!cap.isOpened()) return -1;
    int width = cap.get(CAP_PROP_FRAME_WIDTH);
    int height = cap.get(CAP_PROP_FRAME_HEIGHT);
    VideoWriter writer("output_processed.avi",
    VideoWriter::fourcc('M', 'J', 'P', 'G'),
    30, Size(width, height));
    Mat frame;
    while (true) {
    cap >> frame;
    if (frame.empty()) break;
    // 处理帧,例如灰度
    cvtColor(frame, frame, COLOR_BGR2GRAY);
    cvtColor(frame, frame, COLOR_GRAY2BGR);
    // 保持三通道以写入
    writer.write(frame);
    }
    cap.release();
    writer.release();
    return 0;
    }

示例3:自动读取指定文件夹下所有图片生成视频

#include <opencv2/opencv.hpp>
  #include <iostream>
    #include <filesystem>
      #include <vector>
        #include <algorithm>
          using namespace cv;
          using namespace std;
          namespace fs = std::filesystem;
          int main() {
          string folderPath = "images";
          // 图片文件夹路径
          string outputVideo = "output_video.avi";
          double fps = 30.0;
          // 帧率
          vector<string> imgFiles;
            // 遍历文件夹,收集图片路径
            for (const auto& entry : fs::directory_iterator(folderPath)) {
            if (entry.is_regular_file()) {
            string ext = entry.path().extension().string();
            // 支持 jpg/png/bmp
            if (ext == ".jpg" || ext == ".png" || ext == ".bmp")
            imgFiles.push_back(entry.path().string());
            }
            }
            if (imgFiles.empty()) {
            cout <<
            "No images found in folder!" << endl;
            return -1;
            }
            // 按文件名排序
            sort(imgFiles.begin(), imgFiles.end());
            // 读取第一张图片获取尺寸
            Mat firstImg = imread(imgFiles[0]);
            if (firstImg.empty()) {
            cout <<
            "Failed to read " << imgFiles[0] << endl;
            return -1;
            }
            Size frameSize(firstImg.cols, firstImg.rows);
            // 创建 VideoWriter
            VideoWriter writer(outputVideo,
            VideoWriter::fourcc('M','J','P','G'),
            fps,
            frameSize,
            true);
            if (!writer.isOpened()) {
            cout <<
            "Cannot open VideoWriter!" << endl;
            return -1;
            }
            // 写入每张图片
            for (const auto& file : imgFiles) {
            Mat img = imread(file);
            if (img.empty()) {
            cout <<
            "Failed to read " << file << endl;
            continue;
            }
            // 尺寸不一致就 resize
            if (img.size() != frameSize) {
            resize(img, img, frameSize);
            }
            writer.write(img);
            }
            writer.release();
            cout <<
            "Video saved as " << outputVideo << endl;
            return 0;
            }