C 實現人臉識別一 (運用虹軟人臉識別引擎)

2021-08-18 09:15:11 字數 4926 閱讀 4308

arcsoft.com.cn/ai/arcfa

ce.html

動態呼叫(p/invoke)

我們可以將c或者c++的函式封裝成com元件,在c#中呼叫時比較方便,但是com元件需要註冊,而且多次註冊可能也會導致一些問題,同時在處理c或者c++的型別與com元件的型別轉換的時候也可能有些麻煩

採用動態的方式就是直接用c#呼叫c或者c++已經寫好的動態鏈結庫,這幾種方式相對而言,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上的一張圖,如下所示。

1 查詢包含該函式的非託管dll

2 將該非託管dll載入到記憶體中

3 查詢函式在記憶體中的位址並將其引數按照函式的呼叫約定壓棧  

4 將控制權轉移給非託管函式

看起來很複雜,但使用起來卻很簡單,只需要在c#中重新宣告函式的定義就可以了,然後可以像其它函式一樣呼叫。

看起來很複雜,但使用起來卻很簡單,只需要在c#中重新宣告函式的定義就可以了,然後可以像其它函式一樣呼叫。

arcsoft.com.cn/ai/arcfa

ce.html

typedef mint32 afd_fsdk_orientcode;

mrect * rcface;

mlong nface;

afd_fsdk_orientcode * lfaceorient;

} afd_fsdk_faceres, * lpafd_fsdk_faceres;

intptr用於表示指標或控制代碼的平台特定型別。這個其實說出了這樣兩個事實,intptr 可以用來表示指標或控制代碼、它是乙個平台特定型別,它主要用在兩個地方:

(1)c#呼叫win32 api時

(2)c#呼叫c/c++寫的dll時(其實和1相同,只是這個一般是我們在和他人合作開發時經常用到)

我們可以這樣子理解,intptr就可以互換c++中的指標

); sdkkey [in] 使用者申請sdk時獲取的sdk key

pmem [in] 分配給引擎使用的記憶體位址

lmemsize [in] 分配給引擎使用的記憶體大小

pengine [out] 引擎handle

iorientpriority [in] 期望的臉部檢測角度範圍

nscale [in] 用於數值表示的最小人臉尺寸 有效值範圍[2,50] 推薦值 16。該尺寸是人臉相對於所在的長邊的佔比。例如,如果使用者想檢測到的最小人臉尺寸是長度的1/8,那麼這個nscale就應該設定為8

nmaxfacenum [in] 使用者期望引擎最多能檢測出的人臉數 有效值範圍[1,50]

cdecl 呼叫方清理堆疊。這使您能夠呼叫具有 varargs 的函式(如 printf),使之可用於接受可變數目的引數的方法。

fastcall 不支援此呼叫約定。

stdcall 被呼叫方清理堆疊。這是使用平台 invoke 呼叫非託管函式的預設約定。

thiscall 第乙個引數是 this 指標,它儲存在暫存器 ecx 中。其他引數被推送到堆疊上。此呼叫約定用於對從非託管 dll 匯出的類呼叫方法。

winapi 此成員實際上不是呼叫約定,而是使用了預設平台呼叫約定。例如,在 windows 上預設為 stdcall,在 windows

上預設為 cdecl。

預設情況下,c和c++使用的cdecl呼叫,因此我們在呼叫dll時指定這個值就可以。

marshal類提供了乙個方法集合,這些方法用於分配非託管記憶體、複製非託管記憶體塊、將託管型別轉換為非託管型別,此外還提供了在與非託管**互動時使用的其他雜項方法,我們將會在下面開發程序中頻繁使用這個類的多個方法。

例如:在定義乙個指標型別變數時intptr,我們需要使用marshal.allochglobal為其分配記憶體,得到intptr變數,在分配記憶體時,我們需要使用marshal.sizeof計算需要分配的記憶體的大小。然後呼叫marshal.

structuretoptr為變數賦值

int nscale = 50;

int nmaxfacenum = 10;

string sdkfdkey = "你申請到的fdkey";

if (retcode != 0)

openfile.filter = "檔案|*.bmp;*.jpg;*.jpeg;*.png|所有檔案|*.*;";

引擎初始化失敗

找不到dll

首先請保證你把dll拷貝到對應的目錄下面,其次要確定設定輸出選項為拷貝到輸出目錄。

記憶體不能讀或者寫

這個是c++的尿性,也是c#程式設計師不多見的報錯,主要檢查相關引數是否傳入正確。還要注意,如果人臉檢測返回的值不為0,獲取到的人臉數目會是乙個比較大的隨機數。這個時候如果用迴圈讀取,就會出現位址越界的情況。

虹軟人臉識別Android Sample Code

afr fsdkinte ce engine new afr fsdkengine 用來存放提取到的人臉資訊,face 1 是註冊的人臉,face 2 是要識別的人臉 afr fsdkface face1 new afr fsdkface afr fsdkface face2 new afr fsd...

虹軟人臉識別C demo

同理新增附加庫目錄,如下圖所示 附加依賴項 將兩個dll複製到程式執行的目錄裡面 按照上面的步驟配置完環境後,接下來進行測試 的讀取要用到opencv,我就假設大家opencv配置均不存在問題 下面的 為我參考的官方給的一些資料,但是我用的opencv是3.4的,因此程式有些小小的改動,具體可參考如...

虹軟人臉識別Android Sample Code

afr fsdkinte ce engine new afr fsdkengine 用來存放提取到的人臉資訊,face 1 是註冊的人臉,face 2 是要識別的人臉 afr fsdkface face1 new afr fsdkface afr fsdkface face2 new afr fsd...