摘 要: 谷歌眼鏡是由谷歌公司于2012年4月發(fā)布的一款“拓展現(xiàn)實(shí)”眼鏡,由于其較小的體積、攜帶的方便性和強(qiáng)大、全面的功能使其具備相當(dāng)廣闊的應(yīng)用前景。基于谷歌眼鏡的硬件平臺,在安卓系統(tǒng)中開發(fā)了一個(gè)可以進(jìn)行雙向?qū)崟r(shí)圖像傳輸?shù)能浖撥浖柚雀柩坨R的攝像頭實(shí)時(shí)獲取當(dāng)前時(shí)刻佩戴者所觀察到的環(huán)境信息并將它們發(fā)送到服務(wù)器中,服務(wù)器對這些信息進(jìn)行處理之后將有意義的結(jié)果返回給谷歌眼鏡進(jìn)行顯示。其實(shí)現(xiàn)的整體思路為接收數(shù)據(jù)、顯示預(yù)覽、發(fā)送數(shù)據(jù)并接收回傳數(shù)據(jù)、顯示回傳數(shù)據(jù)。
關(guān)鍵詞: 谷歌眼鏡;Android應(yīng)用;視頻通信
0 引言
2007年11月,Google與84家硬件制造商、軟件開發(fā)商及電信營運(yùn)商成立開放手持設(shè)備聯(lián)盟來共同研發(fā)改良Android系統(tǒng),隨后,Google發(fā)布了Android的源代碼,從此各個(gè)網(wǎng)絡(luò)公司相繼推出各類Android應(yīng)用。Google創(chuàng)造性地將Android系統(tǒng)搭載到一個(gè)“眼鏡”上,使Android系統(tǒng)的硬件平臺進(jìn)一步地拓寬。而針對谷歌眼鏡大多還限于休閑娛樂,對其廣泛的應(yīng)用背景并沒有深入地發(fā)掘。
在醫(yī)學(xué)領(lǐng)域,在大型醫(yī)療設(shè)備上還沒出現(xiàn)Android應(yīng)用,而谷歌眼鏡的出現(xiàn),將拓展其硬件平臺,使移動應(yīng)用與大型醫(yī)療器械結(jié)合成為可能。本文在搭載Android系統(tǒng)的谷歌眼鏡上開發(fā)一個(gè)實(shí)時(shí)雙向圖像通信的應(yīng)用軟件,利用TCP網(wǎng)絡(luò)傳輸協(xié)議,服務(wù)器處理谷歌眼鏡捕獲的圖像并回傳處理后的畫面。此應(yīng)用可以用于手術(shù)中幫助醫(yī)生分辨病灶部位和動脈等關(guān)鍵部位,改變傳統(tǒng)的治療方式,提高醫(yī)生的工作效率。
對于所依賴的無線局域網(wǎng)絡(luò)環(huán)境,由于視頻實(shí)時(shí)傳輸?shù)男枨?,選用WiFi傳輸方式;對于WiFi傳輸方式而言,連接不穩(wěn)定和傳輸出錯率高一直為其缺陷,因此采用TCP網(wǎng)絡(luò)傳輸協(xié)議[1-2]。
TCP協(xié)議是一個(gè)面向連接的可靠的數(shù)據(jù)傳輸協(xié)議。TCP協(xié)議在傳輸數(shù)據(jù)之前要經(jīng)歷3次握手,每次數(shù)據(jù)報(bào)文傳輸完畢后接收方還會發(fā)送一個(gè)確認(rèn)ACK,發(fā)送方接收到確認(rèn)ACK后才會發(fā)送下一個(gè)數(shù)據(jù)報(bào)[1,3-4]。隨著網(wǎng)絡(luò)中端口越來越多,TCP也曾經(jīng)修改其協(xié)議以避免網(wǎng)絡(luò)擁塞,如慢啟動、擁塞避免、快速重傳[5-6]等算法。為了提高傳輸效率,TCP協(xié)議應(yīng)用的是GBN協(xié)議,它允許發(fā)送方傳輸多個(gè)分組而不需要等待確認(rèn)。TCP協(xié)議為了應(yīng)對多客戶端和小封包傳輸?shù)葐栴}設(shè)置了諸多參數(shù),如邏輯參數(shù)TCP_NODELAY、SO_KEEPALIVE、SO_RESUSEADDR,還有整數(shù)參數(shù)SO_SNFBUF、SO_SNFBUF等。
1 圖像傳輸系統(tǒng)總體設(shè)計(jì)框架
此圖像傳輸系統(tǒng)的總體設(shè)計(jì)框架簡單敘述如下:谷歌眼鏡將采集到的一幀圖像數(shù)據(jù)發(fā)送給服務(wù)器,服務(wù)器端的驗(yàn)證程序不對數(shù)據(jù)做任何處理回傳給谷歌眼鏡顯示。算法總體設(shè)計(jì)框架如圖1所示。
2 移動終端通信應(yīng)用設(shè)計(jì)思想
此應(yīng)用的主要功能模塊包括捕獲并預(yù)覽、發(fā)送數(shù)據(jù)線程發(fā)送一幀JPEG格式的圖像數(shù)據(jù)和接收數(shù)據(jù)線程接收并回顯服務(wù)器已經(jīng)處理過的圖像數(shù)據(jù)3個(gè)部分。發(fā)送和接收數(shù)據(jù)利用多線程實(shí)現(xiàn),這樣可以節(jié)省時(shí)間,提高效率。
首先谷歌眼鏡開啟攝像頭,將圖像數(shù)據(jù)采集到谷歌眼鏡中并利用Android系統(tǒng)中的Surface對象開啟預(yù)覽[7],采集到的圖像數(shù)據(jù)通過IO流處理后利用TCP協(xié)議發(fā)送[8]給服務(wù)器。同時(shí)服務(wù)器將接收到的數(shù)據(jù)回傳給谷歌眼鏡,谷歌眼鏡接收到數(shù)據(jù)后將數(shù)據(jù)解壓縮后利用Bitmap對象加載到屏幕上[7],將服務(wù)器返回圖像與預(yù)覽圖像放在一起可以直觀地比較所返回的圖像與采集到的圖像在延遲、流暢程度等方面的差異。其主體框架如圖2所示。
2.1 谷歌眼鏡與服務(wù)器進(jìn)行連接功能實(shí)現(xiàn)
初始狀態(tài)時(shí)電腦和谷歌眼鏡均不知道對方的IP地址,但均在同一個(gè)局域網(wǎng)內(nèi)。因此在服務(wù)器程序上定義一個(gè)網(wǎng)段(一般為192.168),通常一個(gè)網(wǎng)段中會產(chǎn)生256個(gè)IP地址,而在其中254個(gè)IP地址中,會有一個(gè)IP地址為谷歌眼鏡的IP地址。
通常的做法是利用循環(huán)的原理,在主程序中創(chuàng)建一個(gè)IP地址,將此IP地址作為connect函數(shù)的參數(shù),若connect函數(shù)成功執(zhí)行則連接成功;若connect函數(shù)報(bào)錯則換另一個(gè)IP地址,如此最多執(zhí)行254次connect函數(shù),則可連接谷歌眼鏡。但此方法會使程序執(zhí)行時(shí)間比較長,效率比較低。
為了縮短連接谷歌眼鏡所需要的時(shí)間,本文利用多線程方法來實(shí)現(xiàn)對谷歌眼鏡IP地址的查找。首先在主線程中創(chuàng)建254個(gè)子線程,然后將網(wǎng)段中的254個(gè)IP地址作為參數(shù)傳入其子線程的執(zhí)行函數(shù)。此函數(shù)的作用就是嘗試對傳入的IP地址進(jìn)行連接,如果連接失敗則輸出連接失敗,然后子線程結(jié)束;如果成功則將谷歌眼鏡的IP地址保存到服務(wù)器中,同時(shí)谷歌眼鏡也會保存服務(wù)器的IP地址,至此連接成功建立。服務(wù)器連接谷歌眼鏡框圖如圖3所示。
2.2 雙向傳輸數(shù)據(jù)
當(dāng)谷歌眼鏡與服務(wù)器連接后,谷歌眼鏡需要將自己采集到的圖像數(shù)據(jù)傳送到服務(wù)器,服務(wù)器的測試程序不對圖像做任何處理,再重新傳回到谷歌眼鏡。
開始時(shí)谷歌眼鏡捕獲并保存圖像,此部分功能可以由以Android Camera框架為基礎(chǔ)的一些接口函數(shù)實(shí)現(xiàn)。利用initCamera()函數(shù)初始化谷歌眼鏡的攝像頭,然后調(diào)用camera對象中的startPreview方法開始在谷歌眼鏡上預(yù)覽以觀察效果[7]。獲取圖像之后將圖像數(shù)據(jù)存儲在數(shù)組之中。
谷歌眼鏡得到一幀圖像后將原始YUV格式圖像按大約15∶1的比例壓縮成JPEG格式并存儲在數(shù)組之中。在傳輸過程中,因?yàn)榉?wù)器不知道谷歌眼鏡發(fā)送的一幀圖像大小,所以無法分配存儲空間。因而谷歌眼鏡無法直接將數(shù)據(jù)加載到輸出流中利用Socket()函數(shù)發(fā)送出去[8],需要提前發(fā)送一個(gè)表示一幀圖像數(shù)組長度的整數(shù)n,在服務(wù)器中建立長度為n的數(shù)組用以存儲所接收的數(shù)據(jù)。因此每傳輸每一幀圖像均需要提前傳輸一個(gè)表示數(shù)組長度的整數(shù)n,可以稱它為“數(shù)組帽”。
數(shù)據(jù)傳輸?shù)某跏妓惴閱尉€程傳輸算法,即在一個(gè)線程中實(shí)現(xiàn)圖像數(shù)據(jù)傳輸,谷歌眼鏡先傳送一幀圖像,然后等待服務(wù)器接收,服務(wù)器接收完畢后再回傳接收到的圖像。因?yàn)閳D像獲取為連續(xù)的,所以一幀幀圖像連續(xù)起來,就實(shí)現(xiàn)了圖像的實(shí)時(shí)雙向傳輸。但是在谷歌眼鏡完成傳輸與接收服務(wù)器回傳數(shù)據(jù)之間,谷歌眼鏡處于空閑狀態(tài),相應(yīng)的服務(wù)器也有這樣的空閑狀態(tài),即“傳輸—等待—接收—再傳輸”,這樣就增加了圖像傳輸?shù)臅r(shí)間,降低了傳輸?shù)男省?/p>
針對上述方法的缺陷,本文提出一種新的圖像數(shù)據(jù)傳輸方法,稱為“雙線程算法”。在客戶端主程序中創(chuàng)建2個(gè)子線程,子線程A只發(fā)送圖像,子線程B只接收圖像。由于同一主程序下的線程是可以并發(fā)執(zhí)行的,因此谷歌眼鏡在利用子線程A發(fā)送一幀圖像的同時(shí)可以利用子線程B接收服務(wù)器返回的一幀圖像,這樣就實(shí)現(xiàn)了發(fā)送和接收的并發(fā)進(jìn)行,從而消除了等待時(shí)間,縮短了圖像傳輸?shù)臅r(shí)間,提高了傳輸效率。
根據(jù)Android系統(tǒng)的特點(diǎn),子線程被看成類的實(shí)現(xiàn)(對象),并且擁有自己的成員和方法。要實(shí)現(xiàn)上文中的雙線程算法,首先需要開啟用于接收數(shù)據(jù)的子線程B,再創(chuàng)建一個(gè)用于傳輸數(shù)據(jù)的對象C,將要發(fā)送的圖像數(shù)據(jù)復(fù)制給子線程A。在此程序中,復(fù)制數(shù)據(jù)的方法被寫在對象C的構(gòu)造函數(shù)中,即當(dāng)對象C被創(chuàng)建時(shí)復(fù)制數(shù)據(jù)的方法已經(jīng)開始執(zhí)行。當(dāng)子線程B得知對象C創(chuàng)建后立即創(chuàng)建發(fā)送數(shù)據(jù)的子線程A,當(dāng)子線程A得知數(shù)據(jù)已經(jīng)被復(fù)制到自身的數(shù)組成員中時(shí)立即將數(shù)組加載到輸出流中,利用Socket將流中的數(shù)據(jù)加上一個(gè)“數(shù)組帽”后發(fā)送到服務(wù)器。同時(shí)線程B創(chuàng)建用于接收數(shù)據(jù)的Socket,一旦輸入流中有數(shù)據(jù),則進(jìn)行接收,接收完一幀圖像后利用Bitmap類將其加載到屏幕上,這樣在實(shí)際的應(yīng)用中,工作人員就可以看到經(jīng)過處理后的醫(yī)學(xué)圖像。
算法在具體實(shí)現(xiàn)過程中不可避免地會有一些函數(shù)之間的嵌套,其具體的實(shí)現(xiàn)過程如圖4所示。
2.3 網(wǎng)絡(luò)傳輸速率的優(yōu)化
TCP傳輸協(xié)議中有一些參數(shù)是針對多客戶端情況的,但在此應(yīng)用中,在一個(gè)局域網(wǎng)中僅有一個(gè)服務(wù)器和一個(gè)客戶端,為了提高傳輸速率,TCP協(xié)議中的一些參數(shù)需要改變。TCP協(xié)議默認(rèn)開啟Nagle算法[9],但由于Nagle算法導(dǎo)致的不可預(yù)測的較高的延遲以及使吞吐量降低的負(fù)面影響,需要關(guān)閉Nagle算法,即設(shè)置TCP_NODELAY為TRUE;在此應(yīng)用中,僅有一個(gè)客戶端并且對實(shí)時(shí)性有較高的要求,因此要設(shè)置SO_KEEPALIVE為TRUE,即一直保持Socket端口打開,防止再次連接;當(dāng)緩沖區(qū)數(shù)組長度太小時(shí)會引起阻塞,降低傳輸效率,過大又會造成內(nèi)存浪費(fèi),因此可以根據(jù)一幀圖像數(shù)組長度大小合理設(shè)置緩沖區(qū)數(shù)組長度,提高程序執(zhí)行速度。
攝像頭采集的數(shù)據(jù)被存儲在數(shù)組中,為了提高傳輸?shù)膸?,除了上面的修改TCP中的參數(shù)以提高速率,另一個(gè)思路就是壓縮圖像數(shù)據(jù)數(shù)組的長度。GZIP算法是Android系統(tǒng)已經(jīng)成熟應(yīng)用過的壓縮算法,在一定程度上能夠壓縮數(shù)組的長度,提高傳輸速率。
3 算法實(shí)際測試
經(jīng)實(shí)際測試,此通信軟件可以穩(wěn)定運(yùn)行0.5小時(shí)以上,并且在300 Mb/s帶寬情況下,平均傳輸速率可以達(dá)到895 kb/s,傳輸幀率可以穩(wěn)定在11 S/s左右,基本能夠滿足設(shè)計(jì)要求。當(dāng)算法為單線程時(shí),谷歌眼鏡傳輸?shù)膸蕛H在7 S/s左右,算法改為多線程后,圖像數(shù)據(jù)傳輸?shù)乃俾视忻黠@提高,由此說明此多線程算法有更好的執(zhí)行效率。
4 結(jié)論
針對以上設(shè)備連接和數(shù)據(jù)傳輸所用的傳統(tǒng)算法的缺陷,此軟件在設(shè)計(jì)時(shí)提出利用多線程的設(shè)計(jì)思路。對單線程思想中的時(shí)間浪費(fèi)行為進(jìn)行優(yōu)化,消除了等待時(shí)間,提高了數(shù)據(jù)傳輸?shù)男省?/p>
現(xiàn)階段根據(jù)對無線網(wǎng)絡(luò)情況下的TCP網(wǎng)絡(luò)出現(xiàn)的諸多問題,許多機(jī)構(gòu)也進(jìn)行了各種優(yōu)化操作,但還停留在理論階段,還沒實(shí)現(xiàn)成熟的應(yīng)用。由于Android系統(tǒng)的特性并為了應(yīng)用軟件的可移植性,因此無法去應(yīng)用那些在理論方面比現(xiàn)在主流的TCP協(xié)議更優(yōu)的TCP改進(jìn)協(xié)議,如TCP Westwood[10-11]等。
此通信軟件有可靠的穩(wěn)定性,并且算法復(fù)雜度較小,可以高效地完成數(shù)據(jù)的傳輸。但由于WiFi網(wǎng)絡(luò)的不穩(wěn)定性,畫面偶爾會出現(xiàn)卡頓現(xiàn)象。若是硬件條件更完善,則其效果會更佳。
參考文獻(xiàn)
[1] POSTEL J. RFC 793: Transmission control protocol[Z]. 1981.
[2] CERF V. RFC 1120: Internet activities board[Z]. 1990.
[3] SOCOLOFSKY T, KALE C. RFC 1180: TCP/IP Tutorial[Z]. 1991.
[4] KUROSE J F, ROSS K W. 計(jì)算機(jī)網(wǎng)絡(luò):自頂向下方法[M].陳鳴,譯.北京:機(jī)械工業(yè)出版社,2009.
[5] ALLMAN M, PAXSON V, STEVENS W. RFC 2581: TCP congestion control[Z]. 1999.
[6] LAKSHMAN T V, MADHOW U. The performance of TCP/IP for networks with high bandwidth-delay products and random loss[J]. IEEE/ACM Transactions on Networking, 1997, 5(3): 336-350.
[7] OSTRANDER J. Android UI基礎(chǔ)教程[M].劉文斌,譯.北京:人民郵電出版社,2012.
[8] STORIMER J. TCP Socket 編程[M].門佳,譯.北京:人民郵電出版社,2013.
[9] NAGLE J. RFC 896: Congestion control in IP/TCP Internetworks[Z]. 1984.
[10] CASETTI C, GERLA M, MASCOLO S, et al. TCP Westwood: end-to-end bandwidth estimation for enhanced transport over wireless links[J]. Journal of Wireless Networks, 2002,8(5):467-479.
[11] Chen Jiwei, PAGANINI F, SANADIDI M Y. Fluid-flow analysis of TCP Westwood with RED[J]. Computer Networks,2006,50(9):1302-1326.