利用C++ onnx runtime预测训练的.pt模型

news/2025/2/19 22:28:18/

一:工具:

查看模型工具netron

1.https://github.com/lutzroeder/netron/releases

可以查看训练好的模型的输入结构

下载安装好netron ,然后注册右键菜单,弄一个xx.reg ,运行一下

Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\Directory\Background\shell\OpenNetron]
@="Open with Netron"
"Icon"="C:\\Users\\Administrator\\AppData\\Local\\Programs\\netron\\Netron.exe"[HKEY_CLASSES_ROOT\Directory\Background\shell\OpenNetron\command]
@="\"C:\\Users\\Administrator\\AppData\\Local\\Programs\\netron\\Netron.exe\""

 pip install ultralytics 安装 ultralytics库

1.先写 py2onnx.py代码

from ultralytics import YOLOmodel = YOLO("best.pt")
success = model.export(format="onnx", opset=11, simplify=True)  # export the model to onnx format
assert success

二:onnxruntime x86库(我是易语言,所以用x86,首先得用vs编一个32位的dll)

https://github.com/microsoft/onnxruntime/releases?page=2

直接用大哥的代码:一个脚本搞定yolov5和yolov8在c++环境中加载onnx模型格式仅调用opencv部署_c++ 下 图片测试 opencv 部署yolo5 onnx 模型-CSDN博客

 然后再稍微改一下类别,我的模型只有一个输入和一个输出

下面是代码

#include <fstream>
#include <vector>
#include <string>
#include <random>// OpenCV / DNN / Inference
#include <opencv2/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>using namespace cv;
using namespace std;struct Detection
{int class_id{ 0 };std::string className{};float confidence{ 0.0 };cv::Scalar color{};cv::Rect box{};
};class Inference
{
public:Inference(const std::string& onnxModelPath, const cv::Size& modelInputShape, const std::string& classesTxtFile, const bool& runWithCuda){modelPath = onnxModelPath;modelShape = modelInputShape;classesPath = classesTxtFile;cudaEnabled = runWithCuda;loadOnnxNetwork();}
private:std::string modelPath;std::string classesPath;bool cudaEnabled;cv::Size2f modelShape;cv::dnn::Net net;bool letterBoxForSquare = true;std::vector<std::string> classes{ "goal"};float modelConfidenceThreshold{ 0.25 };float modelScoreThreshold{ 0.45 };float modelNMSThreshold{ 0.50 };private:void loadOnnxNetwork(){net = cv::dnn::readNetFromONNX(modelPath);if (cudaEnabled){std::cout << "\nRunning on CUDA" << std::endl;net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);}else{std::cout << "\nRunning on CPU" << std::endl;net.setPreferableBackend(cv::dnn::DNN_BACKEND_OPENCV);net.setPreferableTarget(cv::dnn::DNN_TARGET_CPU);}}cv::Mat formatToSquare(const cv::Mat& source){int col = source.cols;int row = source.rows;int _max = MAX(col, row);cv::Mat result = cv::Mat::zeros(_max, _max, CV_8UC3);source.copyTo(result(cv::Rect(0, 0, col, row)));return result;}
public:std::vector<Detection> runInference(const cv::Mat& input){cv::Mat modelInput = input;if (letterBoxForSquare && modelShape.width == modelShape.height)modelInput = formatToSquare(modelInput);cv::Mat blob;cv::dnn::blobFromImage(modelInput, blob, 1.0 / 255.0, modelShape, cv::Scalar(), true, false);net.setInput(blob);std::vector<cv::Mat> outputs;net.forward(outputs, net.getUnconnectedOutLayersNames());int rows = outputs[0].size[1];int dimensions = outputs[0].size[2];bool yolov8 = false;// yolov5 has an output of shape (batchSize, 25200, 85) (Num classes + box[x,y,w,h] + confidence[c])// yolov8 has an output of shape (batchSize, 84,  8400) (Num classes + box[x,y,w,h])if (dimensions > rows) // Check if the shape[2] is more than shape[1] (yolov8){yolov8 = true;rows = outputs[0].size[2];dimensions = outputs[0].size[1];outputs[0] = outputs[0].reshape(1, dimensions);cv::transpose(outputs[0], outputs[0]);}float* data = (float*)outputs[0].data;float x_factor = modelInput.cols / modelShape.width;float y_factor = modelInput.rows / modelShape.height;std::vector<int> class_ids;std::vector<float> confidences;std::vector<cv::Rect> boxes;for (int i = 0; i < rows; ++i){if (yolov8){float* classes_scores = data + 4;cv::Mat scores(1, classes.size(), CV_32FC1, classes_scores);cv::Point class_id;double maxClassScore;minMaxLoc(scores, 0, &maxClassScore, 0, &class_id);if (maxClassScore > modelScoreThreshold){confidences.push_back(maxClassScore);class_ids.push_back(class_id.x);float x = data[0];float y = data[1];float w = data[2];float h = data[3];int left = int((x - 0.5 * w) * x_factor);int top = int((y - 0.5 * h) * y_factor);int width = int(w * x_factor);int height = int(h * y_factor);boxes.push_back(cv::Rect(left, top, width, height));}}else // yolov5{float confidence = data[4];if (confidence >= modelConfidenceThreshold){float* classes_scores = data + 5;cv::Mat scores(1, classes.size(), CV_32FC1, classes_scores);cv::Point class_id;double max_class_score;minMaxLoc(scores, 0, &max_class_score, 0, &class_id);if (max_class_score > modelScoreThreshold){confidences.push_back(confidence);class_ids.push_back(class_id.x);float x = data[0];float y = data[1];float w = data[2];float h = data[3];int left = int((x - 0.5 * w) * x_factor);int top = int((y - 0.5 * h) * y_factor);int width = int(w * x_factor);int height = int(h * y_factor);boxes.push_back(cv::Rect(left, top, width, height));}}}data += dimensions;}std::vector<int> nms_result;cv::dnn::NMSBoxes(boxes, confidences, modelScoreThreshold, modelNMSThreshold, nms_result);std::vector<Detection> detections{};for (unsigned long i = 0; i < nms_result.size(); ++i){int idx = nms_result[i];Detection result;result.class_id = class_ids[idx];result.confidence = confidences[idx];std::random_device rd;std::mt19937 gen(rd());std::uniform_int_distribution<int> dis(100, 255);result.color = cv::Scalar(dis(gen),dis(gen),dis(gen));result.className = classes[result.class_id];result.box = boxes[idx];detections.push_back(result);}return detections;}void loadClassesFromFile(){std::ifstream inputFile(classesPath);if (inputFile.is_open()){std::string classLine;while (std::getline(inputFile, classLine))classes.push_back(classLine);inputFile.close();}}
};int main(int argc, char** argv)
{std::string projectBasePath = "D:\\C_++\\yolov8_onnx";bool runOnGPU = false;Inference inf(projectBasePath + "/best.onnx", cv::Size(640, 640), "classes.txt", runOnGPU);std::vector<std::string> imageNames;imageNames.push_back(projectBasePath + "/image.png");for (int i = 0; i < imageNames.size(); ++i){cv::Mat frame = cv::imread(imageNames[i]);// Inference starts here...std::vector<Detection> output = inf.runInference(frame);int detections = output.size();std::cout << "Number of detections:" << detections << std::endl;for (int i = 0; i < detections; ++i){Detection detection = output[i];cv::Rect box = detection.box;cv::Scalar color = detection.color;// Detection boxcv::rectangle(frame, box, color, 2);// Detection box textstd::string classString = detection.className + ' ' + std::to_string(detection.confidence).substr(0, 4);cv::Size textSize = cv::getTextSize(classString, cv::FONT_HERSHEY_DUPLEX, 1, 2, 0);cv::Rect textBox(box.x, box.y - 40, textSize.width + 10, textSize.height + 20);cv::rectangle(frame, textBox, color, cv::FILLED);cv::putText(frame, classString, cv::Point(box.x + 5, box.y - 10), cv::FONT_HERSHEY_DUPLEX, 1, cv::Scalar(0, 0, 0), 2, 0);}// Inference ends here...// This is only for preview purposesfloat scale = 0.8;cv::resize(frame, frame, cv::Size(frame.cols * scale, frame.rows * scale));cv::imshow("Inference", frame);cv::waitKey(-1);}std::cout << "-----------------------------" << std::endl;std::cout << "dd" << std::endl;return 0;
}

最后移植到易上调用


http://www.ppmy.cn/news/1456767.html

相关文章

C++之nothrow

nothrow 是 C 中的一个关键字&#xff0c;用于改变 new 操作符的行为&#xff0c;使其在内存分配失败时不抛出异常&#xff0c;而是安静地返回一个空指针&#xff08;nullptr&#xff09;。这对于那些不希望或不能处理异常的代码片段特别有用。要使用 nothrow&#xff0c;你需要…

Servlet(一些实战小示例)

文章目录 一、实操注意点1.1 代码修改重启问题1.2 Smart Tomcat的日志1.3 如何处理错误 一. 抓自己的包二、构造一个重定向的响应&#xff0c;让页面重定向到百度主页三、让服务器返回一个html数据四、表白墙4.1 约定前后端数据4.2 前端代码4.3 后端代码4.4 保存在数据库的版本…

Java常用API之LinkedList类解读

写在开头&#xff1a;本文用于作者学习我将官方文档中LinkedList 1.6版本中类中绝大部分API全测了一遍并打印了结果&#xff0c;日拱一卒&#xff0c;常看常新。 自己补充了一些对该数据结构的理解&#xff0c;如有不对的地方&#xff0c;请各位指正&#xff0c;谢谢。 首先&…

【蓝桥杯备赛国赛】5-5

文章目录 求阶乘双子数 求阶乘 求阶乘 分析k的范围&#xff0c;10的18次方。这个数字很大 想要末尾有0的存在必须要2和5&#xff0c;但是通过分析2的数目应该是远远多于5的&#xff0c;所以只要5的数目够多即可。所以for循环的层次也是10的九次方以上&#xff0c;必然会超时&…

Java jar程序CPU异常高问题排查

文章目录 一、命令排查二、脚本排查方法一 curl脚本文件直接用bash运行方法二 下载脚本文件并运行一、命令排查 1.使用 top 定位到占用CPU高的进程PID top2.获取进程PID信息 ps aux | grep [PID]3.找到占用CPU高的线程 ps -mp [PID

python数据分析-老龄化分析

一、研究背景介绍和分析安排 中国作为世界上人口最多的国家&#xff0c;其人口结构的变化对国内外经济都有着深远的影响。近年来&#xff0c;中国的老龄人口比例不断上升&#xff0c;这一变化引起了广泛的社会关注和政策讨论。老龄化带来的挑战包括劳动力市场紧缩、养老金负担…

spring高级篇(五)

1、参数解析器 前篇提到过&#xff0c;参数解析器是HandlerAdapters中的组件&#xff0c;用于解析controller层方法中加了注解的参数信息。 有一个controller&#xff0c;方法的参数加上了各种注解&#xff1a; public class Controller {public void test(RequestParam("…

MySQL学习笔记9——触发器和权限管理

触发器和权限管理 一、触发器1、如何操作触发器2、触发器的优缺点 二、权限管理1、角色的作用2、角色的操作3、用户的操作 一、触发器 当商品信息和库存信息分别存放在两个不同的数据表中时&#xff0c;可以创建一个触发器&#xff0c; 让商品信息数据的插入操作自动触发库存数…