摘要:基于ARM9 處理器和嵌入式Linux 操作系統(tǒng),,文章研究了視頻圖像采集與顯示的一般方法,。以USB 攝像頭采集圖像為例,,介紹了Linux 系統(tǒng)下基于Video4Linux 進(jìn)行視頻圖像采集的一般過程,,并且最終通過Qt/Embedded 編寫的圖形界面將采集到的視頻圖像在LCD 上實(shí)時(shí)地顯示出來(lái),。
引言
目前市場(chǎng)上大部分的圖像采集與處理系統(tǒng)是基于DSP 芯片的,,這種圖像采集與處理系統(tǒng)成本高、功耗高,、體積約束等特點(diǎn)并不適用于一些簡(jiǎn)單的應(yīng)用,。隨著USB 攝像頭的普及和基于ARM 的嵌入式芯片的快速發(fā)展,將二者結(jié)合的便攜性越來(lái)越受人們歡迎,。本文介紹了一種基于三星S3C2440A 芯片的嵌入式USB 攝像頭圖像采集與顯示方案,,該方案具有良好的可移植性和擴(kuò)展性,并且成本,、大小和實(shí)時(shí)處理都能夠滿足市場(chǎng)需求,。
1 系統(tǒng)架構(gòu)
系統(tǒng)通過當(dāng)前市場(chǎng)上應(yīng)用最廣泛的中芯微公司生產(chǎn)的zc301p 芯片的USB 攝像頭進(jìn)行圖像采集,然后將圖像信息傳送到ARM 芯片中進(jìn)行處理,,最終通過基于Qt/Embedded 編寫的圖形顯示程序在LCD 上實(shí)時(shí)顯示,。系統(tǒng)的整體架構(gòu)如圖1 所示。
2 視頻圖像采集
系統(tǒng)采用中芯微公司生產(chǎn)的zc301p 芯片的USB 攝像頭作為圖像采集設(shè)備,,并介紹了基于Video4Linux 編程協(xié)議進(jìn)行視頻圖像采集的一般過程,。
2.1 USB 攝像頭驅(qū)動(dòng)
Linux 內(nèi)核能夠很好地支持OHCI(開放式主機(jī)控制接口協(xié)議),,并且能夠很好地支持包括OV511系列攝像頭在內(nèi)的各種各樣的USB 設(shè)備,但是并不包括zc301pUSB 攝像頭,。直到后來(lái)2.6.27 版本左右的內(nèi)核中才增加了針對(duì)zc301 系列芯片的驅(qū)動(dòng),,統(tǒng)稱為L(zhǎng)inux UVC.本文采用的是Linux2.6.32.2 版本內(nèi)核,只需要對(duì)內(nèi)核進(jìn)行簡(jiǎn)單的配置,,就可以實(shí)現(xiàn)功能了,。
在配置菜單選項(xiàng)中,設(shè)備驅(qū)動(dòng)是最重要的配置項(xiàng),。選擇的配置項(xiàng)如下:
Device Drivers - - - >
Multimedia devices - - - >
Video For Linux
Enable Video For Linux API 1(DEPRECAteD)
Video capture adapters - - - >
V4L USB devices - - - >
USB Video Class (UVC)
UVC input events device support
GSPCA based webcams - - - >
ZC3XXX USB CAMEra Driver
USB ZC0301 [P]Image Processor and Control
Chip support
現(xiàn)在,,內(nèi)核被配置成可以支持Video4Linux 的視頻接口,并且加入了支持zc301pUSB 攝像頭的驅(qū)動(dòng)程序,。
2.2 基于Video4Linux 的視頻圖像采集程序設(shè)計(jì)
Video4Linux(簡(jiǎn)稱V4L)為目前市場(chǎng)常見的電視捕獲卡和并口及USB 口的攝像頭提供統(tǒng)一的編程接口,。在Linux 內(nèi)核中它為用戶空間提供統(tǒng)一的編程接口,V4L 分為兩層:底層是音頻和視頻設(shè)備驅(qū)動(dòng)程序的內(nèi)核,;上層為系統(tǒng)提供一些API 接口信息,。視頻圖像采集流程如圖2 所示。
?。?)打開視頻設(shè)備,。
在Linux 中視頻設(shè)備是被作為設(shè)備文件來(lái)執(zhí)行的,本文USB 攝像頭的設(shè)備文件名為/dev/video0.
int my_v4l_open (char*dev,,my_v4l_STruct*vd) 函數(shù)用于打開視頻設(shè)備并初始化攝像頭設(shè)備,該函數(shù)調(diào)用open 函數(shù)可以讀設(shè)備文件,,成功返回設(shè)備描述符,,失敗返回- 1.主要程序代碼如下:
int my_v4l_open(char*dev,my_v4l_struct*vd){
if((vd- >fd=open(vd- >videodevice,,O_RDWR))= =- 1){
printf(“ERROR opening V4L interface”),;
exit(1);}
……}
?。?)讀設(shè)備信息,。
int my_v4l_get_capability (my_v4l_struct*) 函數(shù)的功能是讀取設(shè)備基本信息, 它利用ioctl(vd_fd,,VIDIOCGCAP,,&(vd- >capability) 來(lái)讀取有關(guān)攝像頭的信息。該函數(shù)成功返回后將這些信息從內(nèi)核空間拷貝到用戶程序空間capability 各成員分量中,,使用printf 函數(shù)就可得到各成員分量信息,。具體如下:
int my_v4l_get_capability(my_v4l_struct*){
if(ioctl(vd- >fd,VIDIOCGPICT,,&(vd- >capability))<0){
printf(“error:v4l_get_capability\n”),;
exit(1),;}
return 0;}
(3)視頻圖像采集,。
本文通過mmap 方式來(lái)采集視頻圖像信息,。為了獲得映射的幀緩沖信息,my_v4l_mmap_init(my_v4l_struct*)函數(shù)需先初始化緩沖區(qū),,并進(jìn)行內(nèi)存與緩沖區(qū)的綁定,,其中函數(shù)mmap 用于將文件fd與video_mbuf 綁定實(shí)現(xiàn)映射,函數(shù)mmap()返回值是系統(tǒng)實(shí)際分配的起始地址,。函數(shù)my_v4l_mmap_init()的部分代碼實(shí)現(xiàn)如下:
void my_v4l_mmap_init(my_v4l_struct*vd){
……
ioctl(vd- >fd,,VIDIOCGMBUF,&(vd- >mbuf)),;// 初始化video_mbuf 以得到所映射的buffer的信息
vd- >pframebuffer= (unsigned char*)mmap (0,,
vd- >videombuf.size,
PROT_READ|PROT_WRITE,,MAP_SHARED,,vd- >fd,0),;
/* 把文件fd 與video_mbuf 綁定,,實(shí)現(xiàn)映射*/
vd- >mmapsize=vd- >videombuf.size;
vd- >vmmap.height=vd- >hdrheight;
vd- >vmmap.width=vd- >hdrwidth;
vd- >vmmap.format=vd- >formaTIn;
vd- >vmmap.frame=0;
……}
然后利用驅(qū)動(dòng)程序的ioctl () 函數(shù)的VIDIOCMCCAPTURE 和VIDIOCSYNC 命令來(lái)獲取圖像。其中ioctl (vd- >fd,,VIDIOCMCAPTURE,,&(vd- >mmap)) 開始一幀圖像的采集,是非阻塞的,;ioctl(vd- >fd,,VIDIOCSYNC,&frame)用于判斷一幀圖像采集過程結(jié)束與否,,frame 是當(dāng)前采集的幀的序號(hào),。
采集工作結(jié)束后調(diào)用munmap 取消文件fd 與video_mbuf 的綁定。
munmap(vd- >map,,vd- >mbuf.size),;
(4)關(guān)閉設(shè)備在視頻采集完成后,,必需關(guān)閉視頻設(shè)備,。
close(vd- >fd);
3 基于Qt/Embedded 圖像顯示程序的編寫
基于嵌入式Linux 常見的GUI 系統(tǒng)有MiniGUI,、MicroWindows,、OpenGUI和基于Framebuffer[5]的Qt/Embedded[4].Qt 是諾基亞開發(fā)的一個(gè)跨平臺(tái)的C++ 圖形用戶界面應(yīng)用程序框架,它提供給應(yīng)用程序開發(fā)者建立藝術(shù)級(jí)的圖形用戶界面所需的功能,,并且是完全面向?qū)ο蟮?,很容易擴(kuò)展,,允許真正的組件編程。正是基于以上優(yōu)點(diǎn),,本文采用Qt/Embedded 開發(fā)平臺(tái),,并將基于Qt 的圖形界面Qtopia 移入我們的文件系統(tǒng)中。
為了避免由于圖像數(shù)據(jù)量大而在目標(biāo)板上顯示閃爍的問題,,本文采用雙緩沖技術(shù)實(shí)現(xiàn)采集圖像顯示,,采用的是QPixmap 對(duì)象。QPixmap 是Qt 為圖像處理提供的類,,主要用于圖像的繪制,。實(shí)現(xiàn)雙緩沖時(shí),先把要顯示的內(nèi)容繪制在這個(gè)QPixmap pixmap 對(duì)象上,,然后再用一步操作把pixmap 繪制在屏幕上,。基于Qt 圖像顯示及輔助框線繪制的部分代碼段如下:
QPixmap pix (width (),,height ()),;// 定義一個(gè)QPixmap 用于在上面繪制圖像及框線
QPainter p(&pix);// 定義繪制工具
QPainterQPen pen (yellow,,3,,DotLine);// 定義一個(gè)畫筆的屬性,,如顏色,、粗細(xì)、線條樣式
p.drawImage (0,,0,,img);// 把攝像頭采集到的圖像繪制到QPixmap 上
p.setPen(pen),;// 設(shè)置畫筆屬性
p.moveTo(50,,330),;// 設(shè)置畫筆筆尖起始位置
p.lineTo(150,,50);// 開始繪制框線
p.lineTo(490,,50),;
…略
p.end();// 在QPixmap 上的所有繪制任務(wù)結(jié)束
p.begin(this ),;// 準(zhǔn)備把QPixmap 繪制到屏幕上
p.drawPixmap (0,,0,pix),;// 繪制QPixmap 到屏幕操作,,圖像顯示到LCD 上
圖像數(shù)據(jù)的連續(xù)采集和顯示是通過定時(shí)器實(shí)現(xiàn)的,,QTimer 類提供了定時(shí)器信號(hào)和單觸發(fā)定時(shí)器。設(shè)置定時(shí)啟動(dòng)觸發(fā)周期,,每當(dāng)定時(shí)器時(shí)間到就觸發(fā)一個(gè)定時(shí)器事件,,在事件中調(diào)用VIDIOCMCAPTURE 函數(shù)完成對(duì)圖像的采集,并通過QPixmap 類將圖像顯示到LCD上,。至此就可以通過基于Qt 編寫的圖形界面程序,,將USB 攝像頭采集的視頻圖像在LCD 上實(shí)時(shí)顯示。
4 結(jié)論
本文基于ARM9 處理器和嵌入式Linux 操作系統(tǒng),,詳細(xì)介紹了一種USB 攝像頭圖像采集與顯示的通用方法,。Linux 代碼完全開源,系統(tǒng)具有良好的移植性,,可方便地進(jìn)行各種擴(kuò)展,,采用Qt 進(jìn)行人機(jī)界面的設(shè)計(jì)能夠極大地節(jié)省開發(fā)成本和周期。本方案經(jīng)推廣可用于工業(yè)控制,、智能交通,、小區(qū)監(jiān)控等領(lǐng)域。