引言
如今惊科,基于人臉的技術(shù)和話題可以說(shuō)是炙手可熱,基于大數(shù)據(jù)和人工智能的人臉識(shí)別更是突破了我們的想象力的極限亮钦,如果應(yīng)用中不能集成人臉識(shí)別馆截,那就太跟不上潮流了。人臉識(shí)別是一個(gè)算法密集型的項(xiàng)目,如果自行開(kāi)發(fā)蜡娶,需要很深厚的數(shù)學(xué)功底和算法底蘊(yùn)混卵,成本較高,我一個(gè)做C#的窖张,自問(wèn)沒(méi)有那么高的水平能夠?qū)懗瞿敲磸?fù)雜的算法幕随,即使能,我們的算法能和其它公司相比嗎宿接。不過(guò)好在現(xiàn)在是一個(gè)互聯(lián)網(wǎng)時(shí)代赘淮,自己開(kāi)發(fā)不行,那么使用其它現(xiàn)成的人臉識(shí)別引擎可行嗎睦霎?答案當(dāng)然是可行的梢卸。
本系列文章就將先從靜態(tài)圖片的人臉檢測(cè)開(kāi)始,逐步講解C#是如何進(jìn)行人臉識(shí)別的碎赢。共分為以下四篇
- 人臉識(shí)別入門—靜態(tài)照片人臉檢測(cè)
- 人臉識(shí)別入門—基于視頻的人臉檢測(cè)
- 人臉識(shí)別入門—人臉識(shí)別初應(yīng)用
- 人臉識(shí)別入門—模擬簡(jiǎn)單的門禁系統(tǒng)應(yīng)用
在開(kāi)始之前低剔,我們先來(lái)了解一些人臉識(shí)別的集成方式和基礎(chǔ)知識(shí)速梗,為下面的課程做準(zhǔn)備肮塞。
選擇人臉識(shí)別引擎的心路歷程
通過(guò)搜索引擎,可以大致確定集成人臉識(shí)別的可選方式有以下幾種
1. 集成WebAPI
目前以百度云姻锁,騰訊云為首的互聯(lián)網(wǎng)公司提供了基于WEBAPI的集成方式枕赵,可以通過(guò)HTTP的方式提交識(shí)別請(qǐng)求,識(shí)別結(jié)果通過(guò)JSON串的方式返回位隶】酱埽基于HTTP的方式識(shí)別人臉是比較慢的,慢的原因在于IO性能涧黄,相對(duì)來(lái)講篮昧,離線版本的API則能夠充分利用本機(jī)的機(jī)器資源,不用往返于所謂的算法云服務(wù)器笋妥,直接在本地就能完成人臉識(shí)別和標(biāo)記工作懊昨。
2. 集成SDK
以Face++和訊飛語(yǔ)音為例,這些公司即提供了在線識(shí)別的方式也提供了基于SDK的本地識(shí)別方式春宣。本地識(shí)別的優(yōu)點(diǎn)是速度快酵颁,集成度高。而且月帝,作為C#躏惋,我們還可以搭建自己的云識(shí)別平臺(tái)。如果采用了WEBAPI的嚷辅,每一筆請(qǐng)求都需要再經(jīng)過(guò)WEBAPI中轉(zhuǎn)簿姨,性能上會(huì)大打折扣。
因此簸搞,如果我們的項(xiàng)目不需要在互聯(lián)網(wǎng)上訪問(wèn)扁位,可以供選擇的只有本地集成SDK一條路了深寥。
收費(fèi) OR 免費(fèi):免費(fèi)最好
軟件的成本包括人力成本和采購(gòu)成本,在考慮成本的時(shí)候贤牛,自然會(huì)想到惋鹅,我們使用的引擎是否收費(fèi)呢?即使收費(fèi)再便宜殉簸,一旦流量上來(lái)了闰集,也是一筆不小的開(kāi)支。在做技術(shù)選型的時(shí)候般卑,成本是一個(gè)必須要考慮的因素武鲁。有了成本因素,再搜索時(shí)蝠检,就會(huì)悲劇的發(fā)現(xiàn)沐鼠,在百度排首頁(yè)的那些人臉識(shí)別引擎都不是免費(fèi)的。那么有沒(méi)有免費(fèi)的呢叹谁。有饲梭,網(wǎng)上搜索,這次使用Google搜索焰檩,可以發(fā)現(xiàn)憔涉,github上有一系列的的人臉識(shí)別開(kāi)源代碼,但經(jīng)過(guò)試用析苫,不太理想兜叨。
踏破鐵鞋無(wú)覓處,得來(lái)全不費(fèi)功夫
正在一籌莫展之際衩侥,突然今日頭條推送了一條消息国旷,“人臉識(shí)別技術(shù)從此免費(fèi)!虹軟一舉顛覆人工智能“視”界”茫死,踏破鐵鞋無(wú)覓處跪但,得來(lái)全不費(fèi)功夫,這么好的機(jī)會(huì)璧榄,何不試試呢特漩。
由于當(dāng)時(shí)并不了解虹軟,就是看中了人臉識(shí)別和免費(fèi)去的骨杂,后來(lái)重新百度了一下虹軟涂身,發(fā)現(xiàn)這個(gè)公司有點(diǎn)意意思,竟然同時(shí)拿下了OPPO和VIVO搓蚪,SAMSUNG這三大手機(jī)巨頭的單子蛤售,還是有兩把刷子的
下載引擎發(fā)現(xiàn)只C++
想到就要做到,于是趕緊打開(kāi)電腦下載了SDK,吐槽下今日頭條悴能,做新聞不放鏈接太不厚道了揣钦。只能百度了,鏈接在這里http://www.arcsoft.com.cn/ai/arcface.html漠酿。
可是下載后冯凹,傻眼了,不得不說(shuō)虹軟的誠(chéng)意炒嘲,這次免費(fèi)的SDK可真夠厚道的宇姚,包括了人臉識(shí)別,人臉檢測(cè)夫凸,人臉跟蹤所有的API浑劳。不過(guò)美中不足的是,這SDK竟然只有C++版本的夭拌,Windows版本不出C#魔熏,這虹軟有點(diǎn)不近人情啊。不過(guò)傷心歸傷心鸽扁,活得還做蒜绽,沒(méi)有C#,那我們就拿C++的包裹出C#來(lái)用献烦。其實(shí)有了C++就等于有了C#滓窍,因?yàn)镃#本身是兼容C++的卖词,可以直接調(diào)用C++的庫(kù)巩那。
如何用C#調(diào)用C++的庫(kù)
那么,如何使用C#調(diào)用C++的庫(kù)呢此蜈,C#提供了兩種技術(shù)調(diào)用C++的DLL
- 靜態(tài)調(diào)用(DCOM+)
- 動(dòng)態(tài)調(diào)用(P/Invoke)
我們可以將C或者C++的函數(shù)封裝成COM組件即横,在C#中調(diào)用時(shí)比較方便,但是COM組件需要注冊(cè)裆赵,而且多次注冊(cè)可能也會(huì)導(dǎo)致一些問(wèn)題东囚,同時(shí)在處理C或者C++的類型與COM組件的類型轉(zhuǎn)換的時(shí)候也可能有些麻煩
采用動(dòng)態(tài)的方式就是直接用C#調(diào)用C或者C++已經(jīng)寫(xiě)好的動(dòng)態(tài)鏈接庫(kù),這幾種方式相對(duì)而言,P/Invoke要方便一些
** 因此我們選擇P/Invoke的方式**
** P/Invoke是什么*
P/Invoke的全稱是Platform Invoke (平臺(tái)調(diào)用) 它實(shí)際上是一種函數(shù)調(diào)用機(jī)制战授,通過(guò)P/Invoke我們就可以調(diào)用非托管DLL中的函數(shù) 页藻,實(shí)際上很多NET基類庫(kù)中定義的類 型內(nèi)部部調(diào)用了從Kernel32.dll,User32.dll植兰,gdi32.dll等非托管DLL中導(dǎo)出的函數(shù)份帐。
來(lái)看一個(gè)簡(jiǎn)單的例子
[DllImportAttribute("user32.dll", EntryPoint = "SetCursorPos")] [return: MarshalAsAttribute(UnmanagedType.Bool)] //可寫(xiě)可不寫(xiě),定義如何封送返回參數(shù) public static extern bool SetCursorPos(int X, int Y);
這段代碼的目的就是調(diào)用系統(tǒng)中獲取鼠標(biāo)參數(shù)的方法。
P/INVOKE的過(guò)程
關(guān)于P/Invoke的過(guò)程楣导,我找到了MSDN上的一張圖废境,如下所示。
在使用P/Invoke調(diào)用C/C++方法時(shí)肯夏,會(huì)依次執(zhí)行以下操作
1 查找包含該函數(shù)的非托管DLL
2 將該非托管DLL加載到內(nèi)存中
3 查找函數(shù)在內(nèi)存中的地址并將其參數(shù)按照函數(shù)的調(diào)用約定壓椉Φ洌
4 將控制權(quán)轉(zhuǎn)移給非托管函數(shù)
注意:只在第一次調(diào)用函數(shù)時(shí)又憨,才會(huì)查找和加載非托管DLL并查找函數(shù)在內(nèi)存中的地址冒黑。當(dāng)非托管函數(shù)產(chǎn)生異常時(shí)主之,P/Invoke會(huì)將異常傳遞給托管調(diào)用方
看起來(lái)很復(fù)雜掐松,但使用起來(lái)卻很簡(jiǎn)單齐鲤,只需要在C#中重新聲明函數(shù)的定義就可以了瓦糟,然后可以像其它函數(shù)一樣調(diào)用堵泽。
注意:只在第一次調(diào)用函數(shù)時(shí)禀忆,才會(huì)查找和加載非托管DLL并查找函數(shù)在內(nèi)存中的地址。當(dāng)非托管函數(shù)產(chǎn)生異常時(shí)落恼,P/Invoke會(huì)將異常傳遞給托管調(diào)用方
看起來(lái)很復(fù)雜箩退,但使用起來(lái)卻很簡(jiǎn)單,只需要在C#中重新聲明函數(shù)的定義就可以了佳谦,然后可以像其它函數(shù)一樣調(diào)用戴涝。
有關(guān)本系列的全部代碼可以到我的資源中下載,也可以參考https://github.com/smartkids77/ArcSoft_FreeSDK_Demo
中提供的源代碼來(lái)尋找各個(gè)版本的實(shí)現(xiàn)钻蔑,本系列文章就是從這里找到的靈感.
下一篇我們將以項(xiàng)目實(shí)踐的方式來(lái)給大家具體介紹是怎么一步步來(lái)實(shí)現(xiàn)靜態(tài)照片的人臉檢測(cè)的啥刻。