嵌入式系統是以應用為中心,以計算機技術為基礎,并且軟硬件可裁剪,適用于應用系統對功能、可靠性、成本、體積、功耗有嚴格要求的專用計算機系統。嵌入式機器視覺系統是指用嵌入式計算機處理由光學傳感器接收到的圖像信息,以實現對物體的檢測和識別的裝置,如數碼相機、手持二維碼識別設備,體感交互游戲機等。由于機器視覺系統需要進行大量復雜的數據運算,因此目前大多數的機器視覺系統還是基于PC系統構建,但隨著近年來嵌入式系統的高速發展,嵌入式機器視覺系統越來越多地應用于工業檢測與控制、智能交通、安防、醫療器械、機器人導航及消費電子等領域。
嵌入式機器視覺系統的性能主要取決于硬件和軟件兩方面。目前應用于嵌入式機器視覺系統的硬件平臺主要有Intel基于x86架構的Atom平臺、TI基于ARM—DSP的OMAP系列平臺、NVIDIA基于ARM—GeForce的Tegra系列平臺、IBM等基于PowerPC的處理平臺等,其中ARM—DSP是一種高性價比的、應用廣泛的體系結構。除了硬件平臺之外,嵌入式操作系統的選擇對機器視覺系統的性能也很重要,如開機時間,系統穩定性等。嵌入式操作系統的種類比較多,其中較為流行的主要有μC/OS、Windows CE、VxWorks、Android、iOS、Meego、QNX和Linux等。在諸多嵌入式操作系統中,Linux以其內核穩定、支持多種硬件平臺、完全免費、源代碼完全開放、可裁剪定制、易于移植的特性,成為大多數廠家的絕佳選擇。此外,由于嵌入式機器視覺系統具有處理數據量大,算法復雜的特點,對嵌入式機器視覺應用程序的優化也至關重要。
文中以采用ARM—DSP結構的Beagleboard—xM開發板為例,構建了用于目標檢測跟蹤的嵌入式機器視覺系統,從操作系統和機器視覺應用程序方面對系統進行優化,并充分利用Cotex—A處理器的NEON加速技術,顯著提高了嵌入式機器視覺系統的性能。
1 系統軟硬件組成
文中所采用的嵌入式機器視覺系統的硬件組成如圖1所示。其中DM3730處理器是由TI生產的單片系統(SoC)處理器,采用了POP(Package on Package)封裝技術,內含1G主頻的ARM Cortex—A8,主頻800 M的TMS320C64+內核和512 M的LPDDR內存。該處理器有較強的多媒體圖像、視頻處理能力,特別適合于構建嵌入式機器視覺系統。Beagleboard—xM沒有Flash,系統是從MicroSD卡啟動的。PMIC為電源與音頻管理模塊,它通過McBSP總線與處理器連接。攝像頭和以太網數據通過USB接口傳給處理器,處理器運行目標檢測與跟蹤程序,并將處理結果送到LCD顯示。Minicom用于和上位機進行通訊,便于調試。
圖2為系統的軟件結構圖。在嵌入式Linux內核中包含了對CPU、USB攝像頭、電源管理設備及USB以太網等的驅動支持。其中V4L是Linux內核中關于視頻設備的API接口,UVC(USB Video Class)是為USB攝像頭提供即插即用功能的驅動模塊,在此基礎上將開源的跨平臺機器視覺庫OpenCV2.2移植到了嵌入式平臺上,并在應用程序中實現對視頻信號的采集和處理。
2 嵌入式LinuX操作系統優化
嵌入式系統硬件資源較為有限,作為以應用為中心的專用計算機系統,需要對其在啟動速度、實時性、系統尺寸、電源管理等方面進行優化。近年來,Linux憑借其優良特性廣泛地應用于嵌入式系統。但是,作為一種原本為PC機設計的操作系統,設計者開始并沒有考慮嵌入式應用對啟動速度的要求,導致其典型的啟動時間一般在幾十秒或以上,這對用戶來說是不能容忍的。此外,隨著Linux內核的不斷膨脹,啟動時間越來越長。因此,加快啟動速度已經成為嵌入式Linux系統亟待解決的關鍵問題之一。
由于成本的考慮,Beagleboard—xM平臺沒有Flash,它是從MicroSD卡啟動的。嵌入式Linux系統啟動時序如表1所示。系統上電后,內部ROM程序會從SD卡加載x—loader到SRAM。x—loader負責初始化系統(如時鐘、RAM等),并將u—boot從SD卡中加載到RAM。u—boot負責將內核鏡像從SD卡加載到RAM中。內核解壓并運行,掛載文件系統,執行init進程,登錄系統,最終完成系統的啟動。編寫perl腳本記錄串口輸出的時間,開機啟動過程各部分耗時如圖3所示。在系統啟動過程中,內核解壓與運行時間、系統自啟動項加載時間占了整個系統啟動的大部分時間。
本文對嵌入式Linux操作系統采取的優化策略如下。
1)修改并重新編譯u—boot源碼,取消開機3 s等待時間
系統會檢測在開機等待時間內用戶按鈕是否被按下,如果被按下,則可以進行設置系統環境變量,修改啟動選項等操作。這里可以跳過這一步,減少開機時間。
2)裁剪內核中不必要的功能部分
嵌入式Ldnux操作系統內核中除了進程管理、內存管理、任務調度等核心部分外,還提供了多種文件系統、網絡、硬件驅動、內核調試等功能模塊,但它們并非必不可少,例如手持移動終端通常不需要NTFS等文件系統,也不需要RAID和SCSI設備支持。所以,根據嵌入式系統應用的具體需求配置Linux內核才能減小Linux內核的靜態映像體積,同時也能夠相應減少這些功能模塊運行時間的開銷。
3)采用“-Os - mthumb”編譯選項進行優化以減小內核鏡像大小
-Os是gcc優化選項中最深層次的優化,相當于是對代碼進行了-O2的優化,但不增加代碼尺寸。-mthumb表示使用16位短指令集,它具有更高的代碼密度,即占用存儲空間小,僅為32位ARM代碼規格的65%,但其性能卻下降的很少。
4)去掉內核打印輸出
Linux系統啟動時,一般使用串口控制臺或VGA控制臺打印內核啟動信息,打印速度取決于串口的速度和處理器的速度,這在大多數嵌入式系統中要用數百毫秒的時間。
5)用buildroot構建輕量級的根文件系統
常用于構建根文件系統的工具有OE(OpenEmbedded)和buildroot等。OE是重量型的交叉編譯系統工具,可以用來構建復雜的根文件系統,但配置和定制過程難度很大,而且要耗費約20 G的硬盤空間和十幾個小時的編譯時間。buildroot則是一個相當小巧靈活的交叉編譯工具,用它定制和調整軟件包十分方便,而且buildroot提供了類似Linux kernel配置采用的配置菜單,易于使用。
6)桌面環境使用X11而非Gnome或KDE
X11即X Window系統,它是一種可以用于Unix和類Unix操作系統的位圖顯示視窗系統。Gnome和KDE是兩種相對復雜的桌面環境。對于嵌入式機器視覺系統,如果用戶界面不追求華麗,可以使用更為簡潔的X11,以及簡單的桌面管理器twm。
7)禁用或暫緩啟動某些啟動項
為了加速啟動,可以禁用不必要的啟動項,甚至一些必要的啟動項可以在系統完成登錄后再啟動。具體可以通過修改/etc/init.d/下自啟動項快捷方式名稱的方法實現。
$cd/etc/init.d/
$mv S20network K20network
當系統完成開機啟動后再啟動該項目,可以用如下命令:
$K20network start
如表2所示,經過優化后,內核鏡像大小由3.046 MB減小到2.797 MB,系統的啟動時間(從復位到開啟應用程序)由35.171 s縮短到10.056 s,基本滿足實際應用的需要。嵌入式Linux操作系統優化取得了明顯的效果。
應用在移動載體上的嵌入式機器視覺系統通常對能耗也有較高的要求。Beagleboard—xM是一款功耗較低的產品,不需要風扇冷卻。電源管理主要是由PMIC模塊實現的。另外,通過更改系統的顯示設置,如屏保時間、待機時間等,來降低能耗。
3 應用程序優化
機器視覺系統往往涉及大量復雜的計算,大多采用C/C++等高效率的語言進行開發。嵌入式系統對應用軟件的質量要求很高,在嵌入式開發中須注意對代碼進行優化,盡可能地提高代碼效率。本文從算法、代碼效率以及處理器的特性等方面出發,為開發高效率嵌入式機器視覺應用程序提供了些經驗。
3.1 選擇合適的算法
在機器視覺算法優化過程中,速度和內存不可兼得,要想得到較快的運行速度必須適當增加內存空間的使用量。例如,在JPG圖像有Huffman編碼表,從YUV到RGB的變換也有變換表,本文計算梯度方向直方圖HOG時需要用到18個方向的三角函數。這些運算原本較復雜,采用查表的方法之后,雖然占用了內存,但顯著提高了運行速度。
3.2 代碼效率的優化
代碼效率優化的前提是要保證程序結果的正確性,在此基礎上對空間復雜度和時間復雜度進行調整,以達到性能的提升。代碼效率優化可以采用多種方法。
1)采用較短的數據類型
本文實驗中浮點數據類型用float代替double,目標檢測結果基本不變,但是運算量和所占用內存空間都相應減少。
2)switch語句優化
對于switch語句,編譯器是按照順序進行條件比較,發現匹配時,就跳轉到滿足條件的語句執行。為了提高速度,可以把發生頻率較高的條件放在前面。
3)用指針代替數組
在許多情況下,可以用指針運算代替數組索引,編譯后常常能產生又快又短的代碼。與數組索引相比,指針一般能使代碼速度更快,占用空間更少,這在使用多維數組時差異更明顯。
4)用宏函數取代函數
函數和宏函數的區別就在于,宏函數占用大量的空間,而函數占用了時間。當函數被多次調用時,會反復進行壓棧和彈棧操作,從而消耗一些額外的時間。使用宏函數不會產生函數調用,所以僅僅占用了空間,不會增加額外的運行時間。
5)循環優化:采用循環合并與循環展開
當兩個循環的負荷都不滿時,可以把它們合并在一起組成一個循環。循環展開就是把循環計數小的循環展開,成為非循環形式的串行程序,或者把循環計數大的循環部分展開,減少循環迭代次數,這樣可以節省用于循環設置、初始化、增加和校對循環計數器的時間。
6)采用Inline函數
在C++中,當函數前加關鍵字Inline的聲明,編譯器會用函數內部的代碼替換所有對該函數的調用。這樣可以省去調用函數指令需要的執行時間以及傳遞變元和傳遞過程需要的時間。通常,這種優化在Inline函數被頻繁調用并且只包含較短代碼的時候最有效。
7)使用增量和減量操作符
在用到自增和白減運算時應盡量使用增量和減量操作符,因為增量符語句比賦值語句更快。
3.3 充分利用處理器特性進行加速
ARM+DSP的組合在嵌入式開發中堪稱理想架構。DSP可專門用于處理密集型信號處理需求、復雜的數學函數以及圖像處理算法,而ARM則可用于實現圖形用戶界面、網絡連接及系統控制等。上面的代碼優化措施是通用的方法,如果針對處理器的特性對程序進行優化,可以得到更好的優化效果。
1)利用開發工具對DSP程序進行優化
有很多算法在DSP平臺可以實現,在ARM上也可以,但有些特定算法,如濾波、視頻編解碼等放在DSP上運行的效率較高。以往的開發中對DSP程序的優化更多是匯編程序的優化,但用匯編語言做開發和優化往往費時又費力。但是隨著開發工具的更新,現在的C代碼優化效率可達到手工匯編的90%。TI提供的C6EZRUN工具可以使開發人員能在DSP上運行ARM代碼,而無需修改,并且從ARM到DSP代碼的轉換效率非常高。TI的另一個開發工具C6EZAccel則提供了一個包括數百個DSP優化型信號處理算法的程序庫,通過ARM API加快開發進度。開發人員可以將更多的精力投入到算法設計中。
2)充分利用ARM處理器的NEON技術進行加速
ARM高級單指令多數據(SIMD)擴展亦稱NEON技術,它是一種由ARM開發的64/128位混合SIMD體系結構,可以提升多媒體和信號處理應用程序的性能。其關鍵功能包括對齊和未對齊數據訪問,支持整型定點和單精度浮點數據類型、與ARM核心的緊密耦合,以及具有多個視圖的大型寄存器文件。NEON指令在ARM和Thumb-2中都可用。要生成NEON指令,必須在命令行中指定采用NEON技術的Cortex處理器。ARMv7之前的體系結構不提供NEON支持。如果要對進行優化,需要增加編譯選項“-mcpu=cortex-a8-mfpu=neon”。
3.4 應用程序優化結果
在嵌入式實時程序設計時可以運用上面介紹的一種或多種方法來優化代碼。以上方法主要是為了提高代碼的執行效率,但會增加代碼長度,降低可讀性。在嵌入式程序設計中應合理地使用這幾種技術以達到較好的優化效果。
運用上述方法,對基于HOG特征的物體檢測算法進行優化,運行時間如圖3所示。該算法是目前公認的準確率最高的目標檢測算法。對汽車、大巴、自行車、行人的檢測結果如圖4所示??紤]到該算法的復雜性以及檢測精度的要求,我們采用的是浮點數優化。結果表明,經過優化后程序運行速度約為原來的2.5倍。
4 結束語
隨著嵌入式系統的高速發展,嵌入式機器視覺系統的應用也越來越廣泛。如何把運算量大、算法復雜的機器視覺應用程序移植到嵌入式平臺上并進行優化設計是重要的課題。本文針對嵌入式機器視覺系統的特點,在操作系統方面對內核和文件系統進行了精簡,在應用程序方面做了大量的優化,并充分利用Cotex—A處理器的NEON加速技術,顯著提高了嵌入式機器視覺系統的性能,對嵌入式機器視覺系統的開發具有借鑒意義。
評論
查看更多