張 生,龍?jiān)栖S
(上海理工大學(xué) 光電信息與計(jì)算機(jī)學(xué)院,上海 200093)
近年來(lái),隨著計(jì)算機(jī)硬件技術(shù)的不斷發(fā)展,增強(qiáng)現(xiàn)實(shí)、虛擬現(xiàn)實(shí)技術(shù)開(kāi)始從理論變?yōu)楝F(xiàn)實(shí),出現(xiàn)了越來(lái)越多的增強(qiáng)現(xiàn)實(shí)應(yīng)用及設(shè)備。相關(guān)產(chǎn)品主要分為兩類:一類是增強(qiáng)現(xiàn)實(shí)頭盔,比較具有代表性的是微軟的Hololens增強(qiáng)現(xiàn)實(shí)頭盔、谷歌的Google glasses,這兩種屬于獨(dú)立增強(qiáng)現(xiàn)實(shí)設(shè)備,因?yàn)槠渚哂凶约旱奶幚硇酒?,可以脫離計(jì)算機(jī)獨(dú)立工作;另一類是智能手機(jī),美國(guó)蘋果公司與谷歌公司分別研發(fā)了自己的技術(shù)ARkit和ARcore,利用智能手機(jī)攝像頭,使增強(qiáng)現(xiàn)實(shí)應(yīng)用可以運(yùn)行在手機(jī)上。由于智能手機(jī)的廣泛普及,手機(jī)增強(qiáng)現(xiàn)實(shí)應(yīng)用具有更好的發(fā)展前景與商業(yè)應(yīng)用價(jià)值。
一般的智能手機(jī)由于其硬件的性能局限性(CPU頻率低,內(nèi)存小, GPU性能低),導(dǎo)致很多開(kāi)發(fā)完成的AR應(yīng)用雖然在臺(tái)式計(jì)算機(jī)中可以流暢運(yùn)行,且?guī)瑪?shù)穩(wěn)定、圖像質(zhì)量較好,但當(dāng)移植到手機(jī)上,則會(huì)出現(xiàn)明顯的幀數(shù)降低、畫(huà)面卡頓等情況,大大降低了使用體驗(yàn)。傳統(tǒng)解決方案主要有:①使用對(duì)性能要求較低的3D模型;②降低畫(huà)面質(zhì)量參數(shù)(光照、幀數(shù)、色彩、分辨率等)。但上述方案都以降低畫(huà)面質(zhì)量為代價(jià),所以在某些場(chǎng)景下并不是最佳解決方案。
隨著移動(dòng)設(shè)備的普及以及移動(dòng)應(yīng)用的大量增加,特別是游戲、圖像分析類軟件的快速發(fā)展,使渲染性能優(yōu)化成為移動(dòng)圖形類應(yīng)用研發(fā)的一個(gè)核心問(wèn)題。根據(jù)應(yīng)用場(chǎng)景不同有各種不同優(yōu)化方案,一類方案為優(yōu)化渲染算法類,如張?bào)K先 、羅蕾 、姜帆[1]提出的富媒體場(chǎng)景渲染優(yōu)化策略,該優(yōu)化策略從局部渲染與多邊形填充兩方面進(jìn)行,通過(guò)跟蹤場(chǎng)景變化的失效區(qū)域體現(xiàn)局部渲染;另一類則是對(duì)被渲染的場(chǎng)景與物體模型進(jìn)行優(yōu)化的方案,如江能興、周淦淼[2]提出的基于3DMAX的三維模型優(yōu)化策略,通過(guò)簡(jiǎn)化3D模型提高渲染性能。
增強(qiáng)現(xiàn)實(shí)類軟件與傳統(tǒng)圖形類軟件的最大區(qū)別在于,其需要通過(guò)攝像頭實(shí)時(shí)捕獲真實(shí)世界的圖像信息進(jìn)行分析,并在真實(shí)世界基礎(chǔ)上建立一個(gè)虛擬空間。所以對(duì)捕獲到的圖像進(jìn)行分析與處理會(huì)造成很大開(kāi)銷,從而影響系統(tǒng)的整理渲染性能。
對(duì)于增強(qiáng)現(xiàn)實(shí)應(yīng)用的優(yōu)化,傳統(tǒng)對(duì)被渲染的虛擬物體模型進(jìn)行優(yōu)化是一個(gè)可行方案,但是優(yōu)化效果依賴于需要渲染的模型數(shù)量。如果應(yīng)用本身需要渲染的虛擬物體數(shù)量不多,則該優(yōu)化方案收益并不理想。目前學(xué)術(shù)界和產(chǎn)業(yè)界研究與使用最多的方案是對(duì)捕獲到的圖像進(jìn)行處理,并建立虛擬空間的算法進(jìn)行優(yōu)化,如Arthur、 Guez、Joelle、Pineau[3]提出的多任務(wù)SLAM算法。
一般增強(qiáng)現(xiàn)實(shí)應(yīng)用的性能測(cè)試包括渲染性能與計(jì)算性能測(cè)試。計(jì)算性能測(cè)試與常規(guī)軟件性能測(cè)試基本一致,采用一定約束,在其它條件不變的情況下,通過(guò)改變單一參數(shù),比較軟件運(yùn)行時(shí)的內(nèi)存開(kāi)銷、CPU占用及運(yùn)算時(shí)間等[4]。渲染性能測(cè)試,主要關(guān)注的性能指標(biāo)為屏幕分辨率、渲染幀數(shù)及渲染幀數(shù)穩(wěn)定性。本文主要實(shí)驗(yàn)流程為在一個(gè)已搭建好的AR軟件環(huán)境中,在其它參數(shù)及條件一致的情況下,通過(guò)將運(yùn)算進(jìn)行多線程分離,比較使用多線程與不使用多線程情況下的渲染性能,得出實(shí)驗(yàn)結(jié)果。
采用多線程即應(yīng)用程序可在同一時(shí)間里使用芯片的不同部分。雖然單線程芯片每秒能夠處理成千上萬(wàn)條指令,但在任一時(shí)刻只能夠?qū)σ粭l指令進(jìn)行操作,而多線程技術(shù)可以使芯片同時(shí)進(jìn)行多線程處理,由此芯片性能得到提升[5]。本文使用多線程方式,將增強(qiáng)現(xiàn)實(shí)應(yīng)用中的屏幕渲染功能與圖像分析功能分開(kāi)為兩個(gè)線程,屏幕渲染功能設(shè)置為主線程,圖像分析功能設(shè)置為子線程,兩個(gè)線程異步工作。主線程不必等待子線程,當(dāng)子線程完成圖像分析后,發(fā)送信號(hào)給主線程,從而使屏幕渲染功能可以保持流暢執(zhí)行,提升畫(huà)面渲染性能。
2.2.1 單線程環(huán)境搭建
本文實(shí)驗(yàn)環(huán)境使用美國(guó)蘋果公司ARkit搭建的一個(gè)智能手機(jī)增強(qiáng)現(xiàn)實(shí)應(yīng)用,測(cè)試平臺(tái)為Unity3D引擎。該應(yīng)用的主要功能為通過(guò)攝像頭捕捉圖像數(shù)據(jù)進(jìn)行圖像識(shí)別,當(dāng)識(shí)別到特定模式圖像后,展示相關(guān)分析數(shù)據(jù),主要工作流程如圖1所示。只要軟件處于開(kāi)啟狀態(tài),則必須進(jìn)行屏幕渲染,在該流程下,每一個(gè)渲染幀中,都要等待圖像識(shí)別到發(fā)送信號(hào)后,才可繼續(xù)執(zhí)行下一幀渲染,兩個(gè)功能之間是同步關(guān)系。
圖1 軟件工作流程
其中,Update方法用于更新屏幕內(nèi)容,運(yùn)行在每一個(gè)渲染幀,每一次執(zhí)行都需要等待圖像識(shí)別功能的結(jié)束,根據(jù)patternFound信號(hào)量的真假情況,才能進(jìn)行下一步操作。單線程環(huán)境執(zhí)行流程核心代碼如下:
...
//模式識(shí)別函數(shù)
PatternDetector patternDetector;
//需要匹配的模式
Pattern pattern
void Start()
{
pattern = new Pattern();
patternDetector = new PatternDetector();
//生成模式
patternDetector.buildPatternFromImage();
}
//Update方法會(huì)在屏幕刷新的每一幀執(zhí)行
void Update()
{
//執(zhí)行圖像模式識(shí)別
patternDetector.detectPattern();
if(patternDetector.patternFound == true)
{
nextStep();
}
else
{
//do nothing
}
}//update
2.2.2 多線程技術(shù)引入
考慮到保持圖像模式識(shí)別處理與屏幕渲染的同步會(huì)嚴(yán)重影響系統(tǒng)性能,將圖像識(shí)別處理功能分離到子線程中進(jìn)行,而屏幕渲染功能依舊為主線程。此時(shí)的軟件工作流程如圖3所示。屏幕渲染功能運(yùn)行在主線程,圖像識(shí)別處理功能運(yùn)行在子線程。因?yàn)榫€程分離,主線程運(yùn)行不依賴于子線程的運(yùn)行。當(dāng)圖像識(shí)別處理功能未完成時(shí),主線程會(huì)一直執(zhí)行屏幕渲染功能;當(dāng)子線程中圖像識(shí)別完成時(shí),發(fā)送一個(gè)完成信號(hào)給主線程,此時(shí)主線程再執(zhí)行下一步操作,子線程任務(wù)完成并被掛起。
圖2 多線程引入后的工作流程
其中, Update方法用于更新屏幕內(nèi)容,運(yùn)行在每一個(gè)渲染幀,主線程執(zhí)行屏幕渲染工作,子線程detectThread進(jìn)行圖像模式識(shí)別及處理工作。每一幀中,主線程都會(huì)對(duì)isComplete信號(hào)量進(jìn)行校驗(yàn),如果為假,則繼續(xù)執(zhí)行下一幀的屏幕渲染工作;如果為真,則開(kāi)始執(zhí)行觸發(fā)相應(yīng)功能。子線程完成圖像模式識(shí)別后,將信號(hào)量isComplete設(shè)置為真,通知主線程,然后將isThreadRuning信號(hào)量設(shè)置為假,掛起子線程。在該流程下,屏幕渲染與圖像處理處于異步執(zhí)行關(guān)系中。加入多線程之后的執(zhí)行流程核心代碼如下:
...
//定義一個(gè)子線程,用來(lái)執(zhí)行圖像識(shí)別處理功能
Theard detectTheard;
//模式識(shí)別函數(shù)
PatternDetector patternDetector;
//需要匹配的模式
Pattern pattern;
//isComplete用于標(biāo)識(shí)是否完成了識(shí)別
private boolean isComplete;
//isTheardRunning用來(lái)控制子線程開(kāi)關(guān)
boolean isTheardRunning;
//Start函數(shù)用于初始化
void Start()
{
//子線程初始化
detectTheard =new Theard(detectPattern);
pattern =new Pattern();
patternDetector =new PatternDetector();
//生成模式
patternDetector.buildPatternFromImage();
}
// update函數(shù)會(huì)在屏幕刷新的每一幀執(zhí)行
void Update()
{
//執(zhí)行屏幕渲染
if(isComplete == true;)
{
nextStep();
}
}//update
...
//detectPattern在detectTheard線程中執(zhí)行
void detectPattern()
{
if(isTheardRunning)
{
patternDetector.detectPattern();
if(patternDetector.patternFound == true)
{
isComplete =true;
isTheardRunning =false;
}
else
isComplete =false;
}
};
2.3.1 渲染性能對(duì)比算法
本文主要考慮的渲染性能參數(shù)有:f為每一秒屏幕的刷新幀數(shù);Ct為主線程當(dāng)前占用CPU進(jìn)行計(jì)算的時(shí)間絕對(duì)值,單位為s;Rt為GPU渲染線程花費(fèi)時(shí)間,單位為s。對(duì)上述3個(gè)參數(shù)分別賦予不同權(quán)重參數(shù)P1、P2、P3,權(quán)重參數(shù)可根據(jù)對(duì)不同性能關(guān)注度的具體情況而定,在本文場(chǎng)景下,更加關(guān)注屏幕幀數(shù),具體如式(1)所示。
(p1=0.8,p2=0.1,p3=0.1)
(1)
2.3.2 實(shí)驗(yàn)數(shù)據(jù)分析
保持其它條件不變,僅通過(guò)對(duì)多線程的引入進(jìn)行多次實(shí)驗(yàn),結(jié)果如表1所示。從表中可以看出,在本文軟件環(huán)境下,多線程的引入對(duì)CPU和GPU影響較小,但能較好地提升渲染幀數(shù)。
表1 實(shí)驗(yàn)數(shù)據(jù)
從實(shí)驗(yàn)數(shù)據(jù)可以看出,在CPU、GPU相同的情況下,以及相同的環(huán)境參數(shù)下,使用多線程將增強(qiáng)現(xiàn)實(shí)應(yīng)用中的屏幕渲染與圖像識(shí)別處理進(jìn)行線程分離,可以有效提升畫(huà)面幀數(shù),提升幅度為25%,但同時(shí)可能增加約5%的CPU開(kāi)銷,而GPU開(kāi)銷基本不變。因此,在CPU占用量較小的圖像處理類增強(qiáng)現(xiàn)實(shí)應(yīng)用中,引入多線程可以明顯提升渲染性能。