21xrx.com
2024-12-22 16:46:59 Sunday
登录
文章检索 我的文章 写文章
C++ OpenCV 如何保存视频
2023-07-11 09:55:41 深夜i     --     --
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技术

评论区

{{item['qq_nickname']}}
()
回复
回复