赞
踩
我的环境配置:
VS2017
onnxruntime 1.13.1(最好是GPU版本,速度更快)
opencv 4.5.0
这里只是我的开发环境,其他版本也可以(本博客暂时只讲模型推理,不介绍环境配置,如有需求的小伙伴可留下评论)
模型采用yolov8官方提供的yolov8n-seg.pt模型,利用官方工具将其转换为yolov8n-seg.onnx模型,需要的小伙伴私信我
展示下推理效果,话不多说,先看图
本代码实测可用!
#include "onnxruntime_cxx_api.h" #include "cpu_provider_factory.h" #include <opencv2/opencv.hpp> #include <fstream> std::string labels_txt_file = "classes.txt"; std::vector<std::string> readClassNames(); float sigmoid_function(float a) { float b = 1. / (1. + exp(-a)); return b; } std::vector<std::string> readClassNames() { std::vector<std::string> classNames; std::ifstream fp(labels_txt_file); if (!fp.is_open()) { printf("could not open file...\n"); exit(-1); } std::string name; while (!fp.eof()) { std::getline(fp, name); if (name.length()) classNames.push_back(name); } fp.close(); return classNames; } int main(int argc, char** argv) { cv::RNG rng; //生成随机数 float x_factor = 0.0; float y_factor = 0.0; float sx = 160.0f / 640.0f; float sy = 160.0f / 640.0f; std::vector<std::string> labels = readClassNames(); cv::Mat frame = cv::imread("img.png"); // 创建InferSession, 查询支持硬件设备 // GPU Mode, 0 - gpu device id std::string onnxpath = "yolov8n-seg.onnx"; std::wstring modelPath = std::wstring(onnxpath.begin(), onnxpath.end()); Ort::SessionOptions session_options; Ort::Env env = Ort::Env(ORT_LOGGING_LEVEL_ERROR, "yolov8seg-onnx"); session_options.SetGraphOptimizationLevel(ORT_ENABLE_BASIC); std::cout << "onnxruntime inference try to use GPU Device" << std::endl; OrtSessionOptionsAppendExecutionProvider_CUDA(session_options, 0);//GPU版本 // OrtSessionOptionsAppendExecutionProvider_CPU(session_options, 0);//CPU版本 Ort::Session session_(env, modelPath.c_str(), session_options); // get input and output info int input_nodes_num = session_.GetInputCount(); int output_nodes_num = session_.GetOutputCount(); std::vector<std::string> input_node_names; std::vector<std::string> output_node_names; Ort::AllocatorWithDefaultOptions allocator; int input_h = 0; int input_w = 0; // query input data format for (int i = 0; i < input_nodes_num; i++) { auto input_name = session_.GetInputNameAllocated(i, allocator); input_node_names.push_back(input_name.get()); auto inputShapeInfo = session_.GetInputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape(); int ch = inputShapeInfo[1]; input_h = inputShapeInfo[2]; input_w = inputShapeInfo[3]; std::cout << "input format: " << ch << "x" << input_h << "x" << input_w << std::endl; } // query output data format, 25200x85 int num = 116; int nc = 8400; for (int i = 0; i < output_nodes_num; i++) { auto output_name = session_.GetOutputNameAllocated(i, allocator); output_node_names.push_back(output_name.get()); auto outShapeInfo = session_.GetOutputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape(); std::cout << "output format: " << num << "x" << nc << std::endl; } // 图象预处理 - 格式化操作 int64 start = cv::getTickCount(); int w = frame.cols; int h = frame.rows; int _max = std::max(h, w); cv::Mat image = cv::Mat::zeros(cv::Size(_max, _max), CV_8UC3); cv::Rect roi(0, 0, w, h); frame.copyTo(image(roi)); x_factor = image.cols / static_cast<float>(640); y_factor = image.rows / static_cast<float>(640); cv::Mat blob = cv::dnn::blobFromImage(image, 1.0 / 255.0, cv::Size(input_w, input_h), cv::Scalar(0, 0, 0), true, false); size_t tpixels = input_h * input_w * 3; std::array<int64_t, 4> input_shape_info{ 1, 3, input_h, input_w }; // set input data and inference auto allocator_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU); Ort::Value input_tensor_ = Ort::Value::CreateTensor<float>(allocator_info, blob.ptr<float>(), tpixels, input_shape_info.data(), input_shape_info.size()); const std::array<const char*, 1> inputNames = { input_node_names[0].c_str() }; const std::array<const char*, 2> outNames = { output_node_names[0].c_str(), output_node_names[1].c_str() }; std::vector<Ort::Value> ort_outputs; try { ort_outputs = session_.Run(Ort::RunOptions{ nullptr }, inputNames.data(), &input_tensor_, 1, outNames.data(), outNames.size()); } catch (std::exception e) { std::cout << e.what() << std::endl; } // 116x8400, 1x32x160x160 const float* pdata = ort_outputs[0].GetTensorMutableData<float>(); const float* mdata = ort_outputs[1].GetTensorMutableData<float>(); // 后处理, 1x116x8400, 84 - box, 80- min/max, 32 feature std::vector<cv::Rect> boxes; std::vector<int> classIds; std::vector<float> confidences; std::vector<cv::Mat> masks; cv::Mat dout(num, nc, CV_32F, (float*)pdata); cv::Mat det_output = dout.t(); // 116x8400 => 8400x116 cv::Mat mask1(32, 25600, CV_32F, (float*)mdata); for (int i = 0; i < det_output.rows; i++) { cv::Mat classes_scores = det_output.row(i).colRange(4, num - 32); cv::Point classIdPoint; double score; minMaxLoc(classes_scores, 0, &score, 0, &classIdPoint); if (score > 0.25) { cv::Mat mask2 = det_output.row(i).colRange(num - 32, num); float cx = det_output.at<float>(i, 0); float cy = det_output.at<float>(i, 1); float ow = det_output.at<float>(i, 2); float oh = det_output.at<float>(i, 3); int x = static_cast<int>((cx - 0.5 * ow) * x_factor); int y = static_cast<int>((cy - 0.5 * oh) * y_factor); int width = static_cast<int>(ow * x_factor); int height = static_cast<int>(oh * y_factor); cv::Rect box; box.x = x; box.y = y; box.width = width; box.height = height; boxes.push_back(box); classIds.push_back(classIdPoint.x); confidences.push_back(score); masks.push_back(mask2); } } std::vector<int> indexes; cv::dnn::NMSBoxes(boxes, confidences, 0.25, 0.45, indexes); cv::Mat rgb_mask = cv::Mat::zeros(frame.size(), frame.type()); // 显示 for (size_t i = 0; i < indexes.size(); i++) { int idx = indexes[i]; int cid = classIds[idx]; cv::Rect box = boxes[idx]; int x1 = std::max(0, box.x); int y1 = std::max(0, box.y); int x2 = std::max(0, box.br().x); int y2 = std::max(0, box.br().y); cv::Mat m2 = masks[idx]; cv::Mat m = m2 * mask1; for (int col = 0; col < m.cols; col++) { m.at<float>(0, col) = sigmoid_function(m.at<float>(0, col)); } cv::Mat m1 = m.reshape(1, 160); int mx1 = std::max(0, int((x1 * sx) / x_factor)); int mx2 = std::max(0, int((x2 * sx) / x_factor)); int my1 = std::max(0, int((y1 * sy) / y_factor)); int my2 = std::max(0, int((y2 * sy) / y_factor)); if (mx2 >= m1.cols) { mx2 = m1.cols - 1; } if (my2 >= m1.rows) { my2 = m1.rows - 1; } cv::Mat mask_roi = m1(cv::Range(my1, my2), cv::Range(mx1, mx2)); cv::Mat rm, det_mask; cv::resize(mask_roi, rm, cv::Size(x2 - x1, y2 - y1)); for (int r = 0; r < rm.rows; r++) { for (int c = 0; c < rm.cols; c++) { float pv = rm.at<float>(r, c); if (pv > 0.5) { rm.at<float>(r, c) = 1.0; } else { rm.at<float>(r, c) = 0.0; } } } rm = rm * rng.uniform(0, 255); rm.convertTo(det_mask, CV_8UC1); if ((y1 + det_mask.rows) >= frame.rows) { y2 = frame.rows - 1; } if ((x1 + det_mask.cols) >= frame.cols) { x2 = frame.cols - 1; } // std::cout << "x1: " << x1 << " x2:" << x2 << " y1: " << y1 << " y2: " << y2 << std::endl; cv::Mat mask = cv::Mat::zeros(cv::Size(frame.cols, frame.rows), CV_8UC1); det_mask(cv::Range(0, y2 - y1), cv::Range(0, x2 - x1)).copyTo(mask(cv::Range(y1, y2), cv::Range(x1, x2))); add(rgb_mask, cv::Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), rgb_mask, mask); cv::rectangle(frame, boxes[idx], cv::Scalar(0, 0, 255), 2, 8, 0); putText(frame, labels[cid].c_str(), boxes[idx].tl(), cv::FONT_HERSHEY_PLAIN, 1.0, cv::Scalar(255, 0, 0), 1, 8); } float t = (cv::getTickCount() - start) / static_cast<float>(cv::getTickFrequency()); putText(frame, cv::format("FPS: %.2f", 1.0 / t), cv::Point(20, 40), cv::FONT_HERSHEY_PLAIN, 2.0, cv::Scalar(255, 0, 0), 2, 8); cv::Mat result; cv::addWeighted(frame, 0.5, rgb_mask, 0.5, 0, result); result.copyTo(frame); cv::Mat ori = frame.clone(); cv::namedWindow("ori", 0); cv::imshow("ori", ori); cv::namedWindow("seg", 0); cv::imshow("seg", frame); cv::waitKey(0); session_options.release(); session_.release(); return 0; }
如果没有 classes.txt 文件,需要自己新建一个,复制下边文本
person bicycle car motorbike aeroplane bus train truck boat traffic light fire hydrant stop sign parking meter bench bird cat dog horse sheep cow elephant bear zebra giraffe backpack umbrella handbag tie suitcase frisbee skis snowboard sports ball kite baseball bat baseball glove skateboard surfboard tennis racket bottle wine glass cup fork knife spoon bowl banana apple sandwich orange broccoli carrot hot dog pizza donut cake chair sofa pottedplant bed diningtable toilet tvmonitor laptop mouse remote keyboard cell phone microwave oven toaster sink refrigerator book clock vase scissors teddy bear hair drier toothbrush
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。