用OpenCV处理视频

开发软件说明

使用OpenCV,对输入的一段彩色视频,用OpenCV实现以下功能或要求:

1.  对输入视频的每一帧图像都用同一个阈值进行二值化;

2.  在每帧二值化图像上叠加上含自己学号与姓名等信息的版权字幕;

3.  在处理的过程中,实时显示每帧图片处理之后的效果;

4.  将所有这些二值化图像按视频原来顺序合成输出一个视频文件,按原输入视频播放速度的两倍合成;

5.  做成如下的命令行格式,xxx.exe 输入视频文件名 二值化阈值  输出视频文件名(例如 MyBiVideo.exe input.avi 50 output.avi )

自己实现的算法具体步骤

因为要将参数传入程序,在程序开始时判断参数的个数是否为4。将后三个参数(argv[1],argv[2],argv[3])作为输入视频文件名、二值化阈值、输出视频文件。其中二值化阈值应通过atof函数转化为浮点型。

使用cvCreateFileCapture得到相应的输入视频文件的CvCapture指针。通过cvGetCaptureProperty得到视频的fourcc,fps,size,frame_count等参数。

根据获得的参数,使用cvCreateVideoWriter创建输出的视频。其他参数与输入视频一样,名称用argv[3],FOURCC用DIVX,fps是原来fps的两倍。

使用cvNamedWindow开启一个窗口。

使用cvQueryFrame一遍遍地获取输入视频中的帧,直到取到NULL为止。用取到的图像的size和depth构造灰度图和二值图。使用cvCvtColor函数把原图转化为灰度图(第三个参数转化类型为CV_RGB2GRAY)。再通过cvThreshold将灰度图转化为二值图,阈值为argv[2]。

在二值图上使用cvPutText放上文字,文字的字体CvFont可以预先通过cvInitFont设置好。因为在二值图上不管用黑色还是白色的字都可能看不清,所以我在相同位置写了两遍,白色的字大一点,黑色的小一点,这样就会有类似边框的效果。

将合成的帧插入到输出视频中,同时在窗口上输出。输出一定要停留一段时间才能看到,因此使用cvWaitKey(1)停留一毫秒。

退出的时候注意释放该释放的东西,如Capture和VideoWriter。如果使用C++版本,在出作用域的时候会自动调用析构函数。

编程体会

第一次通过代码来实现了视频编辑,还是有些小激动。

在配置环境的时候比较麻烦。因为使用的是Visual Studio,网上的各种教程所用的VS和OpenCV千差万别。在设好环境变量,放好一堆的dll之后,又调了些地方才搞定。今后还应该再仔细研究下VS,看看有没有像Makefile之类的做法。

OpenCV中对C和C++都做了实现。比如,要使用VideoWriter:在C中的做法是定一个CvVideoWriter的指针,之后用cvWriteFrame来写每一帧,最后用cvReleaseVideoWriter释放内存。如果是用C++的话,有更方便的做法。可以构造出一个VideoWriter类的对象,用这个对象的write函数写每一帧,最后应该会自动调用析构函数。(刚开始做的时候,没意识到有这么两套方法,混用造成了些麻烦)

程序关键截图

截图是放在实验报告里给助教姐姐看的,这里就懒得发了。

使用一个ali.flv视频,将其放到hw1.exe同样的文件夹下

在命令行中输入指令hw1.exe ali.flv 127 out_ali.avi。

在处理过程中,命令行上显示当前的进度,窗口上显示这个进度对应的实时画面。

全部完成后窗口关闭,命令行上显示Finished。

原视频ali.flv是彩色的,时长3分33秒。下图是用射手播放器打开的情形。

解析后的视频out_ali.avi是黑白二值的,上有姓名学号的水印。视频总时长1分46秒,大约是原视频的一般。播放的画面在19秒处,对应与原版的38秒处的画面。可认定达到了播放速度加倍的效果。

上面的结果是阈值为127的。将阈值改为200后,效果如下:

背景成为黑色,且能看到左侧地球仪的形态,说明阈值的改变有效果。

源代码

因为这是计算机视觉课的作业,所以还是不公开源码了吧。若有合理需求,请回复或发邮件。


版权声明:本文为u014298090原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。