前言:本文基于OpenCV4.1.1,介绍常见的视频格式以及针对这些视频格式如何进行读取与保存操作。

一、常见的视频格式

1.AVI格式 
  它的英文全称为Audio Video Interleaved,即音频视频交错格式。它于1992年被Microsoft公司推出,随Windows3.1一起被人们所认识和熟知。所谓“音频视频交错”,就是可以将视频和音频交织在一起进行同步播放。这种视频格式的优点是图像质量好,可以跨多个平台使用,但是其缺点是体积过于庞大,而且更加糟糕的是压缩标准不统一,因此经常会遇到高版本Windows媒体播放器播放不了采用早期编码编辑的AVI格式视频,而低版本Windows媒体播放器又播放不了采用最新编码编辑的AVI格式视频。其实解决的方法也非常简单,我们将在后面的视频转换、视频修复部分中给出解决的方案。 
2.DV-AVI格式
  DV的英文全称是Digital Video Format,是由索尼、松下、JVC等多家厂商联合提出的一种家用数字视频格式。目前非常流行的数码摄像机就是使用这种格式记录视频数据的。它可以通过电脑的IEEE 1394端口传输视频数据到电脑,也可以将电脑中编辑好的的视频数据回录到数码摄像机中。这种视频格式的文件扩展名一般也是.avi,所以我们习惯地叫它为DV-AVI格式。
3.MPEG格式 
  它的英文全称为Moving Picture Expert Group,即运动图像专家组格式,家里常看的VCD、SVCD、DVD就是这种格式。MPEG文件格式是运动图像压缩算法的国际标准,它采用了有损压缩方法从而减少运动图像中的冗余信息。MPEG的压缩方法说的更加深入一点就是保留相邻两幅画面绝大多数相同的部分,而把后续图像中和前面图像有冗余的部分去除,从而达到压缩的目的。目前MPEG格式有三个压缩标准,分别是MPEG-1、MPEG-2、和MPEG-4,另外,MPEG-7与MPEG-21仍处在研发阶段。

  • MPEG-1:制定于1992年,它是针对1.5Mbps以下数据传输率的数字存储媒体运动图像及其伴音编码而设计的国际标准。也就是我们通常所见到的VCD制作格式。这种视频格式的文件扩展名包括.mpg、.mlv、.mpe、.mpeg及VCD光盘中的.dat文件等。 
  • MPEG-2:制定于1994年,设计目标为高级工业标准的图像质量以及更高的传输率。这种格式主要应用在DVD/SVCD的制作(压缩)方面,同时在一些HDTV(高清晰电视广播)和一些高要求视频编辑、处理上面也有相当的应用。这种视频格式的文件扩展名包括.mpg、.mpe、.mpeg、.m2v及DVD光盘上的.vob文件等。 
  • MPEG-4:制定于1998年,MPEG-4是为了播放流式媒体的高质量视频而专门设计的,它可利用很窄的带度,通过帧重建技术,压缩和传输数据,以求使用最少的数据获得最佳的图像质量。MPEG-4最有吸引力的地方在于它能够保存接近于DVD画质的小体积视频文件。这种视频格式的文件扩展名包括.asf、.mov和DivX 、AVI等。 

4.DivX格式 
  这是由MPEG-4衍生出的另一种视频编码(压缩)标准,也即我们通常所说的DVDrip格式,它采用了MPEG4的压缩算法同时又综合了MPEG-4与MP3各方面的技术,说白了就是使用DivX压缩技术对DVD盘片的视频图像进行高质量压缩,同时用MP3或AC3对音频进行压缩,然后再将视频与音频合成并加上相应的外挂字幕文件而形成的视频格式。其画质直逼DVD并且体积只有DVD的数分之一。
5.MOV格式 
  美国Apple公司开发的一种视频格式,默认的播放器是苹果的QuickTimePlayer。具有较高的压缩比率和较完美的视频清晰度等特点,但是其最大的特点还是跨平台性,即不仅能支持MacOS,同样也能支持Windows系列。 
  它的英文全称为Advanced Streaming format,它是微软为了和现在的Real Player竞争而推出的一种视频格式,用户可以直接使用Windows自带的Windows Media Player对其进行播放。由于它使用了MPEG-4的压缩算法,所以压缩率和图像的质量都很不错。 ) 

6.WMV格式
  它的英文全称为Windows Media Video,也是微软推出的一种采用独立编码方式并且可以直接在网上实时观看视频节目的文件压缩格式。WMV格式的主要优点包括:本地或网络回放、可扩充的媒体类型、可伸缩的媒体类型、多语言支持、环境独立性、丰富的流间关系以及扩展性等。 
7.RM格式 
  Networks公司所制定的音频视频压缩规范称之为Real Media,用户可以使用RealPlayer或RealOne Player对符合RealMedia技术规范的网络音频/视频资源进行实况转播,并且RealMedia还可以根据不同的网络传输速率制定出不同的压缩比率,从而实现在低速率的网络上进行影像数据实时传送和播放。这种格式的另一个特点是用户使用RealPlayer或RealOne Player播放器可以在不下载音频/视频内容的条件下实现在线播放。 
8.RMVB格式 
  这是一种由RM视频格式升级延伸出的新视频格式,它的先进之处在于RMVB视频格式打破了原先RM格式那种平均压缩采样的方式,在保证平均压缩比的基础上合理利用比特率资源,就是说静止和动作场面少的画面场景采用较低的编码速率,这样可以留出更多的带宽空间,而这些带宽会在出现快速运动的画面场景时被利用。这样在保证了静止画面质量的前提下,大幅地提高了运动图像的画面质量,从而图像质量和文件大小之间就达到了微妙的平衡。

9.ASF(Advanced Streaming Format)格式 
Microsoft公司推出的Advanced Streaming Format (ASF,高级流格式),也是一个在Internet上实时传播多媒体的技术标准,Microsoft公司的野心很大,希图用ASF取代QuickTime之类的技术标准。ASF的主要优点包括:本地或网络回放、可扩充的媒体类型、部件下载、以及扩展性等。ASF应用的主要部件是NetShow服务器和NetShow播放器。有独立的编码器将媒体信息编译成ASF流,然后发送到NetShow服务器,再由NetShow服务器将ASF流发送给网络上的所有NetShow播放器,从而实现单路广播或多路广播。这和Real系统的实时转播则是大同小异。

二、OpenCV的视频格式获取

在OpenCV中,要以某一种格式保存视频,需要指定具体的视频保存格式,常见的视频格式如下,我们可以通过

VideoWriter类的fourcc函数来指定视频的格式,该函数的原型如下:

CV_WRAP static int fourcc(char c1, char c2, char c3, char c4);

它接受四个char类型的参数,然后返回的是一个int类型的整数,常见的保存格式如下: 

OpenCV 4.1版本标志

OpenCV 4.0版本标志

作用

VideoWriter::fourcc('D','I','V','X')

CV_FOURCC('D','I','V','X')

MPEG-4编码

VideoWriter::fourcc('P','I','M','1')

CV_FOURCC('P','I','M','1')

MPEG-1编码

VideoWriter::fourcc('M','J','P','G')

CV_FOURCC('M','J','P','G')

JPEG编码(运行效果一般)

VideoWriter::fourcc('M', 'P', '4', '2')

CV_FOURCC('M', 'P', '4', '2')

MPEG-4.2编码

VideoWriter::fourcc('D', 'I', 'V', '3')

CV_FOURCC('D', 'I', 'V', '3')

MPEG-4.3编码

VideoWriter::fourcc('U', '2', '6', '3')

CV_FOURCC('U', '2', '6', '3')

H263编码

VideoWriter::fourcc('I', '2', '6', '3')

CV_FOURCC('I', '2', '6', '3')

H263I编码

VideoWriter::fourcc('F', 'L', 'V', '1')

CV_FOURCC('F', 'L', 'V', '1')

FLV1编码

2.1 如何读取视频并获得该视频的相关信息

参考如下代码:

VideoCapture videoSource;
bool is_open = videoSource.open(videopath);  //打开视频,成功打开则返回true,否则返回false
if (!is_open) 
{
	cout << "Error on load video..." << endl;
	return 0;
}

那怎么获取这个视频的一些信息呢,比如帧率,这个视频的格式,每一帧的大小等等信息呢?其实都是通过

VideoCapture的get方法来实现的,通过给get方法传递不同的参数来获取不同的信息。

原型如下:

CV_WRAP virtual double get(int propId) const;
//参数propId是一个cv::VideoWriterProperties枚举类型的整数值
//返回的是一个double数值,如果返回的是0,则说明不支持这个操作

cv::VideoWriterProperties枚举类型的取值如下,有很多:

enum VideoCaptureProperties {
       CAP_PROP_POS_MSEC       =0, //在前在视频文件中的位置, 以毫秒milliseconds为单位.
       CAP_PROP_POS_FRAMES     =1, //下一帧的位置,从0帧开始计算
       CAP_PROP_POS_AVI_RATIO  =2, //当前在视频文件中的相对位置: 0代表视频的开始, 1代表视频的结尾
       CAP_PROP_FRAME_WIDTH    =3, //每一帧的width
       CAP_PROP_FRAME_HEIGHT   =4, //每一帧的height
       CAP_PROP_FPS            =5, //帧率
       CAP_PROP_FOURCC         =6, //4个字符的编码. 参考 VideoWriter::fourcc .
       CAP_PROP_FRAME_COUNT    =7, //视频文件一共有多少帧      
.
.
.
等等
}

那如何读取视频帧呢?其实就是一句话:

bool is_end=videoSource.read(frame);  // 读取第一帧,每次读取一帧,读取成功则返回True,结束后返回false

一般这么做:

while (1) 
{
	bool is_end=videoSource.read(frame);  // 依次读取每一帧
	if (frame.empty())        //最后的帧为空,也可以通过判断is_end的真假来实现
    {
		cout << endl << "Video ended!" << endl;
		break;
	}
}

 

2.2 视频的保存

首先要创建视频保存对象即VideoWriter对象,然后设置它的open函数的五个参数,最后执行保存,如下:

//这里的capture指的就是打开的视频文件,这里没放出来
VideoWriter writer;  //创建一个对象
Size size = Size(capture.get(CAP_PROP_FRAME_WIDTH),capture.get(CAP_PROP_FRAME_HEIGHT));获取视频的width和height
int fps = capture.get(CAP_PROP_FPS); //获取帧率

//a是获取打开视频默认的视频格式
int a = capture.get(CAP_PROP_FOURCC);
//b是自己选定视频格式
int b = writer.fourcc('M', 'J', 'P', 'G');
	
//打开要保存视频,需要传递五个参数
writer.open("./output16.avi", b, fps, size, true);

我们看一下这个open函数的定义,原型如下:

CV_WRAP virtual bool open(const String& filename, int fourcc, double fps,Size frameSize, bool isColor = true);
//第一个参数是保存的视频文件路径以及名称
//fourcc :指的就是视频的格式,是一个整数值
//fps :指的是视频的帧率
//frameSize :指的就是每一帧的尺寸
//isColor :指的是是否保存彩色图像

//返回值是布尔值,成功则返回True

注意事项:

需要特别注意第五个参数isColor,

(1)如果isColor为True,则说明需要保存彩色视频,这样每一帧必须是RGB图像格式,如果是单通道灰度图像,则需要使用

cvtColor(gray, gray, COLOR_GRAY2BGR);

将灰度图像转化为彩色的三通道图像才能正确保存视频,否则无法保存,但是却不会报错,只不过发现保存的视频为空的,也打不开;

(2)如果isColor为false,则说明需要保存灰度,这样每一帧必须是灰度单通道图像格式,如果是彩色RGB三通道图像,则需要使用

cvtColor(gray, gray, COLOR_BGR2GRAY);

将RGB三通道图像转化为灰度的单通道图像才能正确保存视频,否则无法保存,但是却不会报错,只不过发现保存的视频为空的,也打不开;

2.3 如何实现视频格式“四字符”与“整数”之间的互相转换

(1)“四字符”——>“整数”

int b = writer.fourcc('M', 'J', 'P', 'G');  //通过四个字符获取与之对应的整数

(2)“整数”——>“四字符”

unsigned int f = (unsigned)capture.get(cv::CAP_PROP_FOURCC);
char fourcc[] = {
		(char)f, // First character is lowest bits
		(char)(f >> 8), // Next character is bits 8-15
		(char)(f >> 16), // Next character is bits 16-23
		(char)(f >> 24), // Last character is bits 24-31
		'\0' // and don't forget to terminate
	};
cout << "the return int fourcc was: " << f << endl;
cout << "FourCC for this video was: " << fourcc << endl;
/*运行结果为:
the return int fourcc was: 1145656920
FourCC for this video was: XVID
*/

2.4 释放视频对象

videoCapture.release();
writer.release();

 

三、常用的视频编解码标准

很多视频编解码器可以很容易的在个人计算机和消费电子产品上实现,这使得在这些设备上有可能同时实现多种视频编解码器,这避免了由于兼容性的原因使得某种占优势的编解码器影响其它编解码器的发展和推广。最后我们可以说,并没有那种编解码器可以替代其它所有的编解码器。下面是一些常用的视频编解码器,按照它们成为国际标准的时间排序:
1、H.261 
H.261主要在老的视频会议和视频电话产品中使用。H.261是由ITU-T开发的,第一个使用的数字视频压缩标准。实质上说,之后的所有的标准视频编解码器都是基于它设计的。它使用了常见的YCbCr颜色空间,4:2:0的色度抽样格式,8位的抽样精度,16x16的宏块,分块的运动补偿,按8x8分块进行的离散余弦变换,量化,对量化系数的Zig-zag扫描,run-level符号影射以及霍夫曼编码。H.261只支持逐行扫描的视频输入。

 
2、MPEG-1第二部分 
MPEG-1第二部分主要使用在VCD上,有些在线视频也使用这种格式。该编解码器的质量大致上和原有的VHS录像带相当,但是值得注意的是VCD属于数字视频技术,它不会像VHS录像带一样随着播放的次数和时间而逐渐损失质量。如果输入视频源的质量足够好,编码的码率足够高,VCD可以给出从各方面看都比VHS要高的质量。但是为了达到这样的目标,通常VCD需要比VHS标准要高的码率。实际上,如果考虑到让所有的VCD播放机都可以播放,高于1150kbps的视频码率或者高于352x288的视频分辨率都不能使用。大体来说,这个限制通常仅仅对一些单体的VCD播放机(包括一些DVD播放机)有效。MPEG-1第三部分还包括了目前常见的*.mp3音频编解码器。如果考虑通用性的话,MPEG-1的视频/音频编解码器可以说是通用性最高的编解码器,几乎世界上所有的计算机都可以播放MPEG-1格式的文件。几乎所有的DVD机也支持VCD的播放。从技术上来讲,比起H.261标准,MPEG-1增加了对半像素运动补偿和双向运动预测帧。和H.261一样,MPEG-1只支持逐行扫描的视频输入。 

3、MPEG-2第二部分 
MPEG-2第二部分等同于H.262,使用在DVD、SVCD和大多数数字视频广播系统和有线分布系统(cable distribution systems)中。当使用在标准DVD上时,它支持很高的图像质量和宽屏;当使用在SVCD时,它的质量不如DVD但是比VCD高出许多。但是不幸的是,SVCD最多能在一张CD光盘上容纳40分钟的内容,而VCD可以容纳一个小时,也就是说SVCD具有比VCD更高的平均码率。MPEG-2也将被使用在新一代DVD标准HD-DVD 和 Blu-ray(蓝光光盘)上。从技术上来讲,比起MPEG-1,MPEG-2最大的改进在于增加了对隔行扫描视频的支持。MPEG-2可以说是一个相当老的视频编码标准,但是它已经具有很大的普及度和市场接受度。 

4、H.263 
H.263主要用在视频会议、视频电话和网络视频上。在对逐行扫描的视频源进行压缩的方面,H.263比它之前的视频编码标准在性能上有了较大的提升。尤其是在低码率端,它可以在保证一定质量的前提下大大的节约码率。 
MPEG-4第二部分 
MPEG-4第二部分标准可以使用在网络传输、广播和媒体存储上。比起MPEG-2和第一版的H.263,它的压缩性能有所提高。和之前的视频编码标准的主要不同点在于,“物件導向”(Object-oriented)的编码方法和一些其它并非用于提高通常视频编码压缩率的技术。当然它也引入了一些提高压缩能力的技术,包括一些H.263的技术和1/4像素的运动补偿。和MPEG-2一样,它同时支持逐行扫描和隔行扫描。 

5、MPEG-4第十部分 ( H.264 ) : 性能最优的视频编码标准 
MPEG-4第十部分技术上和ITU-T H.264是相同的标准,有时候也被叫做“AVC”)。 这个刚刚制定完成的标准是ITU-T VCEG和ISO/IEC MPEG合作完成的性能最优的视频编码标准,并且在已经得到了越来越多的应用。该标准引入了一系列新的能够大大提高压缩性能的技术,并能够同时在高码率端和低码率端大大超越以前的诸标准。已经使用和将要使用H.264技术的产品包括例如索尼公司的PSP,Nero公司的Nero Digital 产品套装,苹果公司的Mac OS X v10.4,以及新一代DVD标准HD-DVD和蓝光光盘(Blu-ray)。 

6、AVS 
AVS是中国制定的音视频压缩编码标准,故准确来说,其不仅仅包括视频编码标准。它最主要的目的是通过采用与H.264不同的专利授权方式,来避免付出大笔的专利授权费用。在技术上,AVS的视频编码部分采用的技术与H.264非常相似,但采取了一些简化措施。这样做,其一可以回避一些非必要专利,另外据称也可以在几乎不影响编码压缩效率的基础上,提高编解码速度。 
DivX,XviD和3ivx 
DivX,XviD和3ivx视频编解码器基本上使用的都是MPEG-4第二部分的技术,以后缀*.avi, *.mp4, *.ogm 或者 *.mkv 结尾的文件有一部分是使用这些视频编解码器的。 

7、WMV 
WMV(Windows Media Video)是微软公司的视频编解码器家族,包括WMV 7、WMV 8、WMV 9、WPV 10。这一族的编解码器可以应用在从拨号上网的窄带视频到高清晰度电视(HDTV)的宽带视频。使用Windows Media Video用户还可以将视频文件刻录到CD、DVD或者其它一些设备上。它也适用于用作媒体服务器。WMV 可以被看作是MPEG-4的一个增强版本。最新的WMV的版本是正在SMPTE制定中的VC-1标准。WMV-9(VC-1,开发代号为“Corona”)刚推出的时候称为VC-9,之后才被电影电视工程师协会(SMPTE)改称为VC-1(VC指Video Codec)。技术上,VC-1也与H.264有诸多相似之处。 

8、RealVideo 
RealVideo是由RealNetworks公司开发的视频编解码器。近几年曾经有段时间的低迷,之后又获得市场的青睐。最近尤其在BT电影界格外受宠。 

9、Sorenson 3 
Sorenson 3是由苹果公司的软件QuickTime使用的一种编解码器。很多因特网上的QuickTime格式的视频都是这种编解码器压缩的。 

10、Cinepak 
Cinepak同样是由苹果公司的软件QuickTime使用的一种很老的编解码器,好处是即使很老的计算机(如486)也都支援并且能顺利播放。 

11、Indeo Video 
Indeo Video Indeo Video 是由 Intel 所研發的编解码器。 
上面提到的编解码器都有各自的优点和缺点,经常可以看到有对这些编解码器进行比较的文章,这时候最重要的同时考虑编码的码率和清晰度(常说的律失真特性,鲁棒性)。