用 OpenVINO C++ API 編寫 YOLOv8-Seg 實例分割模型推理程序
1.1
簡介
?
本文章將介紹使用?OpenVINO??2023.0?C++ API 開發(fā)YOLOv8-Seg 實例分割(Instance Segmentation)模型的AI推理程序。本文 C++ 范例程序的開發(fā)環(huán)境是 Windows + Visual Studio Community 2022,請讀者先配置基于 Visual Studio的OpenVINO C++ 開發(fā)環(huán)境。
?
請克隆本文的代碼倉:git clone https://gitee.com/ppov-nuc/yolov8_openvino_cpp.git
?
1.2
導(dǎo)出 YOLOv8-Seg OpenVINO IR 模型
?
YOLOv8是 Ultralytics 公司基于 YOLO 框架,發(fā)布的一款面向物體檢測與跟蹤、實例分割、圖像分類和姿態(tài)估計任務(wù)的 SOTA 模型工具套件。
?
首先用命令pip install -r requirements.txt 安裝ultralytics 和 openvino-dev。
?
然后使用命令:yolo export model=yolov8n-seg.pt format=openvino half=True,導(dǎo)出FP16精度的? OpenVINO IR 模型,如下圖所示。

?
接著使用命令:benchmark_app -m yolov8n-seg.xml -d GPU.1,獲得yolov8n-seg.xml 模型在 A770m 獨立顯卡上的異步推理計算性能,如下圖所示。

?
1.3
使用 OpenVINO C++ API 編寫 YOLOv8-Seg 實例分割模型推理程序
?
使用 OpenVINO C++ API 編寫 YOLOv8-Seg 實例分割模型推理程序主要有5個典型步驟:
1.?采集圖像&圖像解碼
2.?圖像數(shù)據(jù)預(yù)處理
3.?AI推理計算(基于 OpenVINO C++ API)
4.?對推理結(jié)果進行后處理
5.?將處理后的結(jié)果可視化
?

?
YOLOv8-Seg 實例分割模型推理程序的圖像數(shù)據(jù)預(yù)處理和AI推理計算的實現(xiàn)方式跟 YOLOv8 目標(biāo)檢測模型推理程序的實現(xiàn)方式幾乎一模一樣,可以直接復(fù)用。
?
1.3.1?圖像數(shù)據(jù)預(yù)處理
?
使用 Netron 打開 yolov8n-seg.onnx,如下圖所示,可以看到:
?輸入節(jié)點的名字:“images”;數(shù)據(jù):float32[1,3,640,640]
?輸出節(jié)點1的名字:“output0”;數(shù)據(jù):float32[1,116,8400]。其中116的前84個字段跟 YOLOv8目標(biāo)檢測模型輸出定義完全一致,即cx,cy,w,h和80類的分?jǐn)?shù);后32個字段為掩膜置信度,用于計算掩膜數(shù)據(jù)。
輸出節(jié)點2的名字:“output1”;數(shù)據(jù):float32[1,32,160,160]。output0后32個字段與output1的數(shù)據(jù)做矩陣乘法后得到的結(jié)果,即為對應(yīng)目標(biāo)的掩膜數(shù)據(jù) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

?
圖像數(shù)據(jù)預(yù)處理的目標(biāo)就是將任意尺寸的圖像數(shù)據(jù)轉(zhuǎn)變?yōu)樾螤顬閇1,3,640,640],精度為 FP32的張量。YOLOv8-Seg 模型的輸入尺寸為正方形,為了解決將任意尺寸數(shù)據(jù)放縮為正方形帶來的圖像失真問題,在圖像放縮前,采用 letterbox 算法先保持圖像的長寬比,如下圖所示,然后再使用 cv::dnn::blobFromImage 函數(shù)對圖像進行放縮。

?
圖像數(shù)據(jù)預(yù)處理的范例程序如下所示

?
1.3.2? AI同步推理計算
?
用 OpenVINO C++ API 實現(xiàn)同步推理計算,主要有七步:
1.實例化 Core 對象:ov::Core core;
2.編譯并載入模型:core.compile_model();
3.創(chuàng)建推理請求:infer_request = compiled_model.create_infer_request();
4.讀取圖像數(shù)據(jù)并完成預(yù)處理;
5.將輸入數(shù)據(jù)傳入模型:infer_request.set_input_tensor(input_tensor);
6.啟動推理計算:infer_request.infer();
7.獲得推理結(jié)果:output0?= infer_request.get_output_tensor(0);?
output1?= infer_request.get_output_tensor(1);
?
范例代碼如下所示:

?
1.3.3?推理結(jié)果后處理
?
實例分割推理程序的后處理是從結(jié)果中拆解出預(yù)測別類(class_id),類別分?jǐn)?shù)(class_score),類別邊界框(box)和類別掩膜(mask),范例代碼如下所示:


?
完整范例參考參見:yolov8_seg_ov_infer.cpp,運行結(jié)果如下圖所示:

?
1.4
結(jié)論
?
OpenVINO?C++ API 簡單清晰,易學(xué)易用。本文用不到100行(不含可視化檢測結(jié)果) C++ 代碼就實現(xiàn)了基于OpenVINO的?YOLOv8-Seg 實例分割模型推理程序,在英特爾獨立顯卡?A770m 上獲得了較好的推理計算性能。
?