摘 要:隨著USB攝像頭的普及以及Linux系統(tǒng)桌面應(yīng)用的推廣,基于Linux系統(tǒng)的視頻播放程序設(shè)計有著現(xiàn)實應(yīng)用的意義。采用應(yīng)用編程接口Video4Linux2所提供的數(shù)據(jù)結(jié)構(gòu)、應(yīng)用函數(shù)等,實現(xiàn)在Linux環(huán)境下USB攝像頭圖像數(shù)據(jù)的采集功能,并運用GTK庫顯示和播放其視頻圖像。運用Linux標準庫函數(shù)實現(xiàn)了數(shù)字圖像的采集,對基于Linux內(nèi)核的后續(xù)圖像應(yīng)用開發(fā)具有實用意義。該程序采用Linux系統(tǒng)下新的視頻編程接口和標準庫函數(shù),以模塊化結(jié)構(gòu)實現(xiàn)所需功能,具有良好移植性,基于此平臺可方便加入圖像處理等其他應(yīng)用模塊。
關(guān)鍵詞:Video4Linux2;圖像采集;攝像頭;GTK;顯示播放
中圖分類號:TP31681文獻標識碼:B
文章編號:1004-373X(2008)24-093-03
Programming for the Display of USB Camera on the Linux System
CHEN Liang,PEI Hailong,WU Yue
(College of Automation Science and Engineering,South China University of Technology,Guangzhou,510640,China)
Abstract:With widely and rapidly using of USB camera and the popularization of Linux system desktop,it′s meaning to program for the display video on the Linux system.This paper makes use of the data configuration and the application function which belongs to Video4Linux2 application programming interface,capturing the video picture of the USB camera on the Linux system,and displaying it with GTK are implemented.Programming for the capture of image data on the standard library of Linux,it is usefully significative to exploit the application of image on the Linux kernel.This program uses new API of video and standard library on the Linux,the function is achieved by modularize structure so that it can be transplanted easily and added to other application module such as image processing.
Keywords:Video4Linux2;image acquisition;camera;GTK;display
所述程序基于Linux系統(tǒng)平臺,結(jié)合Video4Linux2應(yīng)用編程接口進行USB攝像頭視頻圖像采集,并運用GTK函數(shù)庫將視頻圖像實時顯示播放,在此程序基礎(chǔ)上可以方便地進行圖像識別、視覺導(dǎo)航等應(yīng)用的二次開發(fā)。Video4Linux2是Video For Linux Two的簡稱,其為Linux系統(tǒng)下視頻音頻的采集及輸出等應(yīng)用編程提供內(nèi)核接口。Video4Linux2是Video For Linux API的第二版本,相較于Video4Linux其改變甚多,在數(shù)據(jù)結(jié)構(gòu)定義和函數(shù)使用上都有很大的變化,在性能上得到很大提高的同時,也使得其并沒有向下兼容Video4Linux,給應(yīng)用程序的升級維護制造了很大的麻煩。目前在2.5以上的內(nèi)核版本中,系統(tǒng)均已默認支持Video4Linux2 API。
GTK全稱為GIMP Tool Kit,即GIMP工具包,是用于實現(xiàn)圖形用戶界面的函數(shù)庫,已經(jīng)發(fā)展為Linux下開發(fā)圖形界面應(yīng)用程序的主流開發(fā)工具之一。在本程序設(shè)計中與采集圖像數(shù)據(jù)后,運用GTK函數(shù)庫,最終實現(xiàn)在桌面上攝像頭圖像的連續(xù)顯示播放。
1 攝像頭驅(qū)動程序加載
在Linux下,所有的外設(shè)均被看成是一種特殊文件進行處理,稱之為設(shè)備文件。系統(tǒng)調(diào)用及各種函數(shù)庫直接或間接地提供了內(nèi)核和應(yīng)用程序之間的接口,而設(shè)備驅(qū)動程序則是內(nèi)核和外設(shè)之間的接口,它完成設(shè)備的初始化和釋放、對設(shè)備文件的各種操作和中斷處理等功能。由于屏蔽了外設(shè)硬件的細節(jié),使得應(yīng)用程序可以像普通文件一樣對外設(shè)進行操作而無需關(guān)注其具體的細節(jié)。在本程序設(shè)計中將對設(shè)備文件/dev/video0進行視頻圖像采集,其中0表示第一個視頻設(shè)備的編號,以此類推。
這里使用羅技快看系列中Communicate Deluxe型號的USB攝像頭進行視頻圖像采集,采用Linuxuvc驅(qū)動程序,這是一個為USB視頻設(shè)備提供驅(qū)動的開源項目,支持Video4Linux2應(yīng)用編程接口,具體步驟如下:
(1) 下載和安裝Linuxuvc驅(qū)動程序,并將生成的模塊文件Linuxuvc.ko復(fù)制至/lib/modules/′uname-r′/kernel/drivers/media/video目錄下;
(2) 在終端使用命令“modprobe linuxuvc”加載驅(qū)動模塊,或者在其安裝目錄下使用命令“insmod linuxuvc.ko”加載也可。
2 GTK主程序設(shè)計
GTK應(yīng)用程序采用事件驅(qū)動機制,在完成用戶界面創(chuàng)建后進入Gtk_main()主循環(huán),由此GTK接管了控制權(quán),然后在主循環(huán)中循環(huán)地監(jiān)聽事件和信號的發(fā)生。當捕獲事件或信號后,則將控制權(quán)傳遞至所注冊的信號事件處理程序進行處理,然后根據(jù)此程序選擇返回或者退出GTK應(yīng)用程序。同時,視頻圖像的截取和顯示播放也是一個循環(huán)。在本程序中采取將視頻圖像讀取及顯示模塊(Cam_show())注冊為GTK空閑函數(shù),由此使得每次通過GTK主循環(huán)后都將調(diào)用此模塊,讀取和顯示一幀圖像。主程序的流程設(shè)計如圖1所示。
3 視頻設(shè)備初始化模塊設(shè)計
在Linux系統(tǒng)下視頻設(shè)備的圖像數(shù)據(jù)采集是基于Video4Linux2應(yīng)用編程接口的,通過使用接口提供的有個數(shù)據(jù)結(jié)構(gòu)定義和函數(shù)庫,對攝像頭進行初始化。下面對主要步驟以及所用到的關(guān)鍵函數(shù)進行介紹。
3.1 打開視頻設(shè)備文件
int fd;
fd =open(\"/dev/video0\",O_RDWR);
利用open函數(shù)打開視頻設(shè)備后,可以獲取相應(yīng)的文件描述符;若打開失敗,則要求返回相應(yīng)的錯誤信息。在實際的程序設(shè)計中,必須加入類似的出錯處理,以方便程序調(diào)試。
3.2 獲取視頻設(shè)備相關(guān)屬性
struct v4l2_capability cap;
ioctl (fd,VIDIOC_QUERYCAP, cap)
在Linux程序設(shè)計中ioctl調(diào)用有點像是大雜燴,它提供了一個用于控制設(shè)備及其描述符行為和配置底層服務(wù)的接口,對設(shè)備的I/O通道進行管理。終端、文件描述符、套接字甚至磁帶機都可以使用為它們定義的ioctl,在Video4Linux2中也是通過ioctl函數(shù)對設(shè)備進行編程的。其原型為:int ioctl(int fildes,int cmd,…);ioctl對描述符fildes指定的對象執(zhí)行cmd參數(shù)中給出的操作,根據(jù)具體函數(shù)還可能有一個可選的第三參數(shù)。如上所示,利用VIDIOC_QUERYCAP來取得設(shè)備文件的屬性參數(shù)并存儲于cap結(jié)構(gòu)中,然后就可以讀取設(shè)備的關(guān)鍵屬性。在此應(yīng)用中,攝像頭設(shè)備顯示支持視頻截取和流操作,但不支持讀寫操作。
3.3 設(shè)置圖像采集格式
struct v4l2_format fmt;
fmt.fmt.pix.width=640;
fmt.fmt.pix.height=480;
fmt.fmt.pix.pixelformat=V4L2_PIX_FMT_YUYV;
ioctl(fd,VIDIOC_S_FMT, fmt)
將fmt結(jié)構(gòu)填入適當?shù)闹?,然后通過傳遞VIDIOC_S_FMT命令參數(shù)對設(shè)備的圖像采集格式、大小等進行初始化。在程序測試中顯示此設(shè)備不能初始化為GTK能直接顯示的RGB格式,因此在其后的圖像處理中首先將YUYV格式轉(zhuǎn)為RGB格式,這些內(nèi)容將在文章的第五節(jié)詳述。
3.4 內(nèi)存映射初始化
在Video4Linux2下截取圖像有2種方法:mmap內(nèi)存映射方式和直接讀取設(shè)備方式。在屬性檢驗中可知此設(shè)備不支持讀寫操作,而且前者采用共享內(nèi)存通信,不需要任何數(shù)據(jù)的拷貝,效率高,因此選用mmap內(nèi)存映射方式,這也是程序設(shè)計中的一個難點,其用到的主要函數(shù)如下:
Ioctl (fd,VIDIOC_REQBUFS, reqbuf);
ioctl (fd,VIDIOC_QUERYBUF,buffer);
void *mmap (NULL,size_t len,int prot,int flags,fd,off_t off);
ioctl (fd,VIDIOC_QBUF,buf);
ioctl (fd,VIDIOC_STREAMON,type);
與最初的Video4Linux應(yīng)用編程接口相比,新的接口最大的改變在于可自定義設(shè)備驅(qū)動緩存數(shù)量,在實際應(yīng)用中大大提供了程序的性能。其主要步驟如下:首先,帶VIDIOC_REQBUFS命令參數(shù)的ioctl函數(shù)分配自定義的緩存數(shù)量,這在初始化中是必須的一步;然后,可以引入一個循環(huán)中,分別對各個緩存進行映射,其偏移量和緩存大小可在VIDIOC_QUERYBUF命令參數(shù)的ioctl函數(shù)中定義;最后利用用mmap()函數(shù)將在設(shè)備緩存和應(yīng)用程序所分配內(nèi)存間建立映射,并返回應(yīng)用程序內(nèi)存的首地址,至此內(nèi)存映射初始化完畢。
在內(nèi)存映射完畢后,此時還不能開始進行圖像采集,下面兩個步驟提示系統(tǒng)將使用這些內(nèi)存進行圖像采集。首先,VIDIOC_QBUF命令參數(shù)的ioctl函數(shù)將此空緩存加入等待輸入緩存隊列;在緩存加入等待輸入隊列后,調(diào)用1次VIDIOC_STREAMON命令參數(shù)的ioctl函數(shù),由此可以正式使用這些緩存進行圖像數(shù)據(jù)了。
4 YUYV格式與RGB格式的轉(zhuǎn)換
顯示器顯示色彩的原理與彩色電視機一樣,都是采用R(Red),G(Green),B(Blue)相加混色的原理:通過發(fā)射出3種不同強度的電子束,使屏幕內(nèi)側(cè)覆蓋的紅、綠、藍磷光材料發(fā)光而產(chǎn)生色彩。這種色彩的表示方法稱為RGB色彩空間表示,這也是多媒體計算機技術(shù)中用得最多的一種色彩空間表示方法。在本程序中使用的RGB24使用24位來表示1個像素,RGB分量都用8位表示,取值范圍為0~255。
YUV是被歐洲電視系統(tǒng)所采用的一種顏色編碼方法(屬于PAL),其中“Y”表示明亮度,也就是灰階值;而“U”和“V” 表示的則是色度,作用是描述影像色彩及飽和度,用于指定像素的顏色。與RGB視頻信號傳輸相比,它最大的優(yōu)點在于只需占用極少的頻寬(RGB要求3個獨立的視頻信號同時傳輸)。YUYV是YUV格式的其中一種,YUV比例為4∶2∶2,它為每個像素保留Y分量,而UV分量在水平方向上每2個像素采樣一次。一個宏像素為4個字節(jié),實際表示2個像素。(4∶2∶2的意思為1個宏像素中有4個Y分量、2個U分量和2個V分量。)圖像數(shù)據(jù)中YUV分量排列順序如下:
Y0 U0 Y1 V0 Y2 U2 Y3 V2…
前面提到攝像頭只能初始化為YUYV圖像格式,而在GTK顯示區(qū)域中可以顯示RGB格式的圖像數(shù)據(jù)。因此在顯示之前必須進行圖像數(shù)據(jù)處理,將YUYV格式轉(zhuǎn)換為RGB24,轉(zhuǎn)換公式為:
R=1.164*(Y-16)+1.159*(V-128);
G=1.164*(Y-16)-0.38*(U-128)-
0.813*(V-128);
B=1.164*(Y-16)+2.018*(U-128)
5 圖像采集模塊設(shè)計
這個模塊的進程主要有3個步驟:首先,VIDIOC_DQBUF命令參數(shù)的ioctl函數(shù)將已填滿圖像數(shù)據(jù)的緩存清空出列;其次,此時與之映射的應(yīng)用程序內(nèi)存已經(jīng)儲存圖像數(shù)據(jù),可以對其進行圖像數(shù)據(jù)處理操作,將YUYV格式轉(zhuǎn)為RGB24格式,使用GTK函數(shù)將圖像數(shù)據(jù)寫入圖像顯示區(qū)域,顯示播放出這一幀的圖像;最后,將出列的空緩存重新加入等待輸入隊列,由此構(gòu)成一個采集循環(huán)。
正如前面所提到的那樣,GTK主循環(huán)在接管控制權(quán)后,將循環(huán)監(jiān)聽和響應(yīng)事件或信號并選擇返回或退出,而圖像采集模塊也需要循環(huán)地采集圖像幀,一般來說這種情況下可以采用多線程編程的方法使主程序具有多個執(zhí)行路線,同步運行兩個循環(huán)。GTK庫提供了一個更為簡單的方法:使用空閑函數(shù)。每次通過GTK主循環(huán)后都將調(diào)用1次空閑函數(shù)(如果有),由此實現(xiàn)應(yīng)用程序和GTK主循環(huán)的處理進程之間的共享,可以方便地在應(yīng)用程序中進行數(shù)據(jù)更新、傳送等,同時同步地處理GTK系統(tǒng)事件,如窗口發(fā)布、界面的同步刷新等。
在這個程序中正是應(yīng)用這個方法,將采集模塊注冊為GTK空閑函數(shù),每次通過GTK主循環(huán)后都將調(diào)用模塊。在GTK主函數(shù)和采集模塊中必須調(diào)用GTK提供的線程控制函數(shù),這是由于空閑函數(shù)是在GTK主循環(huán)外即在GTK控制鎖之外執(zhí)行的。在某一時間只有1個線程能夠使用GTK函數(shù),因此必須保證在任何時候只有GTK主程序和采集模塊之其一在使用GTK函數(shù)。在每個循環(huán)中,采集模塊讀取圖像數(shù)據(jù)并寫入圖像顯示區(qū)域,GTK主程序進行窗口的更新,最終實現(xiàn)實時連續(xù)地顯示播放視頻圖像。
6 結(jié) 語
該程序在Linux系統(tǒng)環(huán)境下實現(xiàn)了使用USB攝像頭采集視頻圖像并連續(xù)顯示播放的功能,主要涉及使用了Video4Linux2應(yīng)用編程接口和GTK函數(shù)庫,以及一些Linux程序設(shè)計中基本的系統(tǒng)調(diào)用或標準庫函數(shù),在類Linux系統(tǒng)中具有良好的移植性。此外,本程序結(jié)構(gòu)比較簡單,組織清晰,可以方便地加入各種圖像處理模塊,進一步實現(xiàn)圖像處理、識別等所需功能。
參考文獻
[1]馮琪.小型無人直升機基于視覺的導(dǎo)航系統(tǒng)分析與設(shè)計[D].廣州:華南理工大學(xué),2005.
[2]羅沛.空中機器人視覺導(dǎo)航系統(tǒng)的研究與設(shè)計[D].廣州:華南理工大學(xué),2007.
[3]Syd Logan,戰(zhàn)曉蘇,王寧.Gtk+程序設(shè)計(C語言版)[M].北京:清華大學(xué)出版社,2002.
[4]阮秋琦,阮宇智,Gonzalez R C,等.數(shù)字圖像處理[M].北京:電子工業(yè)出版社,2003.
[5]魏永明.Rubini A.Linux設(shè)備驅(qū)動程序[M].北京:中國電力出版社,2002.
[6]裘宗燕.Stroustrup B.C++程序設(shè)計語言[M].北京:機械工業(yè)出版社,2005.
[7]龍晉元.Richard W.Unix環(huán)境高級編程[M].2版.北京:人民郵電出版社,2006.
[8]Neil Matthew,Richard Stones,陳健,等.Linux程序設(shè)計[M].3版.北京:人民郵電出版社,2007.
[9]Anon.V4L2 API Specification [EB/OL].http://v4l2spec.bytesex.org/spec/book1.htm.2007.
[10]王永清,何波,王乾,等.Linux下基于ARM920T的USB攝像頭圖像采集[J].微計算機信息,2007(2):176-177.
[11]廖敬萍,馬力.基于Linux的實時解決方案分析[J].現(xiàn)代電子技術(shù),2006,29(19):107-109.
[12]萊特,Wright Peter P,鐘鳴,等.GTK+/GNOME程序設(shè)計[M].北京:機械工業(yè)出版社,2002.
作者簡介
陳 亮 男,1983年出生,廣東興寧人,碩士研究生。主要研究方向為圖像處理、嵌入式系統(tǒng)。
裴海龍 男,1965年出生,博士,副院長,教授,博士生導(dǎo)師。主要從事嵌入式系統(tǒng)、智能機器人系統(tǒng),自適應(yīng)自組織控制等方面的研究和教學(xué)工作。
伍 越 男,1983年出生,碩士研究生。主要研究方向為Linux嵌入式系統(tǒng)及實時仿真系統(tǒng)的構(gòu)建。