文章作者:英特爾邊緣計(jì)算創(chuàng)新大使戰(zhàn)鵬州
01. 簡(jiǎn)介
本文章將介紹使用 OpenVINO2023.0 C++ API 開(kāi)發(fā)YOLOv8-Seg 實(shí)例分割(Instance Segmentation)模型的 AI 推理程序。本文 C++ 范例程序的開(kāi)發(fā)環(huán)境是 Windows + Visual Studio Community 2022。
請(qǐng)讀者先配置基于 Visual Studio 的 OpenVINO C++ 開(kāi)發(fā)環(huán)境。
請(qǐng)克隆本文的代碼倉(cāng):
git clone
https://gitee.com/ppov-nuc/yolov8_openvino_cpp.git
02. 導(dǎo)出YOLOv8-Seg OpenVINO IR 模型
YOLOv8 是 Ultralytics 公司基于 YOLO 框架,發(fā)布的一款面向物體檢測(cè)與跟蹤、實(shí)例分割、圖像分類(lèi)和姿態(tài)估計(jì)任務(wù)的 SOTA 模型工具套件。
首先用命令:
pip install -r requirements.txt
安裝 ultralytics 和 openvino-dev 。
然后使用命令:
yolo export model=yolov8n-seg.pt format=openvino half=True
向右滑動(dòng)查看完整代碼
導(dǎo)出 FP16 精度的 OpenVINO IR 模型,如下圖所示。
接著使用命令:
benchmark_app -m yolov8n-seg.xml -d GPU.1
向右滑動(dòng)查看完整代碼
獲得 yolov8n-seg.xml 模型在 A770m 獨(dú)立顯卡上的異步推理計(jì)算性能,如下圖所示。
03.使用 OpenVINO C++ API
編寫(xiě) YOLOv8-Seg 實(shí)例分割模型推理程序
使用 OpenVINO C++ API 編寫(xiě) YOLOv8-Seg 實(shí)例分割模型推理程序主要有5個(gè)典型步驟:
1采集圖像&圖像解碼
2圖像數(shù)據(jù)預(yù)處理
3AI 推理計(jì)算(基于 OpenVINO C++ API )
4對(duì)推理結(jié)果進(jìn)行后處理
5將處理后的結(jié)果可視化
YOLOv8-Seg 實(shí)例分割模型推理程序的圖像數(shù)據(jù)預(yù)處理和AI推理計(jì)算的實(shí)現(xiàn)方式跟 YOLOv8 目標(biāo)檢測(cè)模型推理程序的實(shí)現(xiàn)方式幾乎一模一樣,可以直接復(fù)用。
3.1圖像數(shù)據(jù)預(yù)處理
使用 Netron 打開(kāi) yolov8n-seg.onnx ,如下圖所示,可以看到:
輸入節(jié)點(diǎn)的名字:“ images ”;數(shù)據(jù):float32[1,3,640,640]
輸出節(jié)點(diǎn)1的名字:“ output0 ”;數(shù)據(jù):float32[1,116,8400]。其中116的前84個(gè)字段跟 YOLOv8 目標(biāo)檢測(cè)模型輸出定義完全一致,即cx,cy,w,h 和80類(lèi)的分?jǐn)?shù);后32個(gè)字段為掩膜置信度,用于計(jì)算掩膜數(shù)據(jù)。
輸出節(jié)點(diǎn)2的名字:“ output1 ”;數(shù)據(jù):float32[1,32,160,160]。output0 后32個(gè)字段與 output1 的數(shù)據(jù)做矩陣乘法后得到的結(jié)果,即為對(duì)應(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ù)放縮為正方形帶來(lái)的圖像失真問(wèn)題,在圖像放縮前,采用 letterbox 算法先保持圖像的長(zhǎng)寬比,如下圖所示,然后再使用 cv::blobFromImage 函數(shù)對(duì)圖像進(jìn)行放縮。
圖像數(shù)據(jù)預(yù)處理的范例程序如下所示:
Mat letterbox(const Mat& source) { int col = source.cols; int row = source.rows; int _max = MAX(col, row); Mat result = Mat::zeros(_max, _max, CV_8UC3); source.copyTo(result(Rect(0, 0, col, row))); return result; } Mat img = cv::imread("bus.jpg"); Mat letterbox_img = letterbox(img); Mat blob = blobFromImage(letterbox_img, 1.0/255.0, Size(640,640), Scalar(), true);
向右滑動(dòng)查看完整代碼
3.2AI同步推理計(jì)算
用 OpenVINO C++ API 實(shí)現(xiàn)同步推理計(jì)算,主要有七步:
1實(shí)例化 Core 對(duì)象:ov::Core core;
2編譯并載入模型:core.compile_model();
3創(chuàng)建推理請(qǐng)求:infer_request = compiled_model.create_infer_request();
4讀取圖像數(shù)據(jù)并完成預(yù)處理;
5將輸入數(shù)據(jù)傳入模型:infer_request.set_input_tensor(input_tensor);
6啟動(dòng)推理計(jì)算:infer_request.infer();
7獲得推理結(jié)果:output0= infer_request.get_output_tensor(0) ;
output1= infer_request.get_output_tensor(1) ;
范例代碼如下所示:
// -------- Step 1. Initialize OpenVINO Runtime Core -------- ov::Core core; // -------- Step 2. Compile the Model -------- auto compiled_model = core.compile_model("yolov8n-seg.xml", "CPU"); // -------- Step 3. Create an Inference Request -------- ov::InferRequest infer_request = compiled_model.create_infer_request(); // -------- Step 4.Read a picture file and do the preprocess -------- Mat img = cv::imread("bus.jpg"); // Preprocess the image Mat letterbox_img = letterbox(img); float scale = letterbox_img.size[0] / 640.0; Mat blob = blobFromImage(letterbox_img, 1.0 / 255.0, Size(640, 640), Scalar(), true); // -------- Step 5. Feed the blob into the input node of the Model ------- // Get input port for model with one input auto input_port = compiled_model.input(); // Create tensor from external memory ov::Tensor input_tensor(input_port.get_element_type(), input_port.get_shape(), blob.ptr(0)); // Set input tensor for model with one input infer_request.set_input_tensor(input_tensor); // -------- Step 6. Start inference -------- infer_request.infer(); // -------- Step 7. Get the inference result -------- auto output0 = infer_request.get_output_tensor(0); //output0 auto output1 = infer_request.get_output_tensor(1); //otuput1
向右滑動(dòng)查看完整代碼
3.3推理結(jié)果后處理
實(shí)例分割推理程序的后處理是從結(jié)果中拆解出預(yù)測(cè)別類(lèi)(class_id),類(lèi)別分?jǐn)?shù)(class_score),類(lèi)別邊界框(box)和類(lèi)別掩膜(mask),范例代碼如下所示:
// -------- Step 8. Postprocess the result -------- Mat output_buffer(output0_shape[1], output0_shape[2], CV_32F, output0.data()); Mat proto(32, 25600, CV_32F, output1.data ()); //[32,25600] transpose(output_buffer, output_buffer); //[8400,116] float score_threshold = 0.25; float nms_threshold = 0.5; std::vector class_ids; std::vector class_scores; std::vector boxes; std::vector mask_confs; // Figure out the bbox, class_id and class_score for (int i = 0; i < output_buffer.rows; i++) { ? ? ? ?Mat classes_scores = output_buffer.row(i).colRange(4, 84); ? ? ? ?Point class_id; ? ? ? ?double maxClassScore; ? ? ? ?minMaxLoc(classes_scores, 0, &maxClassScore, 0, &class_id); ? ? ? ?if (maxClassScore > score_threshold) { class_scores.push_back(maxClassScore); class_ids.push_back(class_id.x); float cx = output_buffer.at (i, 0); float cy = output_buffer.at (i, 1); float w = output_buffer.at (i, 2); float h = output_buffer.at (i, 3); int left = int((cx - 0.5 * w) * scale); int top = int((cy - 0.5 * h) * scale); int width = int(w * scale); int height = int(h * scale); cv::Mat mask_conf = output_buffer.row(i).colRange(84, 116); mask_confs.push_back(mask_conf); boxes.push_back(Rect(left, top, width, height)); } } //NMS std::vector indices; NMSBoxes(boxes, class_scores, score_threshold, nms_threshold, indices);
向右滑動(dòng)查看完整代碼
完整范例參考參見(jiàn):yolov8_seg_ov_infer.cpp ,運(yùn)行結(jié)果如下圖所示:
04 結(jié)論
OpenVINOC++ API 簡(jiǎn)單清晰,易學(xué)易用。本文用不到100行(不含可視化檢測(cè)結(jié)果) C++ 代碼就實(shí)現(xiàn)了基于 OpenVINO 的 YOLOv8-Seg 實(shí)例分割模型推理程序,在英特爾 獨(dú)立顯卡 A770m 上獲得了較好的推理計(jì)算性能。
審核編輯:湯梓紅
-
英特爾
+關(guān)注
關(guān)注
61文章
9949瀏覽量
171692 -
WINDOWS
+關(guān)注
關(guān)注
3文章
3541瀏覽量
88619 -
API
+關(guān)注
關(guān)注
2文章
1499瀏覽量
61959 -
程序
+關(guān)注
關(guān)注
117文章
3785瀏覽量
81001 -
C++
+關(guān)注
關(guān)注
22文章
2108瀏覽量
73618
原文標(biāo)題:用OpenVINO? C++ API編寫(xiě)YOLOv8-Seg實(shí)例分割模型推理程序 | 開(kāi)發(fā)者實(shí)戰(zhàn)
文章出處:【微信號(hào):英特爾物聯(lián)網(wǎng),微信公眾號(hào):英特爾物聯(lián)網(wǎng)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論