首页 文学文摘 时政新闻 科技科普 经济法律 健康生活 管理财经 教育教学 文化艺术 社科历史

基于Qt4和OpenCV的嵌入式视频监控系统

作者:刘冬 来源:现代电子技术

摘 要:当前有不少视频监控系统是基于GSPCA开发的,它们存在不能在本地显示视频,缺乏移动检测等图像处理功能,对于存储空间要求高,难于升级等缺点。为解决上述问题,结合Qt4和OpenCV开发了一种嵌入式视频监控系统。该系统的硬件环境为ARM9系统,操作系统为Linux。系统不仅能够在本地实时显示监视画面,还能够根据移动检测的结果记录视频,大大节省了存储空间。系统还可以在上述检测中加入与预设报警门限值进行比较的功能,根据比较结果决定是否报警并通过网络将拍摄的图像传递给远端系统。达到了在本地显示视频,节约存储空间,可进行移动检测,便于升级的效果。

关键词: 嵌入式视频监控系统; 移动检测; Qt; OpenCV

中图分类号: TN919?34; TP33 文献标识码: A 文章编号: 1004?373X(2013)08?0104?05

0 引 言

随着计算机与视频技术的发展,人们已经可以用摄像装置拍摄自己感兴趣的图像并保存、传输,比如在家庭、办公室、停车场等场所安装的视频监控系统。这些场所安装的监控系统一般要求成本低廉、具有视频存储和传输功能。使用嵌入式系统,可以实现上述目的。不过当前的很多嵌入式视频监控系统是基于GSPCA[1]的系统。GSPCA是法国人编写的Linux视频驱动程序包,支持不少摄像头,也提供了像Spacview之类的视频录制与传输程序。但基于GSPCA软件包构建的监控系统有以下缺陷:首先,GSPCA的图像必须先经过网络传到PC机上才能显示的,如果在嵌入式系统的显示屏上本身反而不能直接显示;第二,GSPCA的图像处理功能并不丰富,不能提供移动检测等功能;第三,GSPCA的图像格式只有MJPEG形式,等于每帧图像都要存储;这样的存储量过大,而如果使用MPEG格式,由于使用帧间压缩,可以节省大量存储空间;第四,缺乏移动侦测功能,因为通常视频如果完全存储下来即便使用MPEG格式也会占据很大的存储空间;如果加入了移动检测功能,在检测到物体运动后再存储视频,就可以大大节省视频文件占据的存储容量;第五,GSPCA所提供的操作界面基本是自己编写的,非常简陋,较之主流的图形化界面库而言,缺乏对于后续开发的良好支撑,这一点严重阻碍了基于GSPCA产品的商业应用。另外,还有以下几点:首先,随着触摸屏技术的快速发展,目前触摸屏的成本已经很低,完全可以把触摸屏应用于监控系统的启动、管理和关闭,这样可以非常方便使用者。其次,如果用户不在现场,此监控系统还应该具备把视频文件通过网络发送给用户的能力。综上所述,在充分考虑后,基于嵌入式技术,开发出了一种成本适中、使用触摸屏、具有视频存储、移动检测和传输功能的视频监控系统。该系统可以独立应用于家庭中的实时监控,也可以用于办公室、车场或和其他大型监控系统集成以执行大范围的监控任务。

1 总体结构

监控系统由数字摄像设备和视频监控终端组成。结构如图1所示。数字摄像设备提供原始图像数据,视频监控终端对图像数据进行处理,数字摄像设备与视频监控终端的视频数据接口相连。监控终端包括管理模块、录制与检测模块、显示模块、触摸屏模块、通信模块。其中管理模块具备系统管理功能,例如报警级别的设置;录制与检测模块完成图像数据压缩、视频录制、差异检测与报警任务;显示模块显示当前实拍的图像或按照不同速率播放录制的视频;触摸屏模块提供触摸输入并传递给管理模块、录制与检测模块和显示模块的功能;通信模块可通过有线或无线方式传输报警信号和视频文件,可以加密传输的数据。

本系统由软件和硬件部分构成。硬件部分由TQ2440开发板和USB摄像头构成。其中TQ2440开发板[2]上包括基于ARM9体系的s3c2410/2440CPU、32 MB内存、32 MB闪存、320×240点阵彩色液晶触摸屏、USB口和以太网口。USB摄像头为中星微ZC301摄像头,支持常见的V4L协议。软件部分包括linux操作系统(内核2.6)、Qt4图形中间件、OpenCV2.0库和自主开发的监控软件。Linux操作系统(内核2.6)具备强大的多进程处理能力、出色的稳定性和良好的扩展性,易于安装各种应用软件和函数库。Qt4图形中间件具有丰富的图形化工具库,OpenCV2.0有强大的图像处理能力。图2为软件系统的架构图。

2 管理模块设计及实现

管理模块功能包含了摄像启动、播放启动、系统设置和系统退出功能。下图为管理界面。管理模块的开发主要是基于Qt4进行的。Qt是一个多平台的C++图形用户界面应用程序框架,属于诺基亚,现在发展到Qt4[3]。它提供给应用程序开发者建立艺术级的图形用户界面所需的所用功能。Qt是完全面向对象的因此很容易扩展,并且允许真正的组件编程。自从1996年早些时候Qt进入商业领域,它已经成为全世界范围内数千种成功的应用程序的基础,Qt不仅是流行的Linux[4]桌面环境KDE 的基础,近年来越来越多的智能化仪表[5]、虚拟仪表[6]也开始采用Qt作为基本的图形化操作界面。

管理模块的主要工作流程是这样的:用户开启系统后即进入主控菜单;在菜单中,选择播放视频、修改设置或摄像;如果是摄像,实时采集图像并提示用户选择图像保存方式究竟是比较节约空间的移动检测方式还是常规方式;用户选择后开始录制;当系统检测到物体移动时将保存当前图像;系统通过网络发送出图像文件;系统结束录制,返回主控菜单;如果是播放,打开当前目录,用户可挑选需要查看的视频文件;选中视频文件后开始播放视频,用户可选择播放视频的速度;系统结束播放,返回主控菜单;如果是修改设置,则调整所需的系统属性,例如背景图案;保存修改的系统属性到设置文件里;设置结束,返回主控菜单;用户关闭系统退出。

管理模块的主要流程如图3所示。

管理模块的部分代码如下:

quit = new QToolButton(this); //退出功能

quit?>setText(QObject::tr("&quit"));

gear = new QToolButton(this); //系统设置

gear?>setText(QObject::tr("&setup"));

camera = new QToolButton(this); //录制视频

camera?>setText(QObject::tr("&camera"));

video = new QToolButton(this); //播放视频

video?>setText(QObject::tr("&play"));

//界面布局

QHBoxLayout *vbuttonLayout0 = new QHBoxLayout;

QVBoxLayout *vbuttonLayout = new QVBoxLayout;

vbuttonLayout?>addWidget(camera);

vbuttonLayout?>addWidget(video);

QVBoxLayout *vbuttonLayout2 = new QVBoxLayout;

vbuttonLayout2?>addWidget(gear);

vbuttonLayout2?>addWidget(quit);

QGridLayout *mainLayout = new QGridLayout;

mainLayout?>addLayout(vbuttonLayout0,1,0);

mainLayout?>addLayout(vbuttonLayout,2,0);

mainLayout?>addLayout(vbuttonLayout2,2,1);

3 录制与检测模块设计及实现

录制与检测模块功能分成按常规拍摄和移动侦测拍摄两种。后一种拍摄条件的每秒帧数低于常规拍摄,主要是考虑一些用户可能希望长时间监视某个区域,这时若使用常规节奏拍摄就要耗费大量存储空间,而使用移动侦测可大大节省存储空间。

该模块使用了OpenCV函数库,OpenCV[7]是开放源代码的计算机视觉类库,由英特尔公司位于俄罗斯的研究实验室所开发,它是可免费获得的由一些C函数和C++类所组成的库,用来实现常用的图像处理及计算机视觉算法,已广泛运用于人脸识别[8]、目标运动检测[9] 、图像处理[10]等领域。选用它有两个原因:首先,OpenCV的图像处理功能相当强大,不仅能处理图像的格式、提供了提供移动检测等功能;其次, OpenCV产生的视频文件可以根据需要选择MPEG4,MJPEG等多种压缩格式,从压缩机理上看,MPEG4算法由于采用插值与帧间预测,不需要压缩每帧图像,压缩效果显然好得多。综合上述因素,选用了OpenCV。

模块接收来自摄像头的图像数据。本模块启动后会调用函数cvCreateCameraCapture检测摄像头是否连接,如果检测到摄像头则得到一个指针,否则会报错退出。之后的工作流程是:先调用cvQueryFrame操作此指针,再调用函数cvCreateVideoWriter指定视频压缩格式并获得视频文件指针。这样可得到一个视频缓冲区A,然后该缓冲区接收从USB摄像头提取的图像数据,如果没有移动检测,则该缓冲区的数据将按照选定的视频压缩格式以调用函数cvWriteFrame的方式被写入视频文件。如果有移动检测,则调用函数motionDetect。该函数的功能如下:将A缓冲区的数据被保存到另外的缓冲区B里等待比较操作,A缓冲区继续接收来自摄像头的数据,A与B的数据在经过相关二值化和降噪处理后进行比较,如果比较中发现数据的不同之处已经超过预设的门限值,则把拍摄时间叠加入B缓冲区的视频数据。此处的视频数据记录以调用cvWriteFrame的方式被写入本地视频文件。本地视频文件的命名是按照数字升序自动产生的,因此不会覆盖之前拍摄的视频。操作过程如图4所示。

录制与检测模块的部分代码如下:

capture = cvCreateCameraCapture(0); //打开摄像头

p_current_frame = cvQueryFrame( capture ); //创建缓冲区A

if ( p_current_frame?>origin == IPL_ORIGIN_TL )

cvCopy( p_current_frame, m_opencvimg, 0 );

//创建缓冲区B

else

cvFlip( p_current_frame, m_opencvimg, 0 );

if (detect_is_needed == false) {

//如不需要运动检测

timeStamp(p_current_frame); //在视频内写入日期

cvWriteFrame(cv_writer,p_current_frame);

} else motionWrite(p_current_frame, m_opencvimg); //检测并生成视频

此外,当前后帧差异检测的结果达到或超过了预设的报警门限,不仅可录入到本地视频文件,还可发出报警信号;同时还会将画面再记录入一个很短的临时视频文件中(例如长度为10 s),并将这个临时视频文件连同报警信号提交给通信模块。该临时视频文件在记录时每幅图像都可加入年?月?日?时?分?秒格式的时间戳。临时视频文件的长度可以预先设置,该文件在传输后即被删除以节省装置的存储空间。采用这种方式出于3种考虑:首先,自动发出的报警信息可以满足迅速报警的需要,随后发出的短长度临时视频文件可以提供具体的现场图像信息;其次,上述数据量较之在网络上传输整个的视频文件可明显降低通信带宽,节省运行成本;最后,由于传输的过程耗时短,数据被截获的概率低,安全性也有所提高。当用户从管理界面选择了录制功能后,屏幕上将全屏显示出当前采集的图像。并在屏幕的偏下位置显示出一组半透明的按钮:“录像”、“返回”和“节约/正常”。这是考虑到用户可能需要随时调整拍摄模式或停止摄像、暂停录制:点按了“录像”按钮后液晶屏上的图像会被记录入视频文件;点按“返回”后会中止录制返回上级菜单;点按“节约”按钮之后,系统仅仅在记录到物体移动时才记录视频文件,且该按钮上的字符变为“正常”,这时若再点按该按钮,系统将按照常规速度记录视频文件,不再根据是否有物体移动记录视频。图5为录制与检测模块工作时的界面显示。

4 显示模块设计及实现

显示模块有两种工作模式:一种是本地实时监视模式;另一种是视频回放模式。在本地监视模式下,本模块启动后也会检测与摄像头是否连接,如果没有检测到摄像头则会报错退出。检测通过后,来自摄像头的图像被实时显示在彩色液晶屏上。而且操作界面设计成使用户可以在观看监视画面的同时能够随时开始录制视频文件或结束录制,录制视频期间液晶屏实时显示的内容不受录制操作的任何影响。在视频回放模式下,用户可以在图形化菜单中选择以前记录的视频文件并播放,播放的画面显示在液晶屏上,播放时可以根据用户需要随时调整播放速度的快慢,也可以随时暂停播放。

显示模块综合使用了Qt4和OpenCV的库函数。播放过程如下:通过Qt4提供的文件接口函数在制定路径下找到要播放的视频文件。在打开视频文件前先开辟一个内存缓冲区C,将读出的视频数据写入到此缓冲区内。通过在PaintEvent函数中调用函数drawImage将时间戳等字符数据写入到视频缓冲区C内,这一步是实现在Qt4界面内显示图像所必须的步骤。在这一步中还可以根据需要叠加控制按钮到显示画面中。然后C缓冲区的合成视频数据再写入到操作系统的帧缓冲区内,过程如图6所示。在Qt中设置好每秒写入帧缓冲区25帧画面,用户就可以从液晶屏上看到连续运动的图像了。实时显示的过程与播放过程很相似,不同之处是图像数据的来源从视频文件变成了USB摄像头。

打开视频文件及建立缓冲区C的部分代码如下:

capture = cvCaptureFromAVI(qPrintable(avi_file));

frame = cvQueryFrame( capture );

//创建缓冲区C

orig_img = QImage(QSize(frame?>width,frame?>height),QImage::Format_RGB888);

……

paintEvent中的相关代码如下:

void PlayerWidget::paintEvent(QPaintEvent* e)

{

QPainter painter(this);

painter.drawImage(0,0,orig_img); //字符叠加

……

QPainter patr(this); //控制按钮叠加

patr.drawRoundRect(PAUSE_X,BUTTON_Y,BUTTON_W,BUTTON_H);

patr.drawText(PAUSE_X+11,BUTTON_Y+20,QObject::tr("暂停"));

……

}

5 通信模块设计

通信模块使用了socket函数,通过线程机制独立于其他程序运行。模块分成初始化和传输两部分。在摄像模块分配视频缓冲区之后就初始化通信模块。初始化过程首先以函数pthread_create启动了一个独立的线程,该线程调用cvCreateVideoWriter获取被传输视频文件指针,待函数正确返回指针后再建立socket连接,至此初始化过程结束。当摄像模块检测到物体移动后,调用cvWriteFrame在抓取的帧图像中打上时间戳并将其存储为临时视频文件,随后向远端服务器发送连接请求,连接建立后,通过TCP连接传送该文件。在传输结束后再等待一段时间后删除临时文件;之后释放视频文件指针,释放socket连接,最后注销线程。

通信模块的部分代码如下:

//创建视频缓冲区,保存视频文件

snprintf(video_file_name,20,"secondVid.avi",);

cv_2nd_writer = cvCreateVideoWriter(video_file_name,CV_FOURCC('M','P','4','2'),8,size_2nd,1);

cvWriteFrame(cv_2nd_writer,p_current_frame);

……

//连接客户机与服务器

connect(client_socket,(struct sockaddr*)&server_addr, server_addr_length);

strncpy(buffer, video_file_name, strlen(video_file_name)>BUFFER_SIZE?BUFFER_SIZE:strlen(video_file_name));

……

//向服务器端发送视频文件

send(client_socket,buffer,file_block_length,0)

……

//关闭套接口,释放缓冲区

close(client_socket);

cvReleaseVideoWriter(&cv_2nd_writer);

6 结 语

经过测试,证明嵌入式家用视频监控系统达到了预期的功能:既可以按照普通速率录制视频并实时显示在液晶屏上,也可以通过移动检测方式,只记录变化较大的图像;可以通过图形化界面,以触摸方式选择实时录制视频或者查看以前录制的视频。在移动检测方式下,可以报警并将图像通过网络发送给远端服务器。

后续的开发包括:加强移动侦测处理能力,做到能够识别某些特征物;加入镜头移动功能,增大监视范围;增添移动互联网接口,利用手机查看视频文件;增加视频记录格式,支持更多文件格式;丰富图形化界面功能,增添报时、对讲、夜光等功能。

参考文献

[1] Linweig. GSPCA驱动移植介绍[OL].[2010?02?10]. http://blog.csdn.net/linweig/article/details/5305334.

[2] 广州天嵌计算机科技有限公司. TQ2440开发板使用手册[R].广州:天嵌计算机科技有限公司,2009.

[3] 成洁,卢紫毅.Linux窗口程序设计:Qt4精彩实例分析[M]. 北京:清华大学出版社,2008.

[4] 陈莉君.Linux操作系统内核分析[M].北京:人民邮电出版社,2000.

[5] 陈卿,戴仙金,唐玉国.基于Qt/Embedded的新生儿监护仪软件系统设计与实现[J].微计算机信息,2012,28(9):431?432.

[6] 王润民,赵祥模,惠飞,等.基于嵌入式Linux与QT的汽车虚拟仪表设计[J].现代电子技术,2012,35(6):1?4.

[7] BRADSKI Gary, KAEHLER Adrian. Leanring OpenCV [M]. United States: O'Reilly Media, Inc., 2008.

[8] 刘静.基于OpenCV机器视觉库的人脸图像预处理方法研究与实现[J].电子设计工程,2012,20(16):186?187.

[9] 刘馨,马宏峰,王宏斌.基于OpenCV和DirectShow的交通运动目标检测算法研究[J].华东交通大学学报,2012,29(3):21?25.

[10] 黄振峰,陈海平,邓培,等.基于OpenCV与USB工业相机零件检测系统的图像处理研究[J].现代电子技术,2012,35(18):128?132.