朱明 李志國
摘 要:對智慧社區(qū)建設(shè)中占重要地位的安防體系建設(shè)進(jìn)行了深入研究,給出了一種基于Neon指令技術(shù)的人臉比對算法優(yōu)化方法。利用Neon指令集的并行處理優(yōu)勢,在嵌入式ARM平臺下,對人臉比對算法進(jìn)行了效率優(yōu)化,實現(xiàn)了前端攝像機(jī)中人臉識別過程的實時性。采用海思平臺Hi3519進(jìn)行測試驗證,結(jié)果表明該方法是一種行之有效的方法,有效地提升了人臉比對算法的性能。
關(guān)鍵詞:人臉識別;NEON;神經(jīng)網(wǎng)絡(luò)
中圖分類號:TP391 文獻(xiàn)標(biāo)識碼:A 文章編號:1671-2064(2020)06-0055-02
0 引言
智慧社區(qū)作為智慧城市建設(shè)的一部分,近年來日益受到市場和行業(yè)的關(guān)注。在智慧社區(qū)建設(shè)中,安防體系建設(shè)又是重中之重。門禁作為社區(qū)安防第一線,其重要性不言而喻?;仡欓T禁系統(tǒng)的發(fā)展歷程中,比門禁卡更便利的是指紋識別,而比指紋識別更智能的當(dāng)屬刷臉門禁了。而且人臉識別具有唯一性和不易復(fù)制性,相比門禁卡和指紋識別,它的造假成本要高出許多,具有更好的安全性。人臉識別就是將待識別的人臉特征與已得到的人臉特征模板進(jìn)行比較,根據(jù)相似程度對人臉的身份信息進(jìn)行判斷。這一過程又分為兩類:一類是確認(rèn),是一對一進(jìn)行圖像比較的過程,另一類是辨認(rèn),是一對多進(jìn)行圖像匹配對比的過程。人臉識別門禁系統(tǒng)就屬于辨認(rèn)過程,比如社區(qū)3000人進(jìn)行了注冊,則刷臉過程就是1∶3000的圖片匹配對比的辨認(rèn)過程。因此想要在應(yīng)用中注冊的人臉身份更多,必須保證單次匹配對比過程的速度足夠快。然而嵌入式ARM平臺下的硬件資源一般有限,提升單次匹配對比過程的效率也就顯得十分重要。因此針對嵌入式ARM平臺進(jìn)行圖像算法優(yōu)化研究非常有意義。本文就給出了一種基于Neon指令技術(shù)的人臉比對算法優(yōu)化方法[1]。
1人臉比對算法
“人臉比對(Face Compare)”是衡量兩個人臉之間相似度的算法。人臉比對算法的輸入是兩個人臉特征,即通過算法對人臉圖像進(jìn)行的特征提取,一般是轉(zhuǎn)化的一串固定長度的數(shù)值。人臉比對算法的輸出是兩個特征之間的相似度,一般為余弦距離或歐氏距離的相似度。通過相似度值與設(shè)定閾值的比較就可以實現(xiàn)人臉識別,包括一對一的人臉驗證和一對多人臉識別[2]。
1.1余弦相似度
余弦相似度用向量空間中兩個向量夾角的余弦值作為衡量兩個個體間差異的大小。余弦值越接近1,就表明夾角越接近0度,也就是兩個向量越相似,這就叫“余弦相似性”。我們知道,對于兩個向量,如果他們之間的夾角越小,那么我們認(rèn)為這兩個向量是越相似的。余弦相似性就是利用了這個理論思想。它通過計算兩個向量的夾角的余弦值來衡量向量之間的相似度值。余弦相似度計算公式如下:
分子為向量A與向量B的點乘,分母為所有向量維度值的平方相加后開方的叉乘。余弦相似度的取值為[0,1],值越大表示越相似。如果再將分母進(jìn)行歸一化處理為1,則余弦相似度就可以認(rèn)為是向量A與向量B的點乘結(jié)果。
1.2余弦相似度的函數(shù)實現(xiàn)
在實際項目中,利用余弦相似度的分值即可進(jìn)行人臉識別比對,其函數(shù)主要實現(xiàn)如下:
for(inti=0;i { fcos_dist+=pf1[i]*pf2[i]; } 其中fcos_dist變量即為計算得到的余弦相似度分值,pf1和pf2是指向兩個特征向量的指針,N為特征向量的長度,在實際項目應(yīng)用中,一般取N=512。 2 ARM NEON技術(shù) 圖1 Q寄存器與D寄存器映射關(guān)系 ARM NEON就是一種基于SIMD思想的ARM技術(shù),從ARMv7開始被采用,相比于ARMv6或之前的架構(gòu),NEON結(jié)合了64-bit和128-bit的SIMD指令集,提供128-bit寬的向量運算(vector operations)。NEON的寄存器與VFP是共享的,而且還具有自己獨立的執(zhí)行流水線。 2.1 NEON寄存器 NEON寄存器共有16個128位的向量寄存器構(gòu)成。而32個雙精度浮點寄存器共享了這16個寄存器,32個單精度浮點寄存器共享了前8個寄存器。其中,單精度寄存器用S0~S31表示,雙精度寄存器用D0~D31來表示,而128位的SIMD寄存器則用Q0~Q15來表示。圖1列舉了Q寄存器與D寄存器的映射關(guān)系。 2.2 NEON指令集 NEON指令按照操作數(shù)類型可以分為正常指令、寬指令、窄指令、飽和指令、長指令。 正常指令:生成大小相同且類型通常與操作數(shù)向量相同的結(jié)果向量,如VADD指令。 長指令:對雙字向量操作數(shù)執(zhí)行運算,生產(chǎn)四字向量結(jié)果。L標(biāo)記,如VMOVL。 寬指令:一個雙字向量操作數(shù)和一個四字向量操作數(shù)執(zhí)行運算,生成四字向量結(jié)果。W標(biāo)記,如VADDW。 窄指令:四字向量操作數(shù)執(zhí)行運算,并生成雙字向量結(jié)果。N標(biāo)記,如VMOVN。 飽和指令:當(dāng)超過數(shù)據(jù)類型指定到范圍則自動限制在該范圍內(nèi)。Q標(biāo)記,如VQSHRUN。 NEON指令按照作用可以分為:加載數(shù)據(jù)、存儲數(shù)據(jù)、加減乘除運算、邏輯AND/OR/XOR運算、比較大小運算等。 2.3 NEON編程基礎(chǔ) 在NEON硬件寄存器及其指令集基礎(chǔ)上,通過NEON編程的熟練應(yīng)用,能夠?qū)λ惴ùa進(jìn)行性能優(yōu)化,從而實現(xiàn)性能的大幅提升,通常使用NEON主要有四種方法:NEON優(yōu)化庫、向量化編譯器、NEON內(nèi)聯(lián)函數(shù)、NEON匯編指令。 根據(jù)優(yōu)化程度需求不同,第4種最為底層,若熟練掌握效果最佳,一般也會配合第3種一起使用。分別簡單介紹如下: 第1種方法NEON優(yōu)化庫可以在程序中直接使用,一般OpenMax DL和Ne10優(yōu)化庫中包含很多算法函數(shù)的優(yōu)化實現(xiàn),供優(yōu)化人員選用。 第2種方法主要是編譯器的向量優(yōu)化選項,通常在GCC編譯器選項中加入向量化表示,有利于C代碼生成NEON代碼,如-ftree-vectorize。 第3種方法提供了一個連接NEON操作的C函數(shù)接口,編譯器會自動生成相關(guān)的NEON指令。 第4種方法包括兩種寫法,如純匯編文件(assembly文件,后綴為“.s”或“.S”)和內(nèi)聯(lián)匯編(即在C代碼中嵌入?yún)R編,調(diào)用簡單,無需手動存儲寄存器)。 本文針對人臉比對算法的優(yōu)化,主要采用第3種方法。 2.4 NEON優(yōu)化技巧 掌握ARM NEON寄存器及其指令集以后,就可以進(jìn)行算法代碼的性能優(yōu)化了,一般情況下,通過細(xì)致的優(yōu)化,能夠獲得幾倍甚至十幾倍以上的性能提升。當(dāng)然這也需要一定的經(jīng)驗積累,下面簡單介紹幾點技巧[3]。 (1)要去除數(shù)據(jù)依賴,不要將當(dāng)前指令的目的寄存器作為下一條指令的源寄存器。因為ARM架構(gòu)采用的是多級流水線技術(shù),如果下一條指令的源寄存器是當(dāng)前指令的目的寄存器,就需要當(dāng)前指令執(zhí)行完之后,下一條指令才能取指執(zhí)行,這樣會產(chǎn)生很大的延遲,影響性能。 (2)要減少分支跳轉(zhuǎn),ARM處理器中廣泛使用分支預(yù)測技術(shù)。但是一旦分支預(yù)測失敗,性能就會損失很大。 (3)要盡量使用預(yù)載指令PLD,它允許處理器告知內(nèi)存系統(tǒng)在不久的將來會從指定地址讀取數(shù)據(jù),若數(shù)據(jù)提取加載到cache中,將會提高cache命中率,從而提升性能。 (4)要關(guān)注指令周期延遲,比如對于乘法指令,指令周期比較長,盡量不要立即使用指令計算結(jié)果,否則會等待耗時。 (5)要保證數(shù)據(jù)運算盡量在NEON寄存器中,避免在ARM寄存器和NEON寄存器之間的運算。 2.5 人臉比對函數(shù)的NEON優(yōu)化 本文主要涉及ARM NEON技術(shù)的優(yōu)化內(nèi)容是人臉識別算法中的人臉比對函數(shù),由前面介紹內(nèi)容可知,我們所使用的人臉比對函數(shù)的核心實現(xiàn)為余弦相似度計算,主要為乘加求和計算[4]。根據(jù)余弦相似的函數(shù)實現(xiàn),可以進(jìn)行打包存取和打包計算,同時利用ARM NEON并行指令,實現(xiàn)算法并行加速,主要代碼如下: for(inti=0;i { float32x4_t? pf1_t=vld1q_f32(pf1); float32x4_t? pf2_t=vld1q_f32(pf2); float32x4_t? pf1n_t=vld1q_f32(pf1+4); float32x4_t? pf2n_t=vld1q_f32(pf2+4); fcos_dist_t=vmlaq_f32(fcos_dist_t,pf1_t,pf2_t); fcos_dist_t=vmlaq_f32(fcos_dist_t,pf1n_t,pf2n_t); pf1+=8; pf2+=8; } float32x2_t sum_t=vpadd_f32(vget_low_f32(fcos_dist_t),vget_high_f32(fcos_dist_t)); sum_t=vpadd_f32(sum_t,sum_t); fcos_dist+=vget_lane_f32(sum_t,0); 其中,float32x4_t數(shù)據(jù)類型是一個包含四條向量線的向量,每條向量線包含一個32位浮點數(shù)。 vld1q_f32指令(float32x4_t vld1q_f32(_transfersize(4) float32_t const*ptr))是加載并存儲4個32位浮點數(shù)元素的單個向量。 vmlaq_f32指令(float32x4_t vmlaq_f32(float32x4_t a, float32x4_t b,float32x4_t c))是兩個向量元素相乘并將結(jié)果進(jìn)行累加(即Vres[i]=Va[i]+Vb[i]*Vc[i] )。 vget_low_f32指令和vget_high_f32指令是將一個128 位向量拆分為2個64位向量。 vpadd_f32指令是兩個向量元素分別按對相加運算。 vget_lane_f32指令(float32_t vget_lane_f32(float32x2_t vec,_constrange(0,1) int lane))是從向量中提取單個元素。 綜合上述指令并按上述函數(shù)流程,可以實現(xiàn)人臉比對函數(shù)的并行優(yōu)化,大幅提升了算法效率,提升人臉識別相關(guān)產(chǎn)品的性能指標(biāo)及客戶體驗。 3 測試結(jié)果分析 本文算法優(yōu)化評測的嵌入式ARM平臺是海思Hi3519V100,該芯片處理器內(nèi)核包括A7@800MHz和A17@1.2GHz,支持NEON加速引擎,集成FPU處理單元。 本文在算法優(yōu)化評測中,所用的特征向量長度為512維,主要驗證人臉比對函數(shù)在嵌入式ARM平臺下優(yōu)化前后的效率情況,其單位為毫秒(ms)。具體測試數(shù)據(jù)如表1所示。 結(jié)果表明,應(yīng)用該方法可以有效的提升ARM平臺下人臉比對函數(shù)的效率,即近3倍左右的提升。此方法適用于各種維度的人臉特征向量的人臉比對過程,特征向量越長,其優(yōu)越性表現(xiàn)的越明顯。 4 結(jié)論 本文針對人臉識別算法在嵌入式ARM平臺的應(yīng)用,研究了基于NEON指令的人臉比對函數(shù)的優(yōu)化方法,利用NEON技術(shù)進(jìn)行并行存取及并行計算,對人臉比對函數(shù)的計算過程進(jìn)行了深入優(yōu)化,并以海思平臺Hi3519為例進(jìn)行驗證,測試結(jié)果表明該方法是一種行之有效的方法,較好地解決了人臉識別算法在嵌入式ARM平臺中遇到的性能困難,有效地提升了人臉比對函數(shù)的性能,及時完成人臉對比功能,特別是注冊人臉數(shù)N較大的時候,即需要進(jìn)行N次人臉比對時,效果更加明顯,從而實現(xiàn)了人臉識別算法在嵌入式ARM平臺應(yīng)用的實時性。 參考文獻(xiàn) [1] 詹森,D.巴克斯.ARM嵌入式系統(tǒng)編程與優(yōu)化[M].北京:機(jī)械工業(yè)出版社,2017. [2] 王文峰.人臉識別原理與實踐[M].北京:電子工業(yè)出版社,2018. [3] 王天慶.Python人臉識別:從入門到工程實踐[M].北京:機(jī)械工業(yè)出版社,2019. [4] 周立功.ARM嵌入式系統(tǒng)基礎(chǔ)教程(第2版)[M].北京:北京航空航天大學(xué)出版社,2019.