摘 要: 以嵌入式ARM为硬件平台,以ARM-Linux" title="ARM-Linux">ARM-Linux为软件平台,在QT/Qtopia" title="QT/Qtopia">QT/Qtopia图形用户界面下,通过调用OpenCV" title="OpenCV">OpenCV图形处理库设计摄像头应用程序,最终实现把摄像头采集到的视频流数据显示在Qtopia图形用户界面窗体上。介绍了QT编程的基本原理,阐述了OpenCV图像处理库的工作机制与使用方法。
关键词: 嵌入式系统" title="嵌入式系统">嵌入式系统;ARM-Linux;QT/Qtopia;OpenCV
随着计算机和微电子技术的迅速发展,嵌入式ARM及ARM-Linux操作系统已广泛应用于工业控制、通信、医疗仪器等各个领域。许多公共场所和居民小区等地点都安装了视频监控系统,因而视频监控与显示终端的应用越来越广泛。于是,如何以更高的效率和更低的成本设计视频监控设备的硬件和软件就成为广大研发人员关心的问题。
本文以嵌入式ARM作为硬件核心,在ARM-Linux QT/Qtopia图形操作系统下开发摄像头应用程序,实现摄像头对视频图像数据的采集、处理与显示。为了提高应用程序的开发效率,本设计采用了OpenCV图形处理库。摄像头视频显示的流程为:首先ARM-Linux通过摄像头驱动程序控制摄像头采集视频流数据,然后利用摄像头应用程序对采集到的视频流数据进行处理,最终使经过处理的视频流数据能够在LCD屏上显示。采用上述平台具有以下优点:(1)ARM-Linux与OpenCV库同为开源的免费软件,开发者不仅可以根据需要修改源代码来提高软件开发的灵活性,而且可以节约开发成本;(2) OpenCV库提供了许多视频图像处理的函数,因此开发者不需要花费大量的时间自己编写,可以提高软件的开发效率;(3)OpenCV库中大部分函数都经过汇编优化,基于OpenCV的程序运行起来有更高的效率。
视频监控与显示系统的硬件和软件结构如图1所示。
硬件由三部分组成:(1)摄像头。负责采集原始视频流数据;(2)ARM开发板。负责处理原始的视频流数据;(3)LCD液晶显示器。负责图像数据的显示。软件部分也由三部分组成,这三部分运行在ARM-Liunx操作系统下:(1)摄像头驱动程序;(2)摄像头应用程序。控制在ARM板把摄像头采集到的视频流数据读入内存中,然后对内存中的图像数据进行处理,即把原始图像数据转化为可以在ARM-Linux QT/Qtopia操作系统下显示的图像数据;(3)LCD显示驱动程序。本文将着重阐述运行在ARM-Linux QT下的摄像头应用程序。
1 嵌入式系统应用程序开发方法
1.1 硬件平台
嵌入式系统开发平台由主机PC机和目标机ARM板组成。
主机PC要求CPU为Pentium 4或以上,拥有一个25针的并口、一个9针的RS-232串口和一个20GB的硬盘。ARM板是由深圳市武耀博德信息技术有限公司生产的270-S平台。
1.2 软件开发平台
软件程序的开发是在PC机上完成的,PC机上的开发环境是Redhat Linux 9.0。Redhat提供了许多与程序开发有关的工具,还要在PC机的Linux操作系统下安装QT和OpenCV软件工具包。
(1)QT软件包。包括QT/X11 2.3.2库、QT/Embedded 2.3.2库、Qtopia 1.7.0库、uic工具、qmake工具、tmake工具和QT designer工具等。
(2)OpenCV软件包。包括Libhighgui.so.0.9.7、Libhighgui.la、Libcxcore.so.0.9.7和Libcxcore.la等主要的库。
在开发摄像头应用程序之前,要把u-boot、ARM-Linux操作系统和外部设备的驱动程序移植进入ARM目标板270-S中,这样主机PC上开发的各类应用程序软件才能在ARM目标板上运行。
2 摄像头应用程序的构架与关键技术
2.1 摄像头应用程序的结构
应用程序由两部分构成:
(1)在ARM-Linux QT/Qtopia图形操作系统下的窗口界面设计(即人机界面的设计)。这部分是通过调用QT/Embedded库的各种库函数与窗口组件来完成的。
(2)对视频流数据进行处理,并把处理完成的图像数据显示在QT/Qtopia图形界面下。这部分设计是摄像头应用程序的核心,除了调用QT/Embedded库函数,还要调用OpenCV库函数。
摄像头应用程序结构图与库函数的调用关系如图2所示。
2.2 摄像头应用程序的关键技术
本设计应用程序以OpenCV库和QT库为核心,负责处理视频数据与图像显示。
2.2.1 OpenCV简介
开放源代码的计算机图像处理库OpenCV(Intel Open Source Computer Vision Library)是由一些C函数和C++类所组成的库,用来实现图像处理及计算机图像算法。OpenCV可以与英特尔公司所开发的图形处理库IPL兼容,所以它能够高效而充分地运行在Intel处理器上,主要用于对图像进行高级处理,例如特征检测与跟踪、运动分析及3D重建等。
2.2.2 嵌入式QT与Qtopia简介
QT是跨平台C++图形用户界面工具。由于QT采用面向对象开发,具有跨多平台、界面设计美观等特点,得到广泛应用。因为KDE等项目使用QT作为支持库,所以有许多基于X-Windows的PC机上的应用程序可以非常方便地移植到QT上。
Qtopia是由Trolltech公司开发的基于QT库的消费电子设备综合应用平台。Qtopia包含完整的应用层、灵活的用户界面、窗口操作系统、应用程序启动程序以及开发框架,并具有游戏和多媒体、工作辅助应用程序、同步框架、PIM应用程序、Internet应用程序等。本设计应用程序显示在Qtopia中。
3 QT窗体的设计方法
在QT编程中,有两种设计程序窗体(即人机界面)的方法。第一种方法完全采用面向对象的C++编程语言实现,开发者需要手工编写所有的代码;另一种是采用编写代码与QT Designer设计工具相结合的方法。QT Designer工具会帮助开发者完成大部分绘制窗体的工作。本文摄像头应用程序的设计采用第二种方法。QT Designer是QT系统专用的窗口界面开发工具,它不包含任何编译器,而仅仅提供一个可视化界面编辑器。QT Designer将编辑完成的窗体界面通过XML保存为.ui文件,然后由专用的uic界面编译器将其转换为标准C++的源文件。
4 视频图像处理与显示
视频图像处理与显示的过程如图3所示。
其过程主要由四步组成。
(1)初始化视频结构。关键代码:
CvCapture*capture=0;
capture=cvCaptureFromCAM(-1);
cvSetCaptureProperty
(capture,CV_CAP_PROP_FRAME_WIDTH,320);
cvSetCaptureProperty
(capture,CV_CAP_PROP_FRAME_HEIGHT,240);
在OpenCV应用程序中都要定义一个CvCapture类型的指针变量capture。CvCapture类是视频获取结构,它没有公共接口,各类图像数据存储位置的头地址都可以赋值给指针变量capture。在capture指针被赋值之后,可以作为其他图像处理函数的参数使用,完成各种图像处理功能。
OpenCV库中用CvCapture*cvCaptureFromCAM(int index)函数对摄像头分配视频图像数据流和初始化CvCapture结构。函数参数index为摄像头索引值。如果系统只有一个摄像头或者使用哪个摄像头都无所谓,则index的值为-1。本设计开发板只连接一个摄像头,因此代码为capture=cvCaptureFromCAM(-1)。
对视频数据结构capture设置参数。用到的OpenCV的库函数为int cvSetCaptureProperty(CvCapture* capture,int property_id,double value)。参数capture指定哪个视频获取结构需要设置参数;property_id为属性标识符,由几个固定值组成,用来决定设置哪个参数。
(2)开启定时器后抓取图像帧
关键代码:
QTimer CameraTimer->start(50,false);
int cvGrabFrame(capture);
IplImage*frame=cvRetrieveFrame(capture);
如果视频结构初始化成功,则开启由QT库提供的QTimer定时器。代码表示为:CameraTimer->start(50,false)。参数“50”表示QT定时器每隔50 ms触发一次,即发出一个内部信号调用一个槽函数,该槽函数负责从视频数据流中抓取一帧图像。
该槽函数抓取一帧图像的方法为:首先调用OpenCV库函数int cvGrabFrame(CvCapture*capture);从摄像头实时采集的视频流中快速抓取一帧图像数据,并且把这帧图像数据存入ARM板的缓存中,这帧图像数据对于用户是不可见的。采用这种机制,是因为cvGrabFrame()可以把一帧图像数据以最快的速度存入缓存中[1]。
接下来,调用OpenCV库函数cvRetrieveFrame()。这个函数把刚刚通过cvGrabFrame()抓取的一帧图像数据从内部缓存重新读取出来。具体代码为:IplImage*frame=cvRetrieveFrame(capture)。事实上在调用这个函数后,OpenCV内部会完成多步复杂的图像处理的工作,例如解码等。
(3)视频格式的转化
关键代码:
for(int y=0;y<height;y++)
{ for(int x=0; x<width; x++)
{ for(int i=0;i<3;i++)
{*dst++=*frame->imageData++;}
*dst++=0;}}
由于cvRetrieveFrame()重新读取到的一帧图像数据是IplImage类型,IplImage类型是24位真彩的三通道BGR(BGR24),而QT库内与图像处理与显示相关的函数只支持对1 bit、8 bit或者32 bit的位图进行处理[2]。因此为了使IplImage类型帧图像能够在QT/Qtopia图像界面中显示,又不降低视频图像质量,需要通过程序将24位(BRG24)帧图像转化为32位(BRG32)帧图像。
BGR32每一个像素点除了拥有与BGR24相同的红绿蓝三种颜色,每种颜色8 bit外,要还在这三种颜色共24 bit的数据后面添加一组长度为8 bit的0数据。因此,图像格式转化的方法应该在原始的24位图像数据中每隔三个字节加入一个字节的0。下列代码为BGR24->BGR32图像中一个点的转化程序,其中frame->imageData为原始图像的指针,dst为转化后图像的指针。
for(int i=0;i<3;i++)
{*dst++=*frame->imageData++;}
*dst++=0;
(4)将视频图像数据显示在QT/Qtopia图形界面
关键代码:
QImage image=QImage((uchar*)image32,frame->width,
frame->height,32,NULL,0,QImage::LittleEndian);
QPainter display(picCamera);
display.drawImage(0,0,image);
首先调用QImage构造函数把上一步转换好的32位(BGR32)图像数据初始化为QT图像数据格式;然后调用QT的低水平绘制类QPainter的构造函数对主窗口的显示器组建初始化;初始化结束后将调用QPainter类的drawImage成员函数,把通过QImage类转换过的图像数据image绘制在主窗体的显示器中,代码为QPainter.drawImage(0,0,image)。
通过以上步骤,应用程序最终将摄像头采集到的视频图像数据显示在嵌入式设备的QT/qtopia图形界面中。
ARM平台的手持移动监控与显示终端设备已经广泛应用于社会的各个领域。OpenCV图像处理库以其开源性、高效性、灵活性帮助开发者大幅度地缩减开发周期。ARM-Linux QT/Qtopia与其他ARM端的图像界面操作系统相比较有免费、移植性好、内核精简、更加稳定的特点。本设计以OpenCV图像处理库为核心,在ARM Linux QT/Qtopia图形界面操作系统下实现摄像头显示的应用程序,有非常好的实用性,可以广泛应用于各类ARM终端设备中。
参考文献
[1] BRADSKI G, KAEHLER A. Learning openCV: computer vision with the OpenCV library. O’Reilly Media, 2008, 9.
[2] Trolltech公司.Qtopia和Qt/Embedded参考文档[OL]. http://www. qiliang. net/qt/index. html, 2005.
[3] 韦东山.嵌入式Linux应用开发完全手册.北京:人民邮电出版社,2008.