OpenCV C++简单的视频读取和保存入门

网友投稿 2668 2022-05-29

1 视频编码概述

根据百度百科的定义,视频编码本质上就是一种视频的压缩技术,不同的视频编码方式代表不同的压缩方式,其压缩率和视频质量都存在一定的差异。不同编码的视频往往需要通过工具进行视频格式转换。目前来说,视频流传输中最为重要的编解码标准有:国际电联的H.263、H.264和H.265;运动静止图像专家组的M-JPEG;运动图像专家组的MPEG系列标准。

视频的本质可以看作是连续的图像序列,图像序列中的每一个图像被称为帧,换句话说:一帧就是一幅图像。由于人眼的视觉暂留效应,当帧序列以一定的速率播放时,比如1秒24帧,那么往我们看到的就是连续的动作比较流畅的视频。由于连续的帧之间相似性极高,为便于储存传输,需要对原始的视频进行编码压缩,以去除空间、时间维度的冗余。

OpenCV C++简单的视频读取和保存入门

2 重要的视频编码概述

视频编码方式非常的多,但是基于标准的视频编码系列可以总结如下几类 :(1)MPEG系列,由ISO(国际标准组织机构)下属的运动图象专家组开发的视频编码方案,其中主要是Mpeg1(VCD)、Mpeg2(DVD)、Mpeg4(如divx,xvid等)、Mpeg4 AVC。主要应用于视频存储、广播电视、互联网或无线网络的流媒体等。(2)H.26X系列,侧重网络传输,主要应用于实时视频通信领域,如可视电话、实时视频会议、视频监控、流媒体、多媒体视频和Internet视频及多媒体等;H.262标准等同于 MPEG-2的视频编码标准,而H.264/AVC标准则被纳入 MPEG-4的第10部分。 如今广泛使用的 H.264 视频压缩标准(如.mp4文件)可以基于H5进行视频播放,目前还有一种更高的压缩率以及更高质量的编码标准H.265/HEVC标准。H.265的压缩有了显著提高,一样质量的编码视频能节省40%至50%的码流,还提高了并行机制。

3 OpenCV 视频入门

首先用Visual Studio 工具新建一个C++项目,并进行相关配置,具体可以参考上一篇博文《OpenCV 4 C++环境快速搭建》,这里不再赘述。下面给出一个视频操作的核心代码,具体如下所示:

#include #include #include #include #include using namespace cv; using namespace std; int main(int, char**) { //Matrix 对象,存储图像的数值,处理图像而引入的一个封装类 Mat src; //默认摄像头 VideoCapture cap(0); // 检查摄像头是否打开 if (!cap.isOpened()) { cerr << "Unable to open camera\n"; return -1; } //获取帧的宽和高,以及每秒帧数 cout << "Frame width: " << cap.get(CAP_PROP_FRAME_WIDTH) << endl; cout << "Frame height: " << cap.get(CAP_PROP_FRAME_HEIGHT) << endl; cout << "FPS: " << cap.get(CAP_PROP_FPS) << endl; // 0 //读取 cap >> src; // 检测读取视频情况 if (src.empty()) { cerr << "blank frame grabbed\n"; return -1; } //是否是彩色的 bool isColor = (src.type() == CV_8UC3); //VideoWriter可以将图像生成视频 VideoWriter writer; double fps = 24.0; if (cap.get(CAP_PROP_FPS) > 0) { fps = cap.get(CAP_PROP_FPS); } // !!! fourcc 编码和 视频扩展名,需要匹配,而且不同平台是不同的 /////////////////////////////////////////////////////////////// int codec = VideoWriter::fourcc('X', 'V', 'I', 'D'); string filename = "./live_xvid.mp4"; /////////////////////////////////////////////////////////////// writer.open(filename, codec, fps, src.size(), isColor); //检查是否可以正常打开文件 if (!writer.isOpened()) { cerr << "Could not open the output video file for write\n"; return -1; } cout << "###################### " << endl; for (;;) { //检查是否读取正常 if (!cap.read(src)) { cerr << " blank frame grabbed\n"; break; } //将帧图像写入视频文件 writer.write(src); //显示标题为Live的窗口来显示视频 imshow("Live", src); //监听键盘任意键,退出 if (waitKey(5) >= 0) break; } return 0; }

首先,需要用 include 引入相关的头文件,然后用 using namespace cv 引入 opencv命令空间,int main(int, char**) 是函数入口,Mat src中的Mat是一个Matrix 对象,存储图像的数值,处理图像而引入的一个封装类。VideoCapture cap(0) 从默认摄像头进行捕获,cap.isOpened()可以判断是否可以正常捕获视频,cap.get(CAP_PROP_FRAME_WIDTH)和cap.get(CAP_PROP_FRAME_HEIGHT)可以获取获取帧的宽和高。

cap >> src 则读取视频数据到Mat src中,VideoWriter可以将图像生成视频,这是opencv图像操作的核心类,int codec = VideoWriter::fourcc('X', 'V', 'I', 'D');则给出了视频的编码方案Xvid,它是一个开放源代码的MPEG-4视频编解码器,它是基于OpenDivX而编写的,同时它是世界上最常用的视频编码解码器(codec),它的总体表现非常的好。还有一种DivX视频编码,支持MPEG-4, H.264和H.265标准的视频,分辨率可高达4K超高清。

注意:XviD编码的的视频文件扩展名可以是AVI、MKV、MP4等。需要说明的是,仅从扩展名并不能看出这个视频的编码格式。

那么,opencv能否支持H.264呢,比较将设置如下所示:

int codec = VideoWriter::fourcc('H', '2', '6', '4'); string filename = "./live_h264.mp4";

在Windows平台上运行此代码,则抛出如下信息:

Failed to load OpenH264 library : openh264 - 1.8.0 - win64.dll Please check environment and /or download library : https://github.com/cisco/openh264/releases

其中让我们使用OpenH264,从 https://github.com/cisco/openh264/releases 上下载 openh264-1.8.0-win64.dll ,放于 文件源码目录中即可加载。再次运行,则抛出如下信息:

PluginBackend::initWriterAPI Video I / O: plugin is ready to use 'FFmpeg OpenCV Video I/O Writer plugin' OpenCV : FFMPEG : tag 0x34363248 / 'H264' is not supported with codec id 27 and format 'mp4 / MP4 (MPEG-4 Part 14)' OpenCV : FFMPEG : fallback to use tag 0x31637661 / 'avc1' OpenH264 Video Codec provided by Cisco Systems, Inc. Writing videofile : . / live.mp4 Press any key to terminate

其中正确加载了 openh264-1.8.0-win64.dll ,显示OpenH264 Video Codec 相关字样。但是提示了 'H264' is not supported with codec id 27 and format 'mp4 / MP4 (MPEG-4 Part 14)' 。说明H264和mp4文件不兼容,系统回退到OpenH264提供的 AVC1编码,因此修改编码如下即可:

int codec = VideoWriter::fourcc('a', 'v', 'c', '1'); //avc1 //openh264 string filename = "./live.mp4";

我尝试了另外一种编码,也成功了,代码如下:

int codec = VideoWriter::fourcc('X', '2', '6', '4'); string filename = "./live_x264.mkv";

如何查看视频的编码信息呢,可以按照 ffmpeg 工具,其中一个组件为 ffprobe ,下面给出命令:

C:\ffmpeg\bin>ffprobe.exe live_x264.mkv

输出如下信息:

Metadata: ENCODER : Lavf58.76.100 Duration: 00:00:46.04, start: 0.000000, bitrate: 3681 kb/s Stream #0:0: Video: h264 (Constrained Baseline), yuv420p(progressive), 640x480, 24 fps, 24 tbr, 1k tbn, 2k tbc (default) Metadata: DURATION : 00:00:46.042000000

其中的 h264 (Constrained Baseline), yuv420p(progressive), 640x480, 24 fps 则表示h264编码,视频宽高为640x480,帧数为24 。下面给出AVC1编码生成的视频信息:

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'live.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf58.76.100 Duration: 00:01:13.75, start: 0.000000, bitrate: 1847 kb/s Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 640x480, 1847 kb/s, 12 fps, 12 tbr, 12288 tbn, 24576 tbc (default) Metadata: handler_name : VideoHandler vendor_id : [0][0][0][0]

其中显示的是 h264 (Constrained Baseline) (avc1 / 0x31637661)  。下面给出另外的编码及输出信息:

int codec = VideoWriter::fourcc('M', 'J', 'P', 'G'); string filename = "./live_mjpg.avi"; ####################################### Input #0, avi, from 'live_mjpg.avi': Metadata: software : Lavf58.76.100 Duration: 00:00:11.08, start: 0.000000, bitrate: 7185 kb/s Stream #0:0: Video: mjpeg (Baseline) (MJPG / 0x47504A4D), yuvj420p(pc, bt470bg/unknown/unknown), 640x480, 7203 kb/s, 24 fps, 24 tbr, 24 tbn, 24 tbc

说明此时是mjpeg (Baseline) (MJPG / 0x47504A4D) 编码。下面给出本文示例中的编码及输出信息:

int codec = VideoWriter::fourcc('X', 'V', 'I', 'D'); string filename = "./live_xvid.mp4"; ############################# Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'live_xvid.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2mp41 encoder : Lavf58.76.100 Duration: 00:00:05.38, start: 0.000000, bitrate: 5824 kb/s Stream #0:0(und): Video: mpeg4 (Simple Profile) (mp4v / 0x7634706D), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 5822 kb/s, 24 fps, 24 tbr, 12288 tbn, 24 tbc (default) Metadata: handler_name : VideoHandler vendor_id : [0][0][0][0]

由此可见,XVID编码使用的是 mpeg4 (Simple Profile) (mp4v / 0x7634706D) 。

OpenCV Visual Studio 视频

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:分析C++工程编译时间过长的原因
下一篇:android如何提升性能技巧(上)
相关文章