21xrx.com
2025-04-03 18:58:55 Thursday
文章检索 我的文章 写文章
C++ OpenCV 如何保存视频
2023-07-11 09:55:41 深夜i     108     0
C++ OpenCV 保存 视频

C++ OpenCV 是一个广泛使用的计算机视觉库,能够提供多种图像和视频处理功能。如果你正在使用 C++ OpenCV 进行视频处理,你可能想要保存处理后的视频以供后续使用。那么,在 C++ OpenCV 中如何保存视频呢?接下来,我们将为大家介绍两种保存视频的方法。

方法一:使用 VideoWriter

VideoWriter 是 OpenCV 中用于将多个带有相同大小和编解码器的图像帧合成视频的类。使用 VideoWriter 类,可以将你的处理后的图像帧合成一个视频文件。下面是一个简单的 VideoWriter 示例代码:

VideoCapture cap(0); //打开默认的摄像头
Mat frame;
//设置输出视频文件名和编解码器类型
VideoWriter outputVideo("output.avi", cv::VideoWriter::fourcc('M', 'J', 'P', 'G'), 25, Size(cap.get(CAP_PROP_FRAME_WIDTH), cap.get(CAP_PROP_FRAME_HEIGHT)), true);
while (true) {
  cap >> frame; //获取视频帧
  if (frame.empty())
    break;
  
  //进行图像处理
  ...
  //将处理后的图像帧写入视频
  outputVideo.write(frame);
}
outputVideo.release(); //释放输出视频
cap.release(); //释放摄像头

在上面的代码中,我们首先打开默认的摄像头并读取视频帧。然后,我们使用 VideoWriter 对象设置输出视频文件名、编解码器类型、帧速率和帧大小。我们使用 while 循环读取每一帧视频,对其进行处理并将其写入输出视频。最后,我们释放输出视频和摄像头。

方法二:使用 FFMPEG 库

FFMPEG 是一个广泛使用的库,可用于在多种平台上编写音频和视频应用程序。如果你使用的 OpenCV 版本没有 VideoWriter 类,那么可以使用 FFMPEG 在 C++ OpenCV 中保存视频。下面是一个简单的 FFMPEG 示例代码:

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "ffmpeg/libavcodec/avcodec.h"
#include "ffmpeg/libavformat/avformat.h"
#include "ffmpeg/libswscale/swscale.h"
int main()
{
  AVFormatContext *formatContext;
  AVOutputFormat *outputFormat;
  AVCodec *codec;
  AVCodecContext *codecContext;
  AVStream *stream;
  int width = 640;
  int height = 480;
  int fps = 30;
  av_register_all(); //注册 FFmpeg
  avformat_alloc_output_context2(&formatContext, NULL, NULL, "video.avi"); //初始化输出格式
  outputFormat = formatContext->oformat;
  codec = avcodec_find_encoder(outputFormat->video_codec); //查找视频编码器
  stream = avformat_new_stream(formatContext, codec); //创建新的视频流
  avcodec_get_context_defaults3(stream->codec, codec);
  codecContext = stream->codec;
  codecContext->codec_id = outputFormat->video_codec;
  codecContext->codec_type = AVMEDIA_TYPE_VIDEO;
  codecContext->bit_rate = 400000;
  codecContext->width = width;
  codecContext->height = height;
  codecContext->time_base.num = 1;
  codecContext->time_base.den = fps;
  codecContext->gop_size = 10;
  codecContext->pix_fmt = AV_PIX_FMT_YUV420P;
  if (codecContext->codec_id == AV_CODEC_ID_H264)
  {
    av_opt_set(codecContext->priv_data, "preset", "slow", 0);
  }
  av_dump_format(formatContext, 0, "video.avi", 1);
  if (!(outputFormat->flags & AVFMT_NOFILE))
  {
    avio_open(&formatContext->pb, "video.avi", AVIO_FLAG_WRITE);
  }
  avformat_write_header(formatContext, NULL); //写入文件头
  AVFrame *picture = av_frame_alloc();
  picture->width = codecContext->width;
  picture->height = codecContext->height;
  picture->format = codecContext->pix_fmt;
  av_image_alloc(picture->data, picture->linesize, codecContext->width, codecContext->height, codecContext->pix_fmt, 32);
  AVPacket pkt;
  int got_output;
  int frame_num = 0;
  for (frame_num = 0; frame_num < 100; frame_num++)
  {
    cv::Mat frame = cv::Mat::zeros(height, width, CV_8UC3); //生成测试视频帧
    //进行图像处理
    ...
    picture->data[0] = (uint8_t *)frame.data;
    picture->linesize[0] = frame.step;
    sws_scale(swsContext, picture->data, picture->linesize, 0, codecContext->height, codecContext->coded_frame->data, codecContext->coded_frame->linesize);
    av_init_packet(&pkt);
    pkt.data = NULL;
    pkt.size = 0;
    got_output = 0;
    avcodec_encode_video2(codecContext, &pkt, picture, &got_output);
    if (got_output)
    {
      av_interleaved_write_frame(formatContext, &pkt);
    }
  }
  av_write_trailer(formatContext);
  avcodec_close(codecContext);
  avio_close(formatContext->pb);
  avformat_free_context(formatContext);
  av_free(picture);
  return 0;
}

在上面的代码中,我们首先使用 av_register_all() 注册 FFmpeg,并初始化输出格式和 codecContext。然后,我们创建视频流和使用 av_opt_set() 方法在 H264 编码器上设置预设值。接下来,我们打开输出文件并写入文件头。

我们使用 cv::Mat::zeros() 方法生成测试视频帧并进行图像处理。然后,我们将帧数据填充到 AVFrame 对象中,并使用 sws_scale() 方法将其编码并将其存储在 AVPacket 对象中。最后,我们使用 av_interleaved_write_frame() 方法将 AVPacket 对象写入文件。我们一直循环直到保存了 100 帧,最后释放编解码器、输出文件和内存空间。

总结

C++ OpenCV 提供了两种保存处理后的视频的方法:使用 VideoWriter 类和使用 FFMPEG 库。如果你的 OpenCV 版本提供了 VideoWriter 类,那么你可以使用 VideoWriter 对象将图像帧合成视频文件。如果你没有 VideoWriter 类,则可以使用 FFmpeg 在 C++ OpenCV 中保存视频。无论你使用哪种方法,都可以在 C++ OpenCV 中轻松地保存视频。

  
  
下一篇: Node.js和JVM技术

评论区

请求出错了