C#人臉識別入門篇-STEP BY STEP人臉識別--入門篇

yifanwu發表於2021-09-09

引言

如今,基於人臉的技術和話題可以說是炙手可熱,基於大資料和人工智慧的人臉識別更是突破了我們的想象力的極限,如果應用中不能整合人臉識別,那就太跟不上潮流了。人臉識別是一個演算法密集型的專案,如果自行開發,需要很深厚的數學功底和演算法底蘊,成本較高,我一個做C#的,自問沒有那麼高的水平能夠寫出那麼複雜的演算法,即使能,我們的演算法能和其它公司相比嗎。不過好在現在是一個網際網路時代,自己開發不行,那麼使用其它現成的人臉識別引擎可行嗎?答案當然是可行的。
本系列文章就將先從靜態圖片的人臉檢測開始,逐步講解C#是如何進行人臉識別的。共分為以下四篇

  1. 人臉識別入門—靜態照片人臉檢測

  2. 人臉識別入門—基於影片的人臉檢測

  3. 人臉識別入門—人臉識別初應用

  4. 人臉識別入門—模擬簡單的門禁系統應用

在開始之前,我們先來了解一些人臉識別的整合方式和基礎知識,為下面的課程做準備。

選擇人臉識別引擎的心路歷程

透過搜尋引擎,可以大致確定整合人臉識別的可選方式有以下幾種

1. 整合WebAPI

目前以百度雲,騰訊云為首的網際網路公司提供了基於WEBAPI的整合方式,可以透過HTTP的方式提交識別請求,識別結果透過JSON串的方式返回。基於HTTP的方式識別人臉是比較慢的,慢的原因在於IO效能,相對來講,離線版本的API則能夠充分利用本機的機器資源,不用往返於所謂的演算法雲伺服器,直接在本地就能完成人臉識別和標記工作。

2. 整合SDK

以Face++和訊飛語音為例,這些公司即提供了線上識別的方式也提供了基於SDK的本地識別方式。本地識別的優點是速度快,整合度高。而且,作為C#,我們還可以搭建自己的雲識別平臺。如果採用了WEBAPI的,每一筆請求都需要再經過WEBAPI中轉,效能上會大打折扣。
因此,如果我們的專案不需要在網際網路上訪問,可以供選擇的只有本地整合SDK一條路了。

收費 OR 免費:免費最好

軟體的成本包括人力成本和採購成本,在考慮成本的時候,自然會想到,我們使用的引擎是否收費呢?即使收費再便宜,一旦流量上來了,也是一筆不小的開支。在做技術選型的時候,成本是一個必須要考慮的因素。有了成本因素,再搜尋時,就會悲劇的發現,在百度排首頁的那些人臉識別引擎都不是免費的。那麼有沒有免費的呢。有,網上搜尋,這次使用Google搜尋,可以發現,github上有一系列的的人臉識別開原始碼,但經過試用,不太理想。

踏破鐵鞋無覓處,得來全不費功夫

正在一籌莫展之際,突然今日頭條推送了一條訊息,“人臉識別技術從此免費!虹軟一舉顛覆人工智慧“視”界”,踏破鐵鞋無覓處,得來全不費功夫,這麼好的機會,何不試試呢。

由於當時並不瞭解虹軟,就是看中了人臉識別和免費去的,後來重新百度了一下虹軟,發現這個公司有點意意思,竟然同時拿下了OPPO和VIVO,SAMSUNG這三大手機巨頭的單子,還是有兩把刷子的

下載引擎發現只C++

想到就要做到,於是趕緊開啟電腦下載了SDK,吐槽下今日頭條,做新聞不放連結太不厚道了。只能百度了,連結在這裡。
可是下載後,傻眼了,不得不說虹軟的誠意,這次免費的SDK可真夠厚道的,包括了人臉識別,人臉檢測,人臉跟蹤所有的API。不過美中不足的是,這SDK竟然只有C++版本的,Windows版本不出C#,這虹軟有點不近人情啊。不過傷心歸傷心,活得還做,沒有C#,那我們就拿C++的包裹出C#來用。其實有了C++就等於有了C#,因為C#本身是相容C++的,可以直接呼叫C++的庫。

如何用C#呼叫C++的庫

那麼,如何使用C#呼叫C++的庫呢,C#提供了兩種技術呼叫C++的DLL

  • 靜態呼叫(DCOM+)

  • 動態呼叫(P/Invoke)
    我們可以將C或者C++的函式封裝成COM元件,在C#中呼叫時比較方便,但是COM元件需要註冊,而且多次註冊可能也會導致一些問題,同時在處理C或者C++的型別與COM元件的型別轉換的時候也可能有些麻煩
    採用動態的方式就是直接用C#呼叫C或者C++已經寫好的動態連結庫,這幾種方式相對而言,P/Invoke要方便一些

** 因此我們選擇P/Invoke的方式**

** P/Invoke是什麼*
P/Invoke的全稱是Platform Invoke (平臺呼叫) 它實際上是一種函式呼叫機制,透過P/Invoke我們就可以呼叫非託管DLL中的函式 ,實際上很多NET基類庫中定義的類 型內部部呼叫了從Kernel32.dll,User32.dll,gdi32.dll等非託管DLL中匯出的函式。
來看一個簡單的例子
[DllImportAttribute("user32.dll", EntryPoint = "SetCursorPos")] [return: MarshalAsAttribute(UnmanagedType.Bool)] //可寫可不寫,定義如何封送返回引數 public static extern bool SetCursorPos(int X, int Y);
這段程式碼的目的就是呼叫系統中獲取滑鼠引數的方法。
P/INVOKE的過程
關於P/Invoke的過程,我找到了MSDN上的一張圖,如下所示。

圖片描述

P/Invoke示例圖


在使用P/Invoke呼叫C/C++方法時,會依次執行以下操作
1 查詢包含該函式的非託管DLL
2 將該非託管DLL載入到記憶體中
3 查詢函式在記憶體中的地址並將其引數按照函式的呼叫約定壓棧  
4 將控制權轉移給非託管函式
注意:只在第一次呼叫函式時,才會查詢和載入非託管DLL並查詢函式在記憶體中的地址。當非託管函式產生異常時,P/Invoke會將異常傳遞給託管呼叫方
看起來很複雜,但使用起來卻很簡單,只需要在C#中重新宣告函式的定義就可以了,然後可以像其它函式一樣呼叫。


注意:只在第一次呼叫函式時,才會查詢和載入非託管DLL並查詢函式在記憶體中的地址。當非託管函式產生異常時,P/Invoke會將異常傳遞給託管呼叫方
看起來很複雜,但使用起來卻很簡單,只需要在C#中重新宣告函式的定義就可以了,然後可以像其它函式一樣呼叫。



作者:隨風而逝的心情
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2157/viewspace-2820777/,如需轉載,請註明出處,否則將追究法律責任。

相關文章