本文將詳細(xì)介紹基于OpenVINO工具包,在C#語言下,部署飛槳PP-Human的全流程,幫助開發(fā)者快速掌握并部署產(chǎn)業(yè)級AI人體分析解決方案。
飛槳實(shí)時(shí)行人分析工具PP-Human
PP-Human是飛槳目標(biāo)檢測套件PaddleDetection中開源的實(shí)時(shí)行人分析工具,提供了五大異常行為識(shí)別和四大產(chǎn)業(yè)級功能:人體屬性分析、人流計(jì)數(shù)、跨鏡ReID,如下圖所示:
圖 1-1PP-Human v2全功能全景圖
PP-Human技術(shù)架構(gòu)
PP-Human支持單張圖片、圖片文件夾單鏡頭視頻和多鏡頭視頻輸入,經(jīng)目標(biāo)檢測以及特征關(guān)聯(lián),實(shí)現(xiàn)屬性識(shí)別、關(guān)鍵點(diǎn)檢測、軌跡/流量計(jì)數(shù)以及行為識(shí)別等功能,如下圖所示。本文將以行人摔倒識(shí)別為例,基于OpenVINO進(jìn)行多種模型聯(lián)合部署。
?
圖 1-2PP-Human技術(shù)架構(gòu)
構(gòu)建C#開發(fā)環(huán)境
為了防止復(fù)現(xiàn)代碼出現(xiàn)問題,列出以下代碼開發(fā)環(huán)境,可以根據(jù)自己需求設(shè)置,注意OpenVINO一定是2022版本,其他依賴項(xiàng)可以根據(jù)自己的設(shè)置修改。
操作系統(tǒng):Windows 11
OpenVINO:2022.3
OpenCV:4.5.5
Visual Studio:2022 Community
C#框架:.NET 6.0
OpenCvSharp:OpenCvSharp4
C#中調(diào)用OpenVINO實(shí)現(xiàn)
構(gòu)建OpenVINO動(dòng)態(tài)鏈接庫
由于OpenVINO只有C++和Python接口,無法直接在C#中使用OpenVINO部署模型,為了實(shí)現(xiàn)在C#中使用,通過動(dòng)態(tài)鏈接庫的方式實(shí)現(xiàn)。
在C#中引入動(dòng)態(tài)鏈接庫文件
在C#中需要使用[DllImport()]方法引入動(dòng)態(tài)鏈接庫文件,其完整的使用方式如以下代碼所示:
[DllImport(openvino_dll_path, CharSet=CharSet.Unicode, CallingConvention=CallingConvention.Cdecl)]
publicexternstaticIntPtrset_input_image_sharp(IntPtrinference_engine, stringinput_node_name, refulonginput_size);
針對[DllImport()]括號中的內(nèi)容:
openvino_dll_path為dll文件路徑
CharSet = CharSet.Unicode代表支持中文編碼格式字符串
CallingConvention = CallingConvention.Cdecl指示入口點(diǎn)的調(diào)用約定為調(diào)用方清理堆棧
在聲明動(dòng)態(tài)鏈接庫后,就可以引入動(dòng)態(tài)鏈接庫中的方法,由于我們在C++環(huán)境下生成的動(dòng)態(tài)鏈接庫,為了讓編譯器識(shí)別,需要方法名、變量類型一一對應(yīng),才可以引入成功:
表 1C++與C#方法對應(yīng)關(guān)系
基于以上方法,我們將動(dòng)態(tài)鏈接庫中的所有方法引入到C#中。
C#構(gòu)建Core類
上一步我們引入了封裝的OpenVINO動(dòng)態(tài)鏈接庫,為了更方便的使用,將其封裝到Core類中。
在不同方法之間,主要通過推理核心結(jié)構(gòu)體指針在各個(gè)方法之間傳遞,在C#是沒有指針這個(gè)說法的,不過可以通過IntPtr結(jié)構(gòu)體來接收這個(gè)指針,為了防止該指針被篡改,將其封裝在類中作為私有成員使用。
根據(jù)模型推理的步驟,構(gòu)建模型推理類:
(1)構(gòu)造函數(shù)
publicCore(stringmodel_file, stringdevice_name){
// 初始化推理核心
ptr = NativeMethods.core_init(model_file, device_name);
}
在該方法中,主要是調(diào)用推理核心初始化方法,初始化推理核心,讀取本地模型,將模型加載到設(shè)備、創(chuàng)建推理請求等模型推理步驟。
(2)設(shè)置模型輸入形狀
// @brief 設(shè)置推理模型的輸入節(jié)點(diǎn)的大小
// @param input_node_name 輸入節(jié)點(diǎn)名
// @param input_size 輸入形狀大小數(shù)組
publicvoidset_input_sharp(stringinput_node_name, ulong[] input_size) {
// 獲取輸入數(shù)組長度
intlength = input_size.Length;
if(length == 4) {
// 長度為4,判斷為設(shè)置圖片輸入的輸入參數(shù),調(diào)用設(shè)置圖片形狀方法
ptr = NativeMethods.set_input_image_sharp(ptr, input_node_name, refinput_size[0]);
}
elseif(length == 2) {
// 長度為2,判斷為設(shè)置普通數(shù)據(jù)輸入的輸入?yún)?shù),調(diào)用設(shè)置普通數(shù)據(jù)形狀方法
ptr = NativeMethods.set_input_data_sharp(ptr, input_node_name, refinput_size[0]);
}
else{
// 為防止輸入發(fā)生異常,直接返回
return;
}
}
OpenVINO 2022.3支持模型動(dòng)態(tài)輸入,讀入模型可以不固定輸入大小,在使用時(shí)固定模型的輸入大小,并且可以隨時(shí)修改輸入形狀。當(dāng)前設(shè)置情況下,至此設(shè)置二維、以及四維的輸入形狀,在當(dāng)前模型中足夠使用。
(3)加載推理數(shù)據(jù)
// @brief 加載推理數(shù)據(jù)
// @param input_node_name 輸入節(jié)點(diǎn)名
// @param input_data 輸入數(shù)據(jù)數(shù)組
publicvoidload_input_data(stringinput_node_name, float[] input_data) {
ptr = NativeMethods.load_input_data(ptr, input_node_name, refinput_data[0]);
}
// @brief 加載圖片推理數(shù)據(jù)
// @param input_node_name 輸入節(jié)點(diǎn)名
// @param image_data 圖片矩陣
// @param image_size 圖片矩陣長度
publicvoidload_input_data(stringinput_node_name, byte[] image_data, ulongimage_size, inttype) {
ptr = NativeMethods.load_image_input_data(ptr, input_node_name, refimage_data[0], image_size, type);
}
加載推理數(shù)據(jù)主要包含圖片數(shù)據(jù)和普通的矩陣數(shù)據(jù),其中對于圖片的預(yù)處理,也已經(jīng)在C++中進(jìn)行封裝,保證了圖片數(shù)據(jù)在傳輸中的穩(wěn)定性。
(4)模型推理
// @brief 模型推理
publicvoidinfer() {
ptr = NativeMethods.core_infer(ptr);
}
(5)讀取推理結(jié)果數(shù)據(jù)
// @brief 讀取推理結(jié)果數(shù)據(jù)
// @param output_node_name 輸出節(jié)點(diǎn)名
// @param data_size 輸出數(shù)據(jù)長度
// @return 推理結(jié)果數(shù)組
publicT[] read_infer_result(stringoutput_node_name, intdata_size) {
// 獲取設(shè)定類型
stringt = typeof(T).ToString();
// 新建返回值數(shù)組
T[] result = newT[data_size];
if(t == "System.Int32") { // 讀取數(shù)據(jù)類型為整形數(shù)據(jù)
int[] inference_result = newint[data_size];
NativeMethods.read_infer_result_I32(ptr, output_node_name, data_size, refinference_result[0]);
result = (T[])Convert.ChangeType(inference_result, typeof(T[]));
returnresult;
}
else{ // 讀取數(shù)據(jù)類型為浮點(diǎn)型數(shù)據(jù)
float[] inference_result = newfloat[data_size];
NativeMethods.read_infer_result_F32(ptr, output_node_name, data_size, refinference_result[0]);
result = (T[])Convert.ChangeType(inference_result, typeof(T[]));
returnresult;
}
}
在讀取模型推理結(jié)果時(shí),支持讀取整形數(shù)據(jù)和浮點(diǎn)型數(shù)據(jù),且需要知曉模型輸出數(shù)據(jù)的大小,這就要求我們對自己所使用的模型有很好的把握。
(6)清除地址
// @brief 刪除創(chuàng)建的地址
publicvoiddelet() {
NativeMethods.core_delet(ptr);
}
此處的清除地址需要調(diào)用fengzhuangd額地址刪除方法實(shí)現(xiàn),不可以直接刪除C#中創(chuàng)建的IntPtr,這樣會(huì)導(dǎo)致內(nèi)存泄漏,影響程序性能。
通過上面的封裝,比可以在C#平臺(tái)下,調(diào)用Core類,間接調(diào)用OpenVINO工具包署自己的模型了。
審核編輯:劉清
-
C語言
+關(guān)注
關(guān)注
180文章
7614瀏覽量
137538 -
OpenCV
+關(guān)注
關(guān)注
31文章
635瀏覽量
41496 -
python
+關(guān)注
關(guān)注
56文章
4807瀏覽量
84984
原文標(biāo)題:基于C# 和OpenVINO部署飛槳PP-Human
文章出處:【微信號:SDNLAB,微信公眾號:SDNLAB】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論