TRT4-trt-integrate - 3 使用onnxruntime进行onnx的模型推理过程
前言:
- onnx是microsoft开发的一个中间格式,而onnxruntime简称ort是microsoft为onnx开发的推理引擎。
- 允许使用onnx作为输入进行直接推理得到结果。
py接口的推理过程:
main函数:
if __name__ == "__main__":session = onnxruntime.InferenceSession("workspace/yolov5s.onnx", providers=["CPUExecutionProvider"])#建立一个InferenceSession,塞进去的是onnx的路径实际运算image = cv2.imread("workspace/car.jpg")image_input, M, IM = preprocess(image)pred = session.run(["output"], {"images": image_input})[0]boxes = post_process(pred, IM)for obj in boxes:left, top, right, bottom = map(int, obj[:4])confidence = obj[4]label = int(obj[6])cv2.rectangle(image, (left, top), (right, bottom), (0, 255, 0), 2)cv2.putText(image, f"{label}: {confidence:.2f}", (left, top+20), 0, 1, (0, 0, 255), 2, 16)cv2.imwrite("workspace/python-ort.jpg", image)
session = onnxruntime.InferenceSession("workspace/yolov5s.onnx", providers=["CPUExecutionProvider"])
建立一个InferenceSession,塞进去的是onnx的路径,实际运算的后端选用的是CPU
也可以选用cuda等等
image = cv2.imread("workspace/car.jpg")image_input, M, IM = preprocess(image)
之后就是预处理
pred = session.run(["output"], {"images": image_input})[0]boxes = post_process(pred, IM)
session.run就是运行的inference过程
输入第一个是output的name,决定了哪几个节点作为输出,就将这个名字传递给他
第二个是input的dict,这个意思就是如果有好多个输入,那应该是将名字与输入进行一一对应,比如"input1 ":input1 , "input2":input2....
那么在这里output就是一个输出的list,然后我们取第0项
就是这个样子。
预处理:
def preprocess(image, input_w=640, input_h=640):scale = min(input_h / image.shape[0], input_w / image.shape[1])ox = (-scale * image.shape[1] + input_w + scale - 1) * 0.5oy = (-scale * image.shape[0] + input_h + scale - 1) * 0.5M = np.array([[scale, 0, ox],[0, scale, oy]], dtype=np.float32)IM = cv2.invertAffineTransform(M)image_prep = cv2.warpAffine(image, M, (input_w, input_h), flags=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT, borderValue=(114, 114, 114))image_prep = (image_prep[..., ::-1] / 255.0).astype(np.float32)image_prep = image_prep.transpose(2, 0, 1)[None]return image_prep, M, IM
后处理:
def nms(boxes, threshold=0.5):keep = []remove_flags = [False] * len(boxes)for i in range(len(boxes)):if remove_flags[i]:continueib = boxes[i]keep.append(ib)for j in range(len(boxes)):if remove_flags[j]:continuejb = boxes[j]# class mismatch or image_id mismatchif ib[6] != jb[6] or ib[5] != jb[5]:continuecleft, ctop = max(ib[:2], jb[:2])#例子:#将 ib 的前两个元素 [2, 3] 与 jb 的前两个元素 [4, 1] 进行比较,并取其中较大的值。所以结果是 [4, 3]。cright, cbottom = min(ib[2:4], jb[2:4])cross = max(0, cright - cleft) * max(0, cbottom - ctop)union = max(0, ib[2] - ib[0]) * max(0, ib[3] - ib[1]) + max(0, jb[2] - jb[0]) * max(0, jb[3] - jb[1]) - crossiou = cross / unionif iou >= threshold:remove_flags[j] = Truereturn keepdef post_process(pred, IM, threshold=0.25):# b, n, 85boxes = []for image_id, box_id in zip(*np.where(pred[..., 4] >= threshold)):item = pred[image_id, box_id]cx, cy, w, h, objness = item[:5]label = item[5:].argmax()confidence = item[5 + label] * objnessif confidence < threshold:continueboxes.append([cx - w * 0.5, cy - h * 0.5, cx + w * 0.5, cy + h * 0.5, confidence, image_id, label])boxes = np.array(boxes)lr = boxes[:, [0, 2]]tb = boxes[:, [1, 3]]boxes[:, [0, 2]] = lr * IM[0, 0] + IM[0, 2]boxes[:, [1, 3]] = tb * IM[1, 1] + IM[1, 2]# left, top, right, bottom, confidence, image_id, labelboxes = sorted(boxes.tolist(), key=lambda x:x[4], reverse=True)return nms(boxes)
我们可以发现,真正的onnxruntime只有两行,一个onnxruntime.InferenceSession,一个run就结束了。其余的都是和之前一样的,这是非常好用便捷的,所以如果有模型需要作测试,是非常推荐用onnxruntime的
CPP接口推理过程:
Inference:
在main函数中只有一个inference
int main(){inference();return 0; }
所以我们直接来到inference的解读中
auto engine_data = load_file("yolov5s.onnx"); //读onnx文件Ort::Env env(ORT_LOGGING_LEVEL_INFO, "onnx"); //设置打印的日志级别 Ort::SessionOptions session_options; //定义sessionoptions 类似于python中的 session = onnxruntime.InferenceSession("workspace/yolov5s.onnx", providers=["CPUExecutionProvider"])auto mem = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault); //设置MemoryInfosession_options.SetIntraOpNumThreads(1);session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED); //启动一些扩展
Ort::Session session(env, "yolov5s.onnx", session_options);//创建session,将选项传进去auto output_dims = session.GetOutputTypeInfo(0).GetTensorTypeAndShapeInfo().GetShape();//获取output的shapeconst char *input_names[] = {"images"}, *output_names[] = {"output"};
int input_batch = 1;int input_channel = 3;int input_height = 640;int input_width = 640;int64_t input_shape[] = {input_batch, input_channel, input_height, input_width};int input_numel = input_batch * input_channel * input_height * input_width;float* input_data_host = new float[input_numel];auto input_tensor = Ort::Value::CreateTensor(mem, input_data_host, input_numel, input_shape, 4);//创建一个Tensor,引用input_data_host中的数据
预处理:
///// letter boxauto image = cv::imread("car.jpg");float scale_x = input_width / (float)image.cols;float scale_y = input_height / (float)image.rows;float scale = std::min(scale_x, scale_y);float i2d[6], d2i[6];i2d[0] = scale; i2d[1] = 0; i2d[2] = (-scale * image.cols + input_width + scale - 1) * 0.5;i2d[3] = 0; i2d[4] = scale; i2d[5] = (-scale * image.rows + input_height + scale - 1) * 0.5;cv::Mat m2x3_i2d(2, 3, CV_32F, i2d);cv::Mat m2x3_d2i(2, 3, CV_32F, d2i);cv::invertAffineTransform(m2x3_i2d, m2x3_d2i);cv::Mat input_image(input_height, input_width, CV_8UC3);cv::warpAffine(image, input_image, m2x3_i2d, input_image.size(), cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar::all(114));cv::imwrite("input-image.jpg", input_image);int image_area = input_image.cols * input_image.rows;unsigned char* pimage = input_image.data;float* phost_b = input_data_host + image_area * 0;float* phost_g = input_data_host + image_area * 1;float* phost_r = input_data_host + image_area * 2;for(int i = 0; i < image_area; ++i, pimage += 3){// 注意这里的顺序rgb调换了*phost_r++ = pimage[0] / 255.0f;*phost_g++ = pimage[1] / 255.0f;*phost_b++ = pimage[2] / 255.0f;}///
制作输出矩阵并运行:
// 3x3输入,对应3x3输出int output_numbox = output_dims[1];int output_numprob = output_dims[2];int num_classes = output_numprob - 5;int output_numel = input_batch * output_numbox * output_numprob;float* output_data_host = new float[output_numel];int64_t output_shape[] = {input_batch, output_numbox, output_numprob};auto output_tensor = Ort::Value::CreateTensor(mem, output_data_host, output_numel, output_shape, 3);Ort::RunOptions options;session.Run(options, (const char* const*)input_names, &input_tensor, 1, (const char* const*)output_names, &output_tensor, 1);
//指定输入输出的name,tensor和个数,传入tensor进行推理
后处理:
// decode boxvector<vector<float>> bboxes;float confidence_threshold = 0.25;float nms_threshold = 0.5;for(int i = 0; i < output_numbox; ++i){float* ptr = output_data_host + i * output_numprob;float objness = ptr[4];if(objness < confidence_threshold)continue;float* pclass = ptr + 5;int label = std::max_element(pclass, pclass + num_classes) - pclass;float prob = pclass[label];float confidence = prob * objness;if(confidence < confidence_threshold)continue;float cx = ptr[0];float cy = ptr[1];float width = ptr[2];float height = ptr[3];float left = cx - width * 0.5;float top = cy - height * 0.5;float right = cx + width * 0.5;float bottom = cy + height * 0.5;float image_base_left = d2i[0] * left + d2i[2];float image_base_right = d2i[0] * right + d2i[2];float image_base_top = d2i[0] * top + d2i[5];float image_base_bottom = d2i[0] * bottom + d2i[5];bboxes.push_back({image_base_left, image_base_top, image_base_right, image_base_bottom, (float)label, confidence});}printf("decoded bboxes.size = %d\n", bboxes.size());// nmsstd::sort(bboxes.begin(), bboxes.end(), [](vector<float>& a, vector<float>& b){return a[5] > b[5];});std::vector<bool> remove_flags(bboxes.size());std::vector<vector<float>> box_result;box_result.reserve(bboxes.size());auto iou = [](const vector<float>& a, const vector<float>& b){float cross_left = std::max(a[0], b[0]);float cross_top = std::max(a[1], b[1]);float cross_right = std::min(a[2], b[2]);float cross_bottom = std::min(a[3], b[3]);float cross_area = std::max(0.0f, cross_right - cross_left) * std::max(0.0f, cross_bottom - cross_top);float union_area = std::max(0.0f, a[2] - a[0]) * std::max(0.0f, a[3] - a[1]) + std::max(0.0f, b[2] - b[0]) * std::max(0.0f, b[3] - b[1]) - cross_area;if(cross_area == 0 || union_area == 0) return 0.0f;return cross_area / union_area;};for(int i = 0; i < bboxes.size(); ++i){if(remove_flags[i]) continue;auto& ibox = bboxes[i];box_result.emplace_back(ibox);for(int j = i + 1; j < bboxes.size(); ++j){if(remove_flags[j]) continue;auto& jbox = bboxes[j];if(ibox[4] == jbox[4]){// class matchedif(iou(ibox, jbox) >= nms_threshold)remove_flags[j] = true;}}}printf("box_result.size = %d\n", box_result.size());for(int i = 0; i < box_result.size(); ++i){auto& ibox = box_result[i];float left = ibox[0];float top = ibox[1];float right = ibox[2];float bottom = ibox[3];int class_label = ibox[4];float confidence = ibox[5];cv::Scalar color;tie(color[0], color[1], color[2]) = random_color(class_label);cv::rectangle(image, cv::Point(left, top), cv::Point(right, bottom), color, 3);auto name = cocolabels[class_label];auto caption = cv::format("%s %.2f", name, confidence);int text_width = cv::getTextSize(caption, 0, 1, 2, nullptr).width + 10;cv::rectangle(image, cv::Point(left-3, top-33), cv::Point(left + text_width, top), color, -1);cv::putText(image, caption, cv::Point(left, top-5), 0, 1, cv::Scalar::all(0), 2, 16);}cv::imwrite("image-draw.jpg", image);delete[] input_data_host;delete[] output_data_host;
}
小结:
可以看到,这个与我们之前yolov5后处理没什么太大的区别,关键只在于对于output_tensor和output作关联,input_tensor和input作关联。
相关文章:

TRT4-trt-integrate - 3 使用onnxruntime进行onnx的模型推理过程
前言: onnx是microsoft开发的一个中间格式,而onnxruntime简称ort是microsoft为onnx开发的推理引擎。允许使用onnx作为输入进行直接推理得到结果。 py接口的推理过程: main函数: if __name__ "__main__":session onn…...
layui+drogon完成文件上传(简例)
layui界面加入按钮、文本框、进度条: <div class"layui-row"><button type"button" class"layui-btn" id"file_upload_control">文件上传</button><input type"file" id"files_input…...

高精度地图服务引擎项目
技术栈:使用vue3TypeScriptElement PlusPiniaaxios 项目描述:高精度地图服务引擎项目,提供轻量化处理3D瓦片切片分布式处理分发服务的一站式解决方案 工作内容:1、项目60%已上的页面开发 2、部分模块的功能实现, 3、封…...
PyTorch使用Transformer进行机器翻译
文章目录 简介数据集环境要求实验代码实验结果参考来源 简介 本文使用PyTorch自带的transformer层进行机器翻译:从德语翻译为英语。从零开始实现Transformer请参阅PyTorch从零开始实现Transformer,以便于获得对Transfomer更深的理解。 数据集 Multi30…...

LoadRunner使用教程
1. LoadRunner简介 LoadRunner是一款广泛使用的性能测试工具 可以对各种应用程序进行性能测试,包括Web应用程序、移动应用程序、企业级应用程序等。它提供了一个综合的性能测试解决方案,包括测试计划设计、脚本录制、测试执行、结果分析和报告生成等功…...
Zia和ChatGPT如何协同工作?
有没有集成ChatGPT的CRM系统推荐?Zoho CRM已经正式与ChatGPT集成。下面我们将从使用场景、使用价值和使用范围等方面切入讲述CRMAI的应用和作用。 Zia和ChatGPT如何协同工作? Zia和ChatGPT是不同的人工智能模型,在CRM中呈现出共生的关系。 …...
【位操作】——获取整数变量最低位为 1 的位置
获取整数变量最低位为 1 的位置 #define BIT_LOW_BIT(y) (((y)&BIT(0)) ? 0 : (((y)&BIT(1)) ? 1 : (((y)&BIT(2)) ? 2 : (((y)&BIT(3)) ? 3 : \(((y)&BIT(4)) ? 4 : (((y)&BIT(5)) ? 5 : (((y)&BIT(6)) ? 6 : (((y)&…...

gtest测试用例注册及自动化调度机制源代码流程分析
gtest的入门参见: 玩转Google开源C单元测试框架Google Test系列(gtest) gtest源码分析流程参见: gtest流程解析 测试用例注册流程分析要点:TEST_F宏替换、C静态成员的动态初始化。 自动化调度流程分析要点:UnitTest、UnitTestIm…...

IOS自动化测试环境搭建教程
目录 一、前言 二、环境依赖 1、环境依赖项 2、环境需求与支持 三、环境配置 1、xcode安装 2、Git安装 3、Homebrew安装(用brew来安装依赖) 4、npm和nodejs安装 5、libimobiledevice安装 6、idevicesinstaller安装 7、ios-deploy安装 8、Ca…...

常用API学习08(Java)
格式化 格式化指的是将数据按照指定的规则转化为指定的形式 。 那么为什么需要格式化?格式化有什么用? 以数字类为例,假设有一个比分牌,在无人得分的时候我们希望以:“00:00”的形式存在,那么…...
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们? 在TypeScript中,装饰器(Decorators)是一种用于增强代码功能的特殊类型声明。装饰器提供了一种在类、方法、…...

Jenkins 还可以支持钉钉消息通知?一个插件带你搞定!
Jenkins 作为最流行的开源持续集成平台,其强大的拓展功能一直备受测试人员及开发人员的青睐。大家都知道我们可以在 Jenkins 中安装 Email 插件支持构建之后通过邮件将结果及时通知到相关人员。 但其实 Jenkins 还可以支持钉钉消息通知,其主要通过 Ding…...
7.ES使用
ES多条件查询 and , or这种的 ES模糊查询 like这种的 {"wildcard": {"title.keyword": {"value": "*宣讲*"}}}说明: title是要匹配的关键字段名称keyword是属性,表示匹配的是关键字信息,如果不用.ke…...
Web安全基础
1、HTML基础 什么是 HTML HTML 是用来描述网页的一种语言。 HTML 指的是超文本标记语言 (Hyper Text Markup Language) HTML 不是一种编程语言,而是一种标记语言 (Markup language) 标记语言是一套标记标签 (Markup tag) HTML 使用标记标签来描述网页 总的来说&…...

jQueryAPI
文章目录 1.jQuery 选择器1.1 jQuery 基础选择器1.2 jQuery 层级选择器1.3 隐式迭代1.4 jQuery 筛选选择器1.5 jQuery 筛选方法1.6 jQuery 里面的排他思想1.7 链式编程 2.jQuery 样式操作2.1 操作 css 方法2.2 设置类样式方法2.3 类操作与className区别 3.jQuery 效果3.1 显示隐…...

如何将路径字符串数组(string[])转成树结构(treeNode[])?
原文链接:如何将路径字符串数组(string[])转成树结构(treeNode[])? 需求 这里的UI使用的是Element-Plus。 将一个路径字符串数组(当然也可能是其他目标字符串数组),渲染成树。 /*source:/a/b/c/d/e/a/b/e/f/g/a/b/h/a…...

中国工程院院士陈晓红一行莅临麒麟信安调研
7月20日下午,中国工程院院士、湘江实验室主任、湖南工商大学党委书记陈晓红,湘江实验室副主任、湖南工商大学副校长刘国权,湘江实验室副主任、湖南工商大学党委组织部统战部常务副部长胡春华等领导一行莅临麒麟信安调研。麒麟信安董事长杨涛&…...
解决Linux环境下启动idea服务,由于权限问题无法正常启动问题
问题: 在Linux环境下启动idea服务,一直提示: invalid registry store file /app/appuser/.dmf/dubbo,cause:failed to create directory /app/appuser! 原因:文件夹中没有操作权限。 解决: (1࿰…...

Linux6.16 Docker consul的容器服务更新与发现
文章目录 计算机系统5G云计算第四章 LINUX Docker consul的容器服务更新与发现一、consul 概述1.什么是服务注册与发现2.什么是consul 二、consul 部署1.consul服务器2.registrator服务器3.consul-template4.consul 多节点 计算机系统 5G云计算 第四章 LINUX Docker consul的…...

Redis学习2--使用java操作Redis
1、java操作Redis库的比较 Redis有各种语言的客户端可以来操作redis数据库,其中java语言主要有Jedis与lettuce ,Spring Data Redis封装了上边两个客户端,优缺点如下: 2、使用Jedis操作Redis Jedis使用的基本步骤: 引…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

STM32标准库-DMA直接存储器存取
文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA(Direct Memory Access)直接存储器存取 DMA可以提供外设…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...

多种风格导航菜单 HTML 实现(附源码)
下面我将为您展示 6 种不同风格的导航菜单实现,每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...