在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

C#平臺(tái)調(diào)用OpenVINO的可行性

OpenCV學(xué)堂 ? 來源:英特爾物聯(lián)網(wǎng) ? 作者:英特爾物聯(lián)網(wǎng) ? 2022-05-24 09:37 ? 次閱讀

1.1 項(xiàng)目概述

1.1.1 項(xiàng)目介紹

C#調(diào)用OpenVINO工具套件部署Al模型項(xiàng)目開發(fā)項(xiàng)目,簡(jiǎn)稱OpenVinoSharp,這是一個(gè)示例項(xiàng)目,該項(xiàng)目實(shí)現(xiàn)在C#編程語(yǔ)言下調(diào)用Intel推出的 OpenVINO 工具套件,進(jìn)行深度學(xué)習(xí)等Al項(xiàng)目在C#框架下的部署。該項(xiàng)目由C++語(yǔ)言編寫OpenVINO dll庫(kù),并在C#語(yǔ)言下實(shí)現(xiàn)調(diào)用。

項(xiàng)目可以實(shí)現(xiàn)在C#編程語(yǔ)言下調(diào)用Intel推出的 OpenVINO 工具套件,進(jìn)行深度學(xué)習(xí)等Al項(xiàng)目在C#框架下的部署,目前可以支持的Al模型格式:

■ Paddlepaddle 飛槳模型 (.pdmodel)

■ ONNX 開放式神經(jīng)網(wǎng)絡(luò)交換模型 (.onnx)

■ IR 模型 (.xml, .bin)

目前該項(xiàng)目針對(duì) Paddlepaddle 飛槳現(xiàn)有模型進(jìn)行了測(cè)試,主要有:

■ PaddleClas 飛槳圖像識(shí)別套件

■ PaddleDetection 目標(biāo)檢測(cè)模型套件

1.1.2 OpenVINO

OpenVINO 工具套件是英特爾基于自身現(xiàn)有的硬件平臺(tái)開發(fā)的一種可以加快高性能計(jì)算機(jī)視覺和深度學(xué)習(xí)視覺應(yīng)用開發(fā)速度工具套件,支持各種英特爾平臺(tái)的硬件加速器上進(jìn)行深度學(xué)習(xí),并且允許直接異構(gòu)執(zhí)行。支持在Windows與Linux系統(tǒng),官方支持編程語(yǔ)言為Python與C++語(yǔ)言,但不直接支持C#。

OpenVINO 工具套件2022.1版于2022年3月22日正式發(fā)布,根據(jù)官宣《OpenVINO 迎來迄今為止最重大更新,2022.1新特性搶先看》,OpenVINO 2022.1將是迄今為止最大變化的版本。從開發(fā)者的角度來看,對(duì)于提升開發(fā)效率或運(yùn)行效率有用的特性有:

■ 提供預(yù)處理API函數(shù)

■ ONNX前端API

■ AUTO設(shè)備插件

■ 支持直接讀入飛槳模型

該項(xiàng)目開發(fā)環(huán)境為OpenVINO 2022.1最新版本,因此使用者需在使用時(shí)將自己電腦上的OpenVINO 版本升級(jí)到2022.1版,不然會(huì)有較多的問題。

1.1.3 項(xiàng)目方案

該項(xiàng)目主要通過調(diào)用dll文件方式實(shí)現(xiàn)。通過C++調(diào)用OpenVINO ,編寫模型推理接口,將我們所用到的推理方法在C++中實(shí)現(xiàn),并將其生成dll文件,在C#調(diào)用dll文件,重寫dll文件接口,并重新組建Core類,用于在C#中進(jìn)行模型的推理,其方案如圖1- 1所示。

8d2ca85a-daac-11ec-ba43-dac502259ad0.png

圖1- 1 項(xiàng)目解決方案

1.1.4 安裝方式

該項(xiàng)目所有文件已經(jīng)上傳到Github和Gitee遠(yuǎn)程代碼倉(cāng),大家可以通過Gi在本地進(jìn)行克隆。

● 系統(tǒng)平臺(tái):

Windows

● 軟件要求:

Visual Studio 2022 / 2019 / 2017

OpenCV 4.5.5

OpenVINO 2022.1

● 安裝方式

在Github上克隆下載

git clone https://github.com/guojin-yan/OpenVinoSharp.git

在Gitee上克隆下載:

git clone https://gitee.com/guojin-yan/OpenVinoSharp.git

1.2 軟件安裝

1.2.1 Microsoft Visual Studio 2022安裝

Microsoft Visual Studio(簡(jiǎn)稱VS)是美國(guó)微軟公司的開發(fā)工具套件系列產(chǎn)品。VS是一個(gè)基本完整的開發(fā)工具集,它包括了整個(gè)軟件生命周期中所需要的大部分工具,如UML工具、代碼管控工具、集成開發(fā)環(huán)境(IDE)等等。其支持C、C++、C#、F#、J#等多門編程語(yǔ)言。

本次項(xiàng)目所使用的編程語(yǔ)言為C++與C#兩門編程語(yǔ)言,在VS中完全可以實(shí)現(xiàn),可選擇安裝版本VS2017、VS2019或VS2022版本。對(duì)于VS不同版本的選擇,該項(xiàng)目不做較多要求,就筆者使用來說,VS2017版本推出時(shí)間較久,不建議使用,其一些編程語(yǔ)言規(guī)范有一些變動(dòng),對(duì)于該項(xiàng)目所提供的范例可能會(huì)有部分不兼容;VS2019和VS2022版本相對(duì)更新,是由起來差異不大,建議選擇這兩個(gè)版本,并且新版OpenVINO 支持VS2022版本Cmake。

筆者電腦安裝的為Microsoft Visual Studio Community 2022 版本,其安裝包可由VS官網(wǎng)直接下載,下載時(shí)選擇社區(qū)版,按照一般安裝步驟進(jìn)行安裝即可。在安裝中,工作負(fù)荷的選擇圖1- 2所示。

8d4d634c-daac-11ec-ba43-dac502259ad0.png

圖1- 2 Visual Studio 2022安裝負(fù)荷

安裝完成后,可以參照網(wǎng)上相關(guān)教程,進(jìn)行學(xué)習(xí)VS的使用。

1.2.2 OpenVINO 安裝

該項(xiàng)目所使用的OpenVINO 版本為2022.1版本,是Intel公司在2022年第一季度發(fā)布的最新版本。該版本基于之前版本有了較大變動(dòng),不在默認(rèn)包含OpenCV工具;其次,對(duì)代碼做了更進(jìn)一步的優(yōu)化,使得代碼在使用時(shí)更加靈活。其具體安裝方式,參考

https://www.intel.com/content/www/us/en/developer/tools/openvino-toolkit/download.html

1.2.3 OpenCV安裝

由于最新版的OpenVINO 2022.1 版本不在默認(rèn)附帶OpenCV工具,所以我們需要額外安裝OpenCV工具。

01

下載并安裝OpenCV

訪問OpenCV官網(wǎng),選擇Library下的Releases,進(jìn)入到下載頁(yè)面,或直接訪問進(jìn)入下載頁(yè)面。

8d84a1fe-daac-11ec-ba43-dac502259ad0.png

圖1- 3 OpenCV-4.5.5 版本頁(yè)面

根據(jù)負(fù)載使用情況,選擇Windows版本,如圖1- 3所示,跳轉(zhuǎn)頁(yè)面后,下載文件名為:opencv-4.5.5-vc14_vc15.exe。下載完成后,直接雙擊打開安裝文件,安裝完成后,打開安裝文件夾,該文件夾下 build、sources文件夾以及LICENSE相關(guān)文件,我們所使用的文件在build文件夾中。

02

配置Path環(huán)境變量

右擊我的電腦,進(jìn)入屬性設(shè)置,選擇高級(jí)系統(tǒng)設(shè)置進(jìn)入系統(tǒng)屬性,點(diǎn)擊環(huán)境變量,進(jìn)入到環(huán)境變量設(shè)置,編輯系統(tǒng)變量下的Path變量,增加以下地址變量:

E:OpenCV Sourceopencv-4.5.5uildx64vc15in

E:OpenCV Sourceopencv-4.5.5uildx64vc15lib

E:OpenCV Sourceopencv-4.5.5uildinclude

E:OpenCV Sourceopencv-4.5.5uildincludeopencv2

其中為本機(jī)安裝OpenCV安裝路徑。安裝完成后,如想在VS中使用,還需要再VS編輯器中設(shè)置相關(guān)配置,具體配置會(huì)在下文中說明。

1.3 OpenVINO 推理模型

與測(cè)試數(shù)據(jù)集

1.3.1 模型種類與下載方式

為了測(cè)試該項(xiàng)目,我們提供并整合了訓(xùn)練好的 Paddlepaddle 模型,主要針對(duì) PaddleClas 以及 PaddleDetection 現(xiàn)有的模型,提供了 PaddleClas 下的花卉分類模型以及 PaddleDetection 中的 Vehicle Detection 模型,并針對(duì)該模型,提供了pdmodel、onnx以及IR格式。

該項(xiàng)目所使用的測(cè)試模型以及數(shù)據(jù)集,均可以在本文下的gitee上下載,下載鏈接為:

https://gitee.com/guojin-yan/OpenVinoSharp

1.3.2 PaddleDetection 模型

PaddleDetection 為飛槳 PaddlePaddle 的端到端目標(biāo)檢測(cè)套件,提供多種主流目標(biāo)檢測(cè)、實(shí)例分割、跟蹤、關(guān)鍵點(diǎn)檢測(cè)算法,配置化的網(wǎng)絡(luò)模塊組件、數(shù)據(jù)增強(qiáng)策略、損失函數(shù)等。該項(xiàng)目在此處主要使用的為PaddleDetection應(yīng)用中的目標(biāo)檢測(cè)功能,使用的網(wǎng)絡(luò)為YOLOv3網(wǎng)絡(luò),表1- 1 給出了YOLOv3網(wǎng)絡(luò)輸出與輸入的相關(guān)信息。

表1- 1 YOLOv3模型輸入與輸出節(jié)點(diǎn)信息

8d9e22aa-daac-11ec-ba43-dac502259ad0.png

注:None表示batch維度,H、W 分別為圖片的高和寬,Num表示識(shí)別結(jié)果的數(shù)量。

本次測(cè)試使用的為 PaddleDetection 中 Vehicle Detection 模型,我們可以在 PaddleDetection gitee 上下載。該模型輸入圖片要求為3×608×608大小,輸出為預(yù)測(cè)框信息,其信息組成為[class_id, score, x1, y1, x2, y2],分別代表分類編號(hào)、分類得分以及預(yù)測(cè)框?qū)琼旤c(diǎn)坐標(biāo)。

1.3.3 PaddleClas 模型

飛槳圖像識(shí)別套件 PaddleClas 是飛槳為工業(yè)界和學(xué)術(shù)界提供的的一個(gè)圖像識(shí)別任務(wù)的工具集,該模型經(jīng)過數(shù)據(jù)集訓(xùn)練,可以識(shí)別多種物品。在該項(xiàng)目中,我們使用flower數(shù)據(jù)集,使用ResNet50網(wǎng)絡(luò)訓(xùn)練識(shí)別102種花卉,關(guān)于該模型的輸入與輸出節(jié)點(diǎn)信息如所示

表1- 2 ResNet50模型輸入與輸出節(jié)點(diǎn)信息

8dc816f0-daac-11ec-ba43-dac502259ad0.png

注:None表示batch維度,H、W 分別為圖片的高和寬,Class表示分類數(shù)量。

花卉訓(xùn)練模型要求圖片輸入為3×224×224大小,輸出結(jié)果為102中預(yù)測(cè)結(jié)果概率。

1.4 創(chuàng)建OpenVINO 方法

C++動(dòng)態(tài)鏈接庫(kù)

1.4.1 新建解決方案以及項(xiàng)目文件

打開vs2022,首先新建一個(gè)C++空項(xiàng)目文件,并將同時(shí)新建一個(gè)解決方案命名為:OpenVinoSharp,用于存放后續(xù)其他項(xiàng)目文件。將C++項(xiàng)目命名為:CppOpenVinoAPI。

進(jìn)入項(xiàng)目后,右擊源文件,選擇添加→新建項(xiàng)→C++文件(cpp),進(jìn)行的文件的添加。具體操作如圖1- 4所示。

8de5855a-daac-11ec-ba43-dac502259ad0.png

圖1- 4 新建項(xiàng)目解決方案及C++項(xiàng)目

本次我們需要添加OpenVinoAPIcpp以及Source.def兩個(gè)文件,如圖1- 5所示。

8e2088da-daac-11ec-ba43-dac502259ad0.png

圖1- 5 CppOpenVinoAPIl函數(shù)方法所需文件

1.4.2 配置C++項(xiàng)目屬性

右擊項(xiàng)目,點(diǎn)擊屬性,進(jìn)入到屬性設(shè)置,此處需要設(shè)置項(xiàng)目的配置類型包含目錄、庫(kù)目錄以及附加依賴項(xiàng),本次項(xiàng)目選擇Release模式下運(yùn)行,因此以Release情況進(jìn)行配置。

01

(1)設(shè)置配置與平臺(tái)

進(jìn)入屬性設(shè)置后,在最上面,將配置改為Release,平臺(tái)改為x64。具體操作如圖1- 6所示。

8e4b06d2-daac-11ec-ba43-dac502259ad0.png

圖1- 6 C++項(xiàng)目屬性配置與平臺(tái)設(shè)置

02

設(shè)置常規(guī)屬性

常規(guī)設(shè)置下,點(diǎn)擊輸出目錄,將輸出位置設(shè)置為,即將生成文件放置在項(xiàng)目文件夾下的dll文件夾下;其次將目標(biāo)文件名修改為:OpenVinoSharp;最后將配置類型改為:動(dòng)態(tài)庫(kù)(.dll),讓其生成dll文件。具體操作如圖1- 7所示。

8e78bb9a-daac-11ec-ba43-dac502259ad0.png

圖1- 7 C++項(xiàng)目常規(guī)屬性設(shè)置

03

設(shè)置包含目錄

點(diǎn)擊VC++目錄,然后點(diǎn)擊包含目錄,進(jìn)行編輯,在彈出的新頁(yè)面中,添加以下路徑:

E:OpenCV Sourceopencv-4.5.5uildinclude

E:OpenCV Sourceopencv-4.5.5uildincludeopencv2

C:Program Files (x86)Intelopenvino_2022.1.0.643 untimeinclude

C:Program Files (x86)Intelopenvino_2022.1.0.643 untimeincludeie

其中路徑為OpenCV的安裝路徑,為OpenVINO安裝路徑,個(gè)人根據(jù)自己安裝的位置及版本確定。操作過程如圖1- 8所示。

8ea6c242-daac-11ec-ba43-dac502259ad0.png

圖1- 8 C++項(xiàng)目屬性庫(kù)目錄設(shè)置

04

設(shè)置庫(kù)目錄

同樣的方式,在VC++目錄下,點(diǎn)擊下方的庫(kù)目錄,點(diǎn)擊編輯,在彈出來的頁(yè)面中增加以下路徑:

E:OpenCV Sourceopencv-4.5.5uildx64vc15lib

C:Program Files (x86)Intelopenvino_2022.1.0.643 untimelibintel64Release

如果時(shí)配置Debug模式,則需要將Release文件路徑改為Debug即可。

05

設(shè)置附加依賴項(xiàng)

點(diǎn)擊展開鏈接器,點(diǎn)擊輸入,在附加依賴項(xiàng)中點(diǎn)擊編輯,在彈出來的新的頁(yè)面,添加以下文件名:

opencv_world455.lib

openvino.lib

具體操作步驟參考如圖1-9所示。新版OpenCV與OpenVINO 都將依賴庫(kù)文件合成到了一個(gè)文件中,這極大地簡(jiǎn)化了使用,如果使用老版本的,需要將所有的.lib文件放置在此處即可。

8ee7cc7e-daac-11ec-ba43-dac502259ad0.png

圖1- 9 C++項(xiàng)目屬性附加依賴項(xiàng)設(shè)置

1.4.3 編寫C++代碼

01

推理引擎結(jié)構(gòu)體

Core是OpenVINO 工具套件里的推理核心類,該類下包含多個(gè)方法,可用于創(chuàng)建推理中所使用的其他類。在此處,需要在各個(gè)方法中傳遞的僅僅是所使用的幾個(gè)變量,因此選擇構(gòu)建一個(gè)推理引擎結(jié)構(gòu)體,用于存放各個(gè)變量。

// @brief 推理核心結(jié)構(gòu)體

typedef struct openvino_core {

ov::Core core; // core對(duì)象

std::shared_ptr model_ptr; // 讀取模型指針

ov::CompiledModel compiled_model; // 模型加載到設(shè)備對(duì)象

ov::InferRequest infer_request; // 推理請(qǐng)求對(duì)象

} CoreStruct;

其中Core是OpenVINO 工具套件里的推理機(jī)核心,該模塊只需要初始化;shared_ptr是讀取本地模型的方法,新版更新后,該方法發(fā)生了較大改動(dòng),可支持讀取Paddlepaddle飛槳模型、onnx模型以及IR模型;CompiledModel指的是一個(gè)已編譯的模型類,其主要是將讀取的本地模型應(yīng)用多個(gè)優(yōu)化轉(zhuǎn)換,然后映射到計(jì)算內(nèi)核,由所指定的設(shè)備編譯模型;InferRequest是一個(gè)推理請(qǐng)求類,在推理中主要用于對(duì)推理過程的操作。

02

接口方法規(guī)劃

經(jīng)典的OpenVINO 進(jìn)行模型推理,一般需要八個(gè)步驟,主要是:初始化Core對(duì)象、讀取本地推理模型、配置模型輸入&輸出、載入模型到執(zhí)行硬件、創(chuàng)建推理請(qǐng)求、準(zhǔn)備輸入數(shù)據(jù)、執(zhí)行推理計(jì)算以及處理推理計(jì)算結(jié)果。我們根據(jù)原有的八個(gè)步驟,對(duì)步驟進(jìn)行重新整合,并根據(jù)推理步驟,調(diào)整方法接口。

對(duì)于方法接口,主要設(shè)置為:推理初始化、配置輸入數(shù)據(jù)形狀、配置輸入數(shù)據(jù)、模型推理、讀取推理結(jié)果數(shù)據(jù)以及刪除內(nèi)存地址六個(gè)大類,其中配置輸入數(shù)據(jù)形狀要細(xì)分為配置圖片數(shù)據(jù)形狀以及普通數(shù)據(jù)形狀,配置輸入數(shù)據(jù)要細(xì)分為配置圖片輸入數(shù)據(jù)與配置普通數(shù)據(jù)輸入,讀取推理結(jié)果數(shù)據(jù)細(xì)分為讀取float數(shù)據(jù)和int數(shù)據(jù),因此,總共有6類方法接口,9個(gè)方法接口。

03

初始化推理模型

OpenVINO 推理引擎結(jié)構(gòu)體是聯(lián)系各個(gè)方法的橋梁,后續(xù)所有操作都是在推理引擎結(jié)構(gòu)體中的變量上操作的,為了實(shí)現(xiàn)數(shù)據(jù)在各個(gè)方法之間的傳輸,因此在創(chuàng)建推理引擎結(jié)構(gòu)體時(shí),采用的是創(chuàng)建結(jié)構(gòu)體指針,并將創(chuàng)建的結(jié)構(gòu)體地址作為函數(shù)返回值返回。推理初始化接口主要整合了原有推理的初始化Core對(duì)象、讀取本地推理模型、載入模型到執(zhí)行硬件和創(chuàng)建推理請(qǐng)求步驟,并將這些步驟所創(chuàng)建的變量放在推理引擎結(jié)構(gòu)體中。

初始化推理模型接口方法為:

extern "C" __declspec(dllexport) void* __stdcall core_init(const wchar_t* model_file_wchar, const wchar_t* device_name_wchar);

該方法返回值為CoreStruct結(jié)構(gòu)體指針,其中model_file_wchar為推理模型本地地址字符串指針,device_name_wchar為模型運(yùn)行設(shè)備名指針,在后面使用上述變量時(shí),需要將其轉(zhuǎn)換為string字符串,利用wchar_to_string()方法可以實(shí)現(xiàn)將其轉(zhuǎn)換為字符串格式:

std::string model_file_path = wchar_to_string(model_file_wchar);

std::string device_name = wchar_to_string(device_name_wchar);

模型初始化功能主要包括:初始化推理引擎結(jié)構(gòu)體和對(duì)結(jié)構(gòu)體里面定義的其他變量進(jìn)行賦值操作,其主要是利用InferEngineStruct中創(chuàng)建的Core類中的方法,對(duì)各個(gè)變量進(jìn)行初始化操作:

CoreStruct* p = new CoreStruct(); // 創(chuàng)建推理引擎指針

p->model_ptr = p->core.read_model(model_file_path); // 讀取推理模型

p->compiled_model = p->core.compile_model(p->model_ptr, ?CPU“); // 將模型加載到設(shè)備

p->infer_request = p->compiled_model.create_infer_request(); // 創(chuàng)建推理請(qǐng)求

04

配置輸入數(shù)據(jù)形狀

在新版OpenVINO 2022.1 中,新增加了對(duì)Paddlepaddle 模型以及onnx模型的支持,Paddlepaddle 模型不支持指定指定默認(rèn)bath通道數(shù)量,因此需要在模型使用時(shí)指定其輸入;其次,對(duì)于onnx模型,也可以在轉(zhuǎn)化時(shí)不指定固定形狀,因此在配置輸入數(shù)據(jù)前,需要配置輸入節(jié)點(diǎn)數(shù)據(jù)形狀。其方法接口為:

extern "C" __declspec(dllexport) void* __stdcall set_input_image_sharp(void* core_ptr, const wchar_t* input_node_name_wchar, size_t * input_size);

extern "C" __declspec(dllexport) void* __stdcall set_input_data_sharp(void* core_ptr, const wchar_t* input_node_name_wchar, size_t * input_size);

由于需要配置圖片數(shù)據(jù)輸入形狀與普通數(shù)據(jù)的輸入形狀,在此處設(shè)置了兩個(gè)接口,分別設(shè)置兩種不同輸入的形狀。該方法返回值是CoreStruct結(jié)構(gòu)體指針,但該指針?biāo)鶎?duì)應(yīng)的數(shù)據(jù)中已經(jīng)包含了對(duì)輸入形狀的設(shè)置。第一個(gè)輸入參數(shù)core_ptr是CoreStruct指針,在當(dāng)前方法中,我們要讀取該指針,并將其轉(zhuǎn)換為CoreStruct類型:

CoreStruct* p = (CoreStruct*)core_ptr;

input_node_name_wchar 為待設(shè)置網(wǎng)絡(luò)節(jié)點(diǎn)名,input_size 為形狀數(shù)據(jù)數(shù)組,對(duì)圖片數(shù)據(jù),需要設(shè)置 [batch, dim, height, width] 四個(gè)維度大小,所以input_size數(shù)組傳入4個(gè)數(shù)據(jù),其設(shè)置在形狀主要使用Tensor類下的set_shape()方法:

std::string input_node_name = wchar_to_string(input_node_name_wchar); // 將節(jié)點(diǎn)名轉(zhuǎn)為string類型

ov::Tensor input_image_tensor = p->infer_request.get_tensor(input_node_name); // 讀取指定節(jié)點(diǎn)Tensor

input_image_tensor.set_shape({ input_size[0],input_size[1],input_size[2],input_size[3] }); // 設(shè)置節(jié)點(diǎn)數(shù)據(jù)形狀

05

配置輸入數(shù)據(jù)

在新版OpenVINO 中,Tensor類的T* data()方法,其返回值為當(dāng)前節(jié)點(diǎn)Tensor的數(shù)據(jù)內(nèi)存地址,通過填充Tensor的數(shù)據(jù)內(nèi)存,實(shí)現(xiàn)推理數(shù)據(jù)的輸入。對(duì)于圖片數(shù)據(jù),其最終也是將其轉(zhuǎn)為一維數(shù)據(jù)進(jìn)行輸入,不過為方便使用,此處提供了配置圖片數(shù)據(jù)和普通數(shù)據(jù)的接口,對(duì)于輸入為圖片的方法接口:

extern "C" __declspec(dllexport) void* __stdcall load_image_input_data(void* core_ptr, const wchar_t* input_node_name_wchar, uchar * image_data, size_t image_size);

該方法返回值是CoreStruct結(jié)構(gòu)體指針,但該指針?biāo)鶎?duì)應(yīng)的數(shù)據(jù)中已經(jīng)包含了加載的圖片數(shù)據(jù)。第一個(gè)輸入?yún)?shù)core_ptr是CoreStruct指針,在當(dāng)前方法中,我們要讀取該指針,并將其轉(zhuǎn)換為CoreStruct類型;第二個(gè)輸入?yún)?shù)input_node_name_wchar為待填充節(jié)點(diǎn)名,先將其轉(zhuǎn)為string字符串:

std::string input_node_name = wchar_to_string(input_node_name_wchar);

在該項(xiàng)目中,我們主要使用的是以圖片作為模型輸入的推理網(wǎng)絡(luò),模型主要的輸入為圖片的輸入。其圖片數(shù)據(jù)主要存儲(chǔ)在矩陣image_data和矩陣長(zhǎng)度image_size兩個(gè)變量中。需要對(duì)圖片數(shù)據(jù)進(jìn)行整合處理,利用創(chuàng)建的data_to_mat () 方法,將圖片數(shù)據(jù)讀取到OpenCV中:

cv::Mat input_image = data_to_mat(image_data, image_size);

接下來就是配置網(wǎng)絡(luò)圖片數(shù)據(jù)輸入,對(duì)于節(jié)點(diǎn)輸入是圖片數(shù)據(jù)的網(wǎng)絡(luò)節(jié)點(diǎn),其配置網(wǎng)絡(luò)輸入主要分為以下幾步:

首先,獲取網(wǎng)絡(luò)輸入圖片大小。

使用InferRequest類中的get_tensor ()方法,獲取指定網(wǎng)絡(luò)節(jié)點(diǎn)的Tensor,其節(jié)點(diǎn)要求輸入大小在Shape容器中,通過獲取該容器,得到圖片的長(zhǎng)寬信息:

ov::Tensor input_image_tensor = p->infer_request.get_tensor(input_node_name);

int input_H = input_image_tensor.get_shape()[2]; //獲得“image“節(jié)點(diǎn)的Height

int input_W = input_image_tensor.get_shape()[3]; //獲得“image“節(jié)點(diǎn)的Width

其次,按照輸入要求,處理輸入圖片。

在這一步,我們除了要按照輸入大小對(duì)圖片進(jìn)行放縮之外,還要根據(jù) PaddlePaddle 對(duì)模型輸入的要求進(jìn)行處理。因此處理圖片其主要分為交換RGB通道、放縮圖片以及對(duì)圖片進(jìn)行歸一化處理。在此處我們借助OpenCV來實(shí)現(xiàn)。

OpenCV讀取圖片數(shù)據(jù)并將其放在Mat類中,其讀取的圖片數(shù)據(jù)是BGR通道格式,PaddlePaddle 要求輸入格式為RGB通道格式,其通道轉(zhuǎn)換主要靠一下方式實(shí)現(xiàn):

cv::cvtColor(input_image, blob_image, cv::COLOR_BGR2RGB);

接下來就是根據(jù)網(wǎng)絡(luò)輸入要求,對(duì)圖片進(jìn)行壓縮處理:

cv::resize(blob_image, blob_image, cv::Size(input_H, input_W), 0, 0, cv::INTER_LINEAR);

最后就是對(duì)圖片進(jìn)行歸一化處理,其主要處理步驟就是減去圖像數(shù)值均值,并除以方差。查詢PaddlePaddle模型對(duì)圖片的處理,其均值mean = [0.485, 0.456, 0.406],方差std = [0.229, 0.224, 0.225],利用OpenCV中現(xiàn)有函數(shù),對(duì)數(shù)據(jù)進(jìn)行歸一化處理:

std::vectormean_values{ 0.485 * 255, 0.456 * 255, 0.406 * 255 };

std::vectorstd_values{ 0.229 * 255, 0.224 * 255, 0.225 * 255 };

std::vectorrgb_channels(3);

cv::split(blob_image, rgb_channels); // 分離圖片數(shù)據(jù)通道

for (auto i = 0; i < rgb_channels.size(); i++){

//分通道依此對(duì)每一個(gè)通道數(shù)據(jù)進(jìn)行歸一化處理

rgb_channels[i].convertTo(rgb_channels[i], CV_32FC1, 1.0 / std_values[i], (0.0 – mean_values[i]) / std_values[i]);

}

cv::merge(rgb_channels, blob_image); // 合并圖片數(shù)據(jù)通道

最后,將圖片數(shù)據(jù)輸入到模型中。

在此處,我們重寫了網(wǎng)絡(luò)賦值方法,并將其封裝到 fill_tensor_data_image(ov::Tensor& input_tensor, const cv::Mat& input_image)方法中,input_tensor為模型輸入節(jié)點(diǎn)Tensor類,input_image為處理過的圖片Mat數(shù)據(jù)。因此節(jié)點(diǎn)賦值只需要調(diào)用該方法即可:

fill_tensor_data_image(input_image_tensor, blob_image);

對(duì)于普通數(shù)據(jù)的輸入,其方法接口如下:

extern "C" __declspec(dllexport) void* __stdcall load_input_data(void* core_ptr, const wchar_t* input_node_name_wchar, float* input_data);

與配置圖片數(shù)據(jù)不同點(diǎn),在于輸入數(shù)據(jù)只需要輸入input_data數(shù)組即可。其數(shù)據(jù)處理哦在外部實(shí)現(xiàn),只需要將處理后的數(shù)據(jù)填充到輸入節(jié)點(diǎn)的數(shù)據(jù)內(nèi)存中即可,通過調(diào)用自定義的fill_tensor_data_float(ov::Tensor& input_tensor, float* input_data, int data_size) 方法即可實(shí)現(xiàn):

std::string input_node_name = wchar_to_string(input_node_name_wchar);

ov::Tensor input_image_tensor = p->infer_request.get_tensor(input_node_name); // 讀取指定節(jié)點(diǎn)tensor

int input_size = input_image_tensor.get_shape()[1]; //獲得輸入節(jié)點(diǎn)的長(zhǎng)度

fill_tensor_data_float(input_image_tensor,input_data, input_size); // 將數(shù)據(jù)填充到tensor數(shù)據(jù)內(nèi)存上

06

模型推理

上一步中我們將推理內(nèi)容的數(shù)據(jù)輸入到了網(wǎng)絡(luò)中,在這一步中,我們需要進(jìn)行數(shù)據(jù)推理,這一步中我們留有一個(gè)推理接口:

extern "C" __declspec(dllexport) void* __stdcall core_infer(void* core_ptr)

進(jìn)行模型推理,只需要調(diào)用CoreStruct結(jié)構(gòu)體中的infer_request對(duì)象中的infer()方法即可:

CoreStruct* p = (CoreStruct*)core_ptr;

p->infer_request.infer();

07

讀取推理數(shù)據(jù)

上一步我們對(duì)數(shù)據(jù)進(jìn)行了推理,這一步就需要查詢上一步推理的結(jié)果。對(duì)于我們所使用的模型輸出,主要有float數(shù)據(jù)和int數(shù)據(jù),對(duì)此,留有了兩種數(shù)據(jù)的查詢接口,其方法為:

extern "C" __declspec(dllexport) void __stdcall read_infer_result_F32(void* core_ptr, const wchar_t* output_node_name_wchar, int data_size, float* infer_result);

extern "C" __declspec(dllexport) void __stdcall read_infer_result_I32(void* core_ptr, const wchar_t* output_node_name_wchar, int data_size, int* infer_result);

其中data_size為讀取數(shù)據(jù)長(zhǎng)度,infer_result 為輸出數(shù)組指針。讀取推理結(jié)果數(shù)據(jù)與加載推理數(shù)據(jù)方式相似,依舊是讀取輸出節(jié)點(diǎn)處數(shù)據(jù)內(nèi)存的地址:

const ov::Tensor& output_tensor = p->infer_request.get_tensor(output_node_name);

const float* results = output_tensor.data();

針對(duì)讀取整形數(shù)據(jù),其方法一樣,只是在轉(zhuǎn)換類型時(shí),需要將其轉(zhuǎn)換為整形數(shù)據(jù)即可。我們讀取的初始數(shù)據(jù)為二進(jìn)制數(shù)據(jù),因此要根據(jù)指定類型轉(zhuǎn)換,否則數(shù)據(jù)會(huì)出現(xiàn)錯(cuò)誤。將數(shù)據(jù)讀取出來后,將其放在數(shù)據(jù)結(jié)果指針中,并將所有結(jié)果賦值到輸出數(shù)組中:

for (int i = 0; i < data_size; i++) {

*inference_result = results[i];

inference_result++;

}

08

刪除推理核心結(jié)構(gòu)體指針

推理完成后,我們需要將在內(nèi)存中創(chuàng)建的推理核心結(jié)構(gòu)地址刪除,防止造成內(nèi)存泄露,影響電腦性能,其接口該方法為:

extern "C" __declspec(dllexport) void __stdcall core_delet(void* core_ptr);

在該方法中,我們只需要調(diào)用delete命令,將結(jié)構(gòu)體指針刪除即可。

1.4.4 編寫模塊定義文件

我們?cè)诙x接口方法時(shí),在原有方法的基礎(chǔ)上,增加了extern "C" 、 __declspec(dllexport) 以及__stdcall 三個(gè)標(biāo)識(shí),其主要原因是為了讓編譯器識(shí)別我們的輸出方法。其中,extern ?C“是指示編譯器這部分代碼按C語(yǔ)言(而不是C++)的方式進(jìn)行編譯;__declspec(dllexport)用于聲明導(dǎo)出函數(shù)、類、對(duì)象等供外面調(diào)用;__stdcall是一種函數(shù)調(diào)用約定。通過上面三個(gè)標(biāo)識(shí),我們?cè)贑++種所寫的接口方法,會(huì)在dll文件中暴露出來,并且可以實(shí)現(xiàn)在C#中的調(diào)用。

不過上面所說內(nèi)容,我們?cè)诰庉嬈髦锌梢酝ㄟ^模塊定義文件(.def)所實(shí)現(xiàn),在模塊定義文件中,添加以下代碼:

LIBRARY

"OpenVinoSharp"

EXPORTS

core_init

set_input_image_sharp

set_input_data_sharp

load_image_input_data

load_input_data

core_infer

read_infer_result_F32

read_infer_result_I32

core_delet

LIBRARY后所跟的為輸出文件名,EXPORTS后所跟的為輸出方法名。僅需要以上語(yǔ)句便可以替代extern "C" 、 __declspec(dllexport) 以及__stdcall的使用。

1.4.5 生成dll文件

前面我們將項(xiàng)目配置輸出設(shè)置為了生成dll文件,因此該項(xiàng)目不是可以執(zhí)行的exe文件,只能生成不能運(yùn)行。右鍵項(xiàng)目,選擇重新生成/生成。在沒有錯(cuò)誤的情況下,會(huì)看到項(xiàng)目成功的提示??梢钥吹絛ll文件在解決方案同級(jí)目錄下x64Release文件夾下。

使用dll文件查看器打開dll文件,如圖1- 10所示;可以看到,我們創(chuàng)建的四個(gè)方法接口已經(jīng)暴露在dll文件中。

8f17535e-daac-11ec-ba43-dac502259ad0.png

圖1- 10 dll文件方法輸出目錄

1.5 C#構(gòu)建Core類

1.5.1 新建C#類庫(kù)

右擊解決方案,添加->新建項(xiàng)目,選擇添加C#類庫(kù),項(xiàng)目名命名為OpenVinoSharp,項(xiàng)目框架根據(jù)電腦中的框架選擇,此處使用的是.NET 5.0。新建完成后,然后右擊項(xiàng)目,選擇添加->新建項(xiàng),選擇類文件,添加Core.cs和NativeMethods.cs兩個(gè)類文件。

1.5.2 引入dll文件中的方法

在NativeMethods.cs文件下,我們通過[DllImport()]方法,將dll文件中所有的方法讀取到C#中。讀取方式如下:

[DllImport(openvino_dll_path, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]

public extern static IntPtr core_init(string model_file, string device_name);

其中openvino_dll_path為dll文件路徑,CharSet = CharSet.Unicode代表支持中文編碼格式字符串,CallingConvention = CallingConvention.Cdecl指示入口點(diǎn)的調(diào)用約定為調(diào)用方清理堆棧。

上述所列出的為初始化推理模型,dlii文件接口在匹配時(shí),是通過方法名字匹配的,因此,方法名要保證與dll文件中一致。其次就是方法的參數(shù)類型要進(jìn)行對(duì)應(yīng),在上述方法中,函數(shù)的返回值在C++中為void* ,在C#中對(duì)應(yīng)的為IntPtr類型,輸入?yún)?shù)中,在C++中為wchar_t* 字符指針,在C#中對(duì)應(yīng)的為string字符串。通過方法名與參數(shù)類型一一對(duì)應(yīng),在C#可以實(shí)現(xiàn)對(duì)方法的調(diào)用。其他方法的引用類似,在此處不在一一贅述,具體可以參照項(xiàng)目提供的源代碼。

1.5.3 創(chuàng)建Core類

為了更方便地調(diào)用我們通過dll引入的OpenVINO 方法,減少使用時(shí)的函數(shù)方法接口,我們?cè)贑#中重新組建我們自己的推理類,命名為Class Core,其主要成員變量和方法如圖1- 11所示。

8f4a8170-daac-11ec-ba43-dac502259ad0.png

圖1- 11 Core類圖

在Core.類中,我們只需要?jiǎng)?chuàng)建一個(gè)地址變量,作為Core類的成員變量,用于接收接口函數(shù)返回的推理核心指針,該成員變量我們只需要在當(dāng)前類下訪問,因此將其設(shè)置為私有變量:

private IntPtr ptr = new IntPtr();

接下來,構(gòu)建類的構(gòu)造函數(shù),在類的初始化時(shí),我們需要輸入模型地址以及設(shè)備類型,通過掉用dll文件中引入的方法,獲取初始化指針,對(duì)成員變量進(jìn)行賦值,實(shí)現(xiàn)類的初始化:

public Core(string model_file, string device_name) {

ptr = NativeMethods.core_init(model_file, device_name);

}

然后構(gòu)其中的方法,在構(gòu)建設(shè)置數(shù)據(jù)輸入形狀時(shí),我們需要提供的為節(jié)點(diǎn)名以及形狀數(shù)據(jù),為了簡(jiǎn)化該方法,我們合并了圖片形狀設(shè)置與普通數(shù)據(jù)形狀設(shè)置接口,通過判斷輸入數(shù)組的長(zhǎng)度,來確定是對(duì)那一個(gè)形狀的設(shè)置:

public void set_input_sharp(string input_node_name, ulong[] input_size);

對(duì)于該類中方法的構(gòu)建,可以參考源碼文件,在此處不做詳述。并且其他方法構(gòu)建方式基本相似,此處不在一一贅述,具體可以參考源碼文檔。

1.5.4 編譯Core類庫(kù)

右擊項(xiàng)目,點(diǎn)擊生成/重新生成,出現(xiàn)如下圖1- 12所示,表示編譯成功。

8f770f88-daac-11ec-ba43-dac502259ad0.png

圖1- 12 Core類編譯輸出

1.6 C#實(shí)現(xiàn)OpenVINO

方法的調(diào)用

1.6.1 新建C#項(xiàng)目

右擊解決方案,添加->新建項(xiàng)目,選擇添加C#控制臺(tái)項(xiàng)目,項(xiàng)目框架根據(jù)電腦中的框架選擇,此處使用的是.NET 5.0。

8f9a2220-daac-11ec-ba43-dac502259ad0.png

圖1- 13 C#項(xiàng)目設(shè)置

1.6.2 添加OpenCVsharp

右擊項(xiàng)目,選擇管理NuGet程序包,在新頁(yè)面中選擇瀏覽,在搜索框中輸入opencvsharp3,在搜索結(jié)果中,找到OpenCvSharp3-AnyCPU,然后右側(cè)點(diǎn)擊安裝,具體操作步驟如圖1- 14所示。

8fbc90bc-daac-11ec-ba43-dac502259ad0.png

圖1- 14 NuGet程序包安裝

1.6.3添加項(xiàng)目引用

上一步中我們將dll文件中的方法引入到C#中,并組建了Core類,在這一步中,我們主要通過調(diào)用Core類,進(jìn)行Al模型的部署,所以需要引入上一步的項(xiàng)目。

右擊當(dāng)前項(xiàng)目,選擇添加,選擇項(xiàng)目引用,在出現(xiàn)的窗體中,選擇上一步中創(chuàng)建的項(xiàng)目OpenVinoSharp,點(diǎn)擊確定;然后在當(dāng)前項(xiàng)目下,添加using OpenVinoSharp命名空間。具體操作如圖1- 15所示。

8ff0cada-daac-11ec-ba43-dac502259ad0.png

圖1- 15 添加項(xiàng)目引用

1.6.4 編寫代碼測(cè)試花卉分類模型

在該項(xiàng)目中,我們提供了兩種推理模型,此處我們以花卉分類模型為例,簡(jiǎn)介如何通過C#調(diào)用OpenVINO 進(jìn)行Al模型的部署。

01

引入相關(guān)變量

string device_name = "CPU";

string model_file = "E:/Text_Model/flowerclas/flower_rec.onnx";

string image_file = "E:/Text_dataset/flowers102/jpg/image_00001.jpg";

string input_node_name = "x";

string output_node_name = "softmax_1.tmp_0";

為了讓大家更加清晰的看懂后續(xù)代碼,在此處對(duì)引入的相關(guān)變量進(jìn)行解釋:

device_name:設(shè)備類型名稱,可為CPU、GPU以及AUTO(均可);

model_file:模型地址,可以為onnx、pdmodel或者xml格式;

image_file:測(cè)試圖片地址;

input_node_name:輸入模型節(jié)點(diǎn)名,當(dāng)多輸入時(shí),可以為數(shù)組;

output_node_name:輸出模型節(jié)點(diǎn)名,當(dāng)多輸出時(shí),可以為數(shù)組。

02

初始化Core類

在此處我們直接調(diào)用Core類的構(gòu)造函數(shù),進(jìn)行初始化:

Core ie = new Core(model_file_paddle, device_name);

03

配置模型輸入

花卉分類模型輸入只有一個(gè),即待分類花卉圖片。如果我們調(diào)用的模型未指定輸入大小,需要在輸入數(shù)據(jù)前,調(diào)用模型輸入數(shù)據(jù)形狀設(shè)置方法,設(shè)置節(jié)點(diǎn)輸入數(shù)據(jù)形狀。圖片數(shù)據(jù)為三維數(shù)組,再加一個(gè)batchsize,最終為四維數(shù)據(jù),將形狀數(shù)據(jù)放在數(shù)組中,調(diào)用set_input_sharp()方法:

ulong[] image_sharp = new ulong[] { 1, 3, 224, 224 };

ie.set_input_sharp(input_node_name, image_sharp);

對(duì)于圖片數(shù)據(jù),需要將其轉(zhuǎn)為轉(zhuǎn)為矩陣數(shù)據(jù),在此處,我們可以直接使用opencvsharp中的編解碼方法,將圖片數(shù)據(jù)放置在byte數(shù)組中:

Mat image = new Mat(image_file);

byte[] image_data = new byte[2048 * 2048 * 3];

ulong image_size = new ulong();

image_data = image.ImEncode(".bmp");

image_size = Convert.ToUInt64(image_data.Length);

就最后調(diào)用Core類中的load _input_data()方法,將數(shù)據(jù)加載到推理網(wǎng)絡(luò)中:

ie.load_input_data(input_node_name, image_data, image_size);

在配置完輸入數(shù)據(jù)后,調(diào)用模型推理方法,對(duì)輸入數(shù)據(jù)進(jìn)行推理:

ie.infer();

接下來就是讀取推理結(jié)果,對(duì)于模型的推理結(jié)果輸出一般為數(shù)組數(shù)據(jù),可以通過調(diào)用Core類中讀取推理數(shù)據(jù)結(jié)果的方法,對(duì)與花卉分類模型的輸出,其結(jié)果為長(zhǎng)度為102的浮點(diǎn)型數(shù)據(jù),所以直接調(diào)用read_inference_result ()方法讀取即可:

float[] result = new float[102];

result = ie.read_infer_result(output_node_name, 102);

在讀取推理數(shù)據(jù)時(shí),我們一定要根據(jù)模型的書名讀取正確的結(jié)果數(shù)據(jù),因?yàn)槿绻鰧?shí)際輸出長(zhǎng)度,其結(jié)果數(shù)據(jù)會(huì)摻雜其他干擾數(shù)據(jù)。

最后一步就是處理輸出數(shù)據(jù)。對(duì)于不同的推理模型,其結(jié)果處理方式是不同的,對(duì)于花卉分類模型,其輸出為102種分類情況打分,因此,在處理數(shù)據(jù)時(shí),需要找出得分最高的哪一類即可。在此處,我們提供了一個(gè)方法,該方法可以實(shí)現(xiàn)提取數(shù)組中前N個(gè)max數(shù)據(jù)的位置,通過調(diào)用該方法,我們可以獲取分類結(jié)果中分?jǐn)?shù)最高的幾個(gè)結(jié)果,并將結(jié)果打印輸出:

int[] index = find_array_max(result,5);

for (int i = 0; i < 5; i++){

Console.WriteLine("the index is {0} , the score is {1} ", index[i], result[index[i]]);

}

最終輸出結(jié)果如圖1- 16所示,該頁(yè)面打印出來了推理結(jié)果預(yù)測(cè)分?jǐn)?shù)最大的前五個(gè)分?jǐn)?shù)和其對(duì)應(yīng)的索引值,最后可以通過索引值查詢flowers102_label_list.txt文件中對(duì)應(yīng)的花卉名稱。

9017a6c8-daac-11ec-ba43-dac502259ad0.png

圖1- 16 花卉分類結(jié)果

在程序最后,我們?cè)撔枰獙⑶懊嬖趦?nèi)存上創(chuàng)建推理引擎結(jié)構(gòu)體進(jìn)行刪除,只需要調(diào)用Core類下的delet()即可。

1.6.5 編寫代碼測(cè)試車輛識(shí)別模型

對(duì)于車輛識(shí)別模型此處不再進(jìn)行詳細(xì)講解,具體實(shí)現(xiàn)可以參考源碼文件,此處只對(duì)一些不同點(diǎn)進(jìn)行分析。

在配置輸入時(shí),除了需要配置圖片數(shù)據(jù)輸入,還需要配置圖片長(zhǎng)寬數(shù)據(jù)以及長(zhǎng)寬縮放比例數(shù)據(jù),在配置時(shí),只需要將數(shù)據(jù)放置在數(shù)組中,通過調(diào)用load_input_data()方法實(shí)現(xiàn),對(duì)于設(shè)置縮放比例數(shù)據(jù)輸入,如下所示:

float scale_h = 608.00f / image.Height;

float scale_w = 608.00f / image.Width;

float[] scale_factor = new float[] { scale_h, scale_w };

ie.load_input_data(input_node_name[1], scale_factor);

對(duì)于該模型推理結(jié)果數(shù)據(jù),總共有兩個(gè)節(jié)點(diǎn)輸出,一個(gè)是識(shí)別結(jié)果數(shù)量,一個(gè)為識(shí)別結(jié)果信息。對(duì)于識(shí)別結(jié)果數(shù)量,其數(shù)據(jù)類型為整形數(shù)據(jù),對(duì)于單圖片輸入,只需要讀取一位即可,利用該數(shù)據(jù),確定識(shí)別結(jié)果信息長(zhǎng)度。識(shí)別結(jié)果信息為6列N行數(shù)據(jù),在數(shù)據(jù)讀取時(shí),我們將其轉(zhuǎn)化為一維數(shù)據(jù),所以在處理數(shù)據(jù)時(shí),以6位數(shù)據(jù)為一組,進(jìn)行處理。

識(shí)別結(jié)果信息數(shù)據(jù)中,第1位為識(shí)別標(biāo)簽,第2位為識(shí)別得分,第3位到第6位四個(gè)數(shù)據(jù)為位置矩形框?qū)屈c(diǎn)坐標(biāo),通過每6位讀取一次數(shù)據(jù),獲取識(shí)別結(jié)果。在此處,我們提供了專門的結(jié)果處理方法,通過該方法們可以實(shí)現(xiàn)直接將結(jié)果繪制在原圖片上:

image = draw_image_resule(image, resule_num[0], result, lable, 0.2f);

其中image為原圖片,resule_num[0]為識(shí)別結(jié)果數(shù)量,result為識(shí)別結(jié)果數(shù)組,lable為結(jié)果標(biāo)簽,0.2f為評(píng)價(jià)得分下限。通過結(jié)果處理,將識(shí)別結(jié)果標(biāo)注在圖片中,并把識(shí)別結(jié)果以及得分情況打印在圖片中,最終識(shí)別結(jié)果如圖1- 17所示。

906c92e6-daac-11ec-ba43-dac502259ad0.png

圖1- 17 車輛類型識(shí)別結(jié)果輸出

1.7 程序時(shí)間分析

為了對(duì)比C++、C#以及Python這三個(gè)平臺(tái)下調(diào)用OpenVINO 所使用的時(shí)間,我們通過測(cè)試flower_clas以及vehicle_yolov3_darknet模型運(yùn)行時(shí)間進(jìn)行對(duì)比,在同一臺(tái)電腦相同運(yùn)行環(huán)境之下,以及對(duì)模型的處理方式在不同編程語(yǔ)言下盡量做到相同,在程序測(cè)試100次之后,得到結(jié)果表1- 3如所示。

表1- 3 程序運(yùn)行時(shí)間

90f4cfbc-daac-11ec-ba43-dac502259ad0.png

在本次檢測(cè)中,我們通過C++、C#以及Python分別調(diào)用OpenVINO 進(jìn)行模型的部署與推理,通過上述表格,一方面可以看出,C#通過調(diào)用C++的dll,實(shí)現(xiàn)模型的部署與推理,并沒有太大的影響程序的運(yùn)行速度;另一方面,C++與C#部署模型推理,在總時(shí)間上來看,運(yùn)行速度是優(yōu)于Python的。

測(cè)試模型運(yùn)行時(shí)間所使用的測(cè)試代碼,已同步到遠(yuǎn)程成代碼托管倉(cāng)庫(kù)gitee與github中,具體在https://gitee.com/guojin-yan/OpenVinoSharp/tree/master/openvino_run_time文件夾下,使用人員可以根據(jù)自己的設(shè)備對(duì)C++、C#和Python三個(gè)平臺(tái)進(jìn)行測(cè)試。

1.8 項(xiàng)目總結(jié)

該項(xiàng)目通過C++調(diào)用OpenVINO ,創(chuàng)建推理方法接口,并通過調(diào)用dll文件的方式,在C#中進(jìn)行重新構(gòu)建Core模型推理類,并測(cè)試了花卉分類模型以及車輛識(shí)別模型,在預(yù)測(cè)結(jié)果精度以及預(yù)測(cè)時(shí)間上,和C++相比,并沒有較大的差異。

該項(xiàng)目所提供的方法,證實(shí)了C#平臺(tái)調(diào)用OpenVINO 的可行性,為后續(xù)在C#部署OpenVINO 模型提供了一個(gè)技術(shù)途徑。本文所有源代碼參見:

https://gitee.com/guojin-yan/OpenVinoSharp

審核編輯 :李倩

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 英特爾
    +關(guān)注

    關(guān)注

    61

    文章

    9964

    瀏覽量

    171776
  • 編程語(yǔ)言
    +關(guān)注

    關(guān)注

    10

    文章

    1945

    瀏覽量

    34736
  • 深度學(xué)習(xí)
    +關(guān)注

    關(guān)注

    73

    文章

    5503

    瀏覽量

    121162

原文標(biāo)題:在C#中調(diào)用OpenVINO? 模型 | 開發(fā)者實(shí)戰(zhàn)

文章出處:【微信號(hào):CVSCHOOL,微信公眾號(hào):OpenCV學(xué)堂】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    服務(wù)器數(shù)據(jù)恢復(fù)—LINUX系統(tǒng)刪除/格式化的數(shù)據(jù)恢復(fù)可行性分析

    基于linux的文件系統(tǒng)(EXT2/EXT3/EXT4/Reiserfs/Xfs) 下刪除或者格式化的數(shù)據(jù)恢復(fù)流程和可行性。
    的頭像 發(fā)表于 12-06 13:52 ?138次閱讀

    請(qǐng)問帶調(diào)零的同相放大電路可行嗎?

    實(shí)現(xiàn)同相放大的同時(shí)有兼顧調(diào)零(不想用兩個(gè)反向放大器實(shí)現(xiàn)),后面接的分壓電阻是為了縮小電壓輸出的,請(qǐng)教可行性
    發(fā)表于 09-20 15:04

    單CPU 雙項(xiàng)目開發(fā)實(shí)現(xiàn)更好的維護(hù)可行性應(yīng)用說明

    電子發(fā)燒友網(wǎng)站提供《單CPU 雙項(xiàng)目開發(fā)實(shí)現(xiàn)更好的維護(hù)可行性應(yīng)用說明.pdf》資料免費(fèi)下載
    發(fā)表于 09-12 09:42 ?0次下載
    單CPU 雙項(xiàng)目開發(fā)實(shí)現(xiàn)更好的維護(hù)<b class='flag-5'>性</b>和<b class='flag-5'>可行性</b>應(yīng)用說明

    使用OpenVINO C# API部署YOLO-World實(shí)現(xiàn)實(shí)時(shí)開放詞匯對(duì)象檢測(cè)

    的快速準(zhǔn)確識(shí)別,并通過AR技術(shù)將虛擬元素與真實(shí)場(chǎng)景相結(jié)合,為用戶帶來沉浸式的交互體驗(yàn)。在本文中,我們將結(jié)合OpenVINO C# API使用最新發(fā)布的OpenVINO 2024.0部署 YOLO-World實(shí)現(xiàn)實(shí)時(shí)開放詞匯對(duì)象檢
    的頭像 發(fā)表于 08-30 16:27 ?654次閱讀
    使用<b class='flag-5'>OpenVINO</b> <b class='flag-5'>C#</b> API部署YOLO-World實(shí)現(xiàn)實(shí)時(shí)開放詞匯對(duì)象檢測(cè)

    OpenVINO2024 C++推理使用技巧

    很多人都使用OpenVINO新版的C++ 或者Python的SDK,都覺得非常好用,OpenVINO2022之后的版本C++ SDK做了大量的優(yōu)化與整理,已經(jīng)是非常貼近開發(fā)的使用習(xí)慣與
    的頭像 發(fā)表于 07-26 09:20 ?907次閱讀

    人臉識(shí)別技術(shù)的可行性在于矛盾具有什么

    人臉識(shí)別技術(shù)的可行性在于矛盾具有普遍。 一、引言 人臉識(shí)別技術(shù)作為人工智能領(lǐng)域的一項(xiàng)重要技術(shù),近年來得到了廣泛的關(guān)注和應(yīng)用。然而,隨著技術(shù)的發(fā)展,人臉識(shí)別技術(shù)也面臨著越來越多的挑戰(zhàn)和問題。本文將從
    的頭像 發(fā)表于 07-04 09:28 ?514次閱讀

    防靜電的可行性措施

    靜電防護(hù)是一種具有系統(tǒng)、站體化、全過程的綜合工作,不但需要相當(dāng)復(fù)雜的相關(guān)技術(shù)措施,而且需要強(qiáng)有力的和健全的治理措施;不但要求工程技術(shù)人員參和,理要求操作人員、使用及維護(hù)人員參和。
    的頭像 發(fā)表于 07-03 15:54 ?288次閱讀

    OpenVINO C# API在intel平臺(tái)部署YOLOv10目標(biāo)檢測(cè)模型

    的模型設(shè)計(jì)策略,從效率和精度兩個(gè)角度對(duì)YOLOs的各個(gè)組成部分進(jìn)行了全面優(yōu)化,大大降低了計(jì)算開銷,增強(qiáng)了性能。在本文中,我們將結(jié)合OpenVINO C# API使用最新發(fā)布的OpenVINO 2024.1部署YOLOv10目標(biāo)檢
    的頭像 發(fā)表于 06-21 09:23 ?1037次閱讀
    用<b class='flag-5'>OpenVINO</b> <b class='flag-5'>C#</b> API在intel<b class='flag-5'>平臺(tái)</b>部署YOLOv10目標(biāo)檢測(cè)模型

    振弦采集儀在巖土工程地質(zhì)災(zāi)害監(jiān)測(cè)中的可行性研究

    振弦采集儀在巖土工程地質(zhì)災(zāi)害監(jiān)測(cè)中的可行性研究 引言: 巖土工程地質(zhì)災(zāi)害是指在巖土體中由于自然力和人類活動(dòng)等因素引起的,對(duì)人類生活、財(cái)產(chǎn)以及環(huán)境造成威脅的災(zāi)害。為了及時(shí)發(fā)現(xiàn)并準(zhǔn)確監(jiān)測(cè)地質(zhì)災(zāi)害的發(fā)生
    的頭像 發(fā)表于 05-28 14:09 ?322次閱讀
    振弦采集儀在巖土工程地質(zhì)災(zāi)害監(jiān)測(cè)中的<b class='flag-5'>可行性</b>研究

    關(guān)于電化學(xué)儲(chǔ)能的BMS可行性方案

    基于嵌入式ARM核心板實(shí)現(xiàn)的BMS可行性方案,希望可幫助相關(guān)企業(yè)作為參考。 二、電池管理系統(tǒng)(BMS)BMS主要由電池陣列管理單元(BAMS)、電池蔟管理單元(BCMS)以及電池管理單元(BMU)組成
    發(fā)表于 05-16 17:08

    千萬(wàn)不要忽視了零件選型調(diào)用

    選型和調(diào)用,是確保產(chǎn)品設(shè)計(jì)質(zhì)量、可靠和制造可行性的基礎(chǔ)。隨著供應(yīng)鏈短缺和信賴性要求提高,這一環(huán)節(jié)變得越發(fā)重要。設(shè)計(jì)工具的元器件庫(kù)集成和智能搜索功能,可以極大提高
    的頭像 發(fā)表于 05-14 13:28 ?539次閱讀
    千萬(wàn)不要忽視了零件選型<b class='flag-5'>調(diào)用</b>

    振弦采集儀在地下水位監(jiān)測(cè)中的可行性研究與實(shí)踐

    振弦采集儀在地下水位監(jiān)測(cè)中的可行性研究與實(shí)踐 地下水位的監(jiān)測(cè)對(duì)于水資源管理和地下水環(huán)境保護(hù)具有重要意義。傳統(tǒng)的地下水位監(jiān)測(cè)方法主要包括井水位計(jì)、壓力傳感器和雨水入滲監(jiān)測(cè)等。然而,這些方法存在著一些
    的頭像 發(fā)表于 04-08 13:38 ?274次閱讀
    振弦采集儀在地下水位監(jiān)測(cè)中的<b class='flag-5'>可行性</b>研究與實(shí)踐

    高壓探頭測(cè)量相間電壓的可行性與注意事項(xiàng)

    可行性,并介紹在使用高壓探頭測(cè)量相間電壓時(shí)需要注意的事項(xiàng)。 高壓探頭的原理: 高壓探頭是一種專門設(shè)計(jì)用于測(cè)量高電壓的探頭。它通常由絕緣材料包圍,以確保安全,并具有適當(dāng)?shù)碾姎馓匦詠硖幚砀唠妷骸8邏禾筋^通過
    的頭像 發(fā)表于 04-07 14:24 ?526次閱讀
    高壓探頭測(cè)量相間電壓的<b class='flag-5'>可行性</b>與注意事項(xiàng)

    基于英特爾哪吒開發(fā)者套件平臺(tái)來快速部署OpenVINO Java實(shí)戰(zhàn)

    OpenVINO 工具套件基于OneAPI開發(fā),可以加快高性能計(jì)算機(jī)視覺和深度學(xué)習(xí)應(yīng)用開發(fā)速度的工具套件,適用于從邊緣到云的各種英特爾計(jì)算平臺(tái)
    的頭像 發(fā)表于 03-21 18:24 ?1496次閱讀
    基于英特爾哪吒開發(fā)者套件<b class='flag-5'>平臺(tái)</b>來快速部署<b class='flag-5'>OpenVINO</b> Java實(shí)戰(zhàn)

    七段式SVPWM優(yōu)化電機(jī)電磁噪聲的量產(chǎn)可行性驗(yàn)證

    七段式SVPWM優(yōu)化電機(jī)電磁噪聲的量產(chǎn)可行性驗(yàn)證
    的頭像 發(fā)表于 03-21 17:28 ?1164次閱讀
    七段式SVPWM優(yōu)化電機(jī)電磁噪聲的量產(chǎn)<b class='flag-5'>可行性</b>驗(yàn)證
    主站蜘蛛池模板: 精品二区| 色多多拼多多网站| 日本www黄| 好紧好爽太大了h快穿| 色男人社区| 欧美特黄一区二区三区| 一级视频在线| 202z欧美成人| 亚洲综合精品| 激情六月婷婷开心丁香开心| 免费看美女禁处爆涌视频| 日本一区不卡视频| 免费人成在线观看网站| 人人爽人人干| 综合色区| 日本成片免费高清| 午夜毛片免费观看视频| 国产精品片| 性毛片| 国产精品毛片在线大全| 三级成人网| 男人操女人视频在线观看| 四虎日韩| 国产精品久久国产三级国不卡顿| 国产精品莉莉欧美自在线线| 性欧美视频videos6一9| 99pao在线视频精品免费| 亚洲日本免费| 四虎国产永久在线精品免费观看| 777国产精品永久免费观看| 亚洲综合一二三区| 美女被羞羞产奶视频网站| 国产综合在线观看| 亚洲jizzjizz中文在线播放| 97综合| 欧美性xxxxxbbbbbb精品| 久久黄色精品视频| 欧美射射射| 五月婷婷色网| 手机看片福利日韩| 性欧美xxxxhd|