yolov5 C++推理(libtorch和onnxruntime框架)

libtorch推理

#include <iostream>
#include <algorithm>
#include <opencv2/opencv.hpp>
#include <torch/script.h>
#include <torch/torch.h>std::vector<torch::Tensor> non_max_suppression(torch::Tensor preds, float score_thresh = 0.01, float iou_thresh = 0.35)
{std::vector<torch::Tensor> output;for (size_t i = 0; i < preds.sizes()[0]; ++i){torch::Tensor pred = preds.select(0, i);pred = pred.to(at::kCPU); //GPU推理结果为cuda数据类型,nms之前要转成cpu,否则会报错; 注意preds的数据类型,转成cpu进行后处理。// Filter by scorestorch::Tensor scores = pred.select(1, 4) * std::get<0>(torch::max(pred.slice(1, 5, pred.sizes()[1]), 1));pred = torch::index_select(pred, 0, torch::nonzero(scores > score_thresh).select(1, 0));if (pred.sizes()[0] == 0) continue;// (center_x, center_y, w, h) to (left, top, right, bottom)pred.select(1, 0) = pred.select(1, 0) - pred.select(1, 2) / 2;pred.select(1, 1) = pred.select(1, 1) - pred.select(1, 3) / 2;pred.select(1, 2) = pred.select(1, 0) + pred.select(1, 2);pred.select(1, 3) = pred.select(1, 1) + pred.select(1, 3);// Computing scores and classesstd::tuple<torch::Tensor, torch::Tensor> max_tuple = torch::max(pred.slice(1, 5, pred.sizes()[1]), 1);pred.select(1, 4) = pred.select(1, 4) * std::get<0>(max_tuple);pred.select(1, 5) = std::get<1>(max_tuple);torch::Tensor  dets = pred.slice(1, 0, 6);torch::Tensor keep = torch::empty({ dets.sizes()[0] });torch::Tensor areas = (dets.select(1, 3) - dets.select(1, 1)) * (dets.select(1, 2) - dets.select(1, 0));std::tuple<torch::Tensor, torch::Tensor> indexes_tuple = torch::sort(dets.select(1, 4), 0, 1);torch::Tensor v = std::get<0>(indexes_tuple);torch::Tensor indexes = std::get<1>(indexes_tuple);int count = 0;while (indexes.sizes()[0] > 0){keep[count] = (indexes[0].item().toInt());count += 1;// Computing overlapstorch::Tensor lefts = torch::empty(indexes.sizes()[0] - 1);torch::Tensor tops = torch::empty(indexes.sizes()[0] - 1);torch::Tensor rights = torch::empty(indexes.sizes()[0] - 1);torch::Tensor bottoms = torch::empty(indexes.sizes()[0] - 1);torch::Tensor widths = torch::empty(indexes.sizes()[0] - 1);torch::Tensor heights = torch::empty(indexes.sizes()[0] - 1);for (size_t i = 0; i < indexes.sizes()[0] - 1; ++i){lefts[i] = std::max(dets[indexes[0]][0].item().toFloat(), dets[indexes[i + 1]][0].item().toFloat());tops[i] = std::max(dets[indexes[0]][1].item().toFloat(), dets[indexes[i + 1]][1].item().toFloat());rights[i] = std::min(dets[indexes[0]][2].item().toFloat(), dets[indexes[i + 1]][2].item().toFloat());bottoms[i] = std::min(dets[indexes[0]][3].item().toFloat(), dets[indexes[i + 1]][3].item().toFloat());widths[i] = std::max(float(0), rights[i].item().toFloat() - lefts[i].item().toFloat());heights[i] = std::max(float(0), bottoms[i].item().toFloat() - tops[i].item().toFloat());}torch::Tensor overlaps = widths * heights;// FIlter by IOUstorch::Tensor ious = overlaps / (areas.select(0, indexes[0].item().toInt()) + torch::index_select(areas, 0, indexes.slice(0, 1, indexes.sizes()[0])) - overlaps);indexes = torch::index_select(indexes, 0, torch::nonzero(ious <= iou_thresh).select(1, 0) + 1);}keep = keep.toType(torch::kInt64);output.push_back(torch::index_select(dets, 0, keep.slice(0, 0, count)));}return output;
}int main(int argc, char* argv[])
{torch::DeviceType device_type = at::kCPU; // 定义设备类型if (torch::cuda::is_available()){device_type = at::kCUDA;std::cout << "cuda::is_available():" << torch::cuda::is_available() << std::endl;}// Loading  Moduletorch::jit::script::Module module = torch::jit::load("yolov5n-gpu.torchscript");module.to(device_type); std::vector<std::string> classnames;std::ifstream f("class_det.txt");std::string name;while (std::getline(f, name)){classnames.push_back(name);}cv::Mat frame = cv::imread("bus.jpg"), img;// Preparing input tensorcv::resize(frame, img, cv::Size(640, 640));cv::cvtColor(img, img, cv::COLOR_BGR2RGB);  // BGR -> RGBimg.convertTo(img, CV_32FC3, 1.0f / 255.0f);  // normalization 1/255auto imgTensor = torch::from_blob(img.data, { 1, img.rows, img.cols, img.channels() }).to(device_type);imgTensor = imgTensor.permute({ 0, 3, 1, 2 }).contiguous();  // BHWC -> BCHW (Batch, Channel, Height, Width)std::vector<torch::jit::IValue> inputs;inputs.emplace_back(imgTensor);torch::jit::IValue output = module.forward(inputs);auto preds = output.toTuple()->elements()[0].toTensor();std::vector<torch::Tensor> dets = non_max_suppression(preds, 0.35, 0.5);if (dets.size() > 0){for (size_t i = 0; i < dets[0].sizes()[0]; ++i){float left = dets[0][i][0].item().toFloat() * frame.cols / 640;float top = dets[0][i][1].item().toFloat() * frame.rows / 640;float right = dets[0][i][2].item().toFloat() * frame.cols / 640;float bottom = dets[0][i][3].item().toFloat() * frame.rows / 640;float score = dets[0][i][4].item().toFloat();int classID = dets[0][i][5].item().toInt();cv::rectangle(frame, cv::Rect(left, top, (right - left), (bottom - top)), cv::Scalar(0, 255, 0), 2);cv::putText(frame, classnames[classID] + ": " + cv::format("%.2f", score),cv::Point(left, top), cv::FONT_HERSHEY_SIMPLEX, (right - left) / 200, cv::Scalar(0, 255, 0), 2);}}cv::imshow("", frame);cv::waitKey();return 0;
}

onnxruntime推理

#include <iostream>
#include <fstream>
#include <opencv2/opencv.hpp>
#include <onnxruntime_cxx_api.h>void LetterBox(const cv::Mat& image, cv::Mat& outImage,cv::Vec4d& params, //[ratio_x,ratio_y,dw,dh]const cv::Size& newShape = cv::Size(640, 640),bool autoShape = false,bool scaleFill = false,bool scaleUp = true,int stride = 32,const cv::Scalar& color = cv::Scalar(114, 114, 114))
{cv::Size shape = image.size();float r = std::min((float)newShape.height / (float)shape.height, (float)newShape.width / (float)shape.width);if (!scaleUp){r = std::min(r, 1.0f);}float ratio[2]{ r, r };int new_un_pad[2] = { (int)std::round((float)shape.width * r),(int)std::round((float)shape.height * r) };auto dw = (float)(newShape.width - new_un_pad[0]);auto dh = (float)(newShape.height - new_un_pad[1]);if (autoShape){dw = (float)((int)dw % stride);dh = (float)((int)dh % stride);}else if (scaleFill){dw = 0.0f;dh = 0.0f;new_un_pad[0] = newShape.width;new_un_pad[1] = newShape.height;ratio[0] = (float)newShape.width / (float)shape.width;ratio[1] = (float)newShape.height / (float)shape.height;}dw /= 2.0f;dh /= 2.0f;if (shape.width != new_un_pad[0] && shape.height != new_un_pad[1])cv::resize(image, outImage, cv::Size(new_un_pad[0], new_un_pad[1]));elseoutImage = image.clone();int top = int(std::round(dh - 0.1f));int bottom = int(std::round(dh + 0.1f));int left = int(std::round(dw - 0.1f));int right = int(std::round(dw + 0.1f));params[0] = ratio[0];params[1] = ratio[1];params[2] = left;params[3] = top;cv::copyMakeBorder(outImage, outImage, top, bottom, left, right, cv::BORDER_CONSTANT, color);
}void nms(std::vector<cv::Rect>& boxes, std::vector<float>& confs, std::vector<int>& classIds, float threshold)
{assert(boxes.size() == confs.size());struct BoxConf{cv::Rect box;float conf;int id;};std::vector<BoxConf> boxes_confs;for (size_t i = 0; i < boxes.size(); i++){BoxConf box_conf;box_conf.box = boxes[i];box_conf.conf = confs[i];box_conf.id = classIds[i];boxes_confs.push_back(box_conf);}std::sort(boxes_confs.begin(), boxes_confs.end(), [](BoxConf a, BoxConf b) { return a.conf > b.conf; });std::vector<float> area(boxes_confs.size());for (size_t i = 0; i < boxes_confs.size(); ++i){area[i] = boxes_confs[i].box.width * boxes_confs[i].box.height;}std::vector<bool> isSuppressed(boxes_confs.size(), false);for (size_t i = 0; i < boxes_confs.size(); ++i){if (isSuppressed[i])	{ continue; }for (size_t j = i + 1; j < boxes_confs.size(); ++j){if (isSuppressed[j])	{ continue; }float x1 = (std::max)(boxes_confs[i].box.x, boxes_confs[j].box.x);float y1 = (std::max)(boxes_confs[i].box.y, boxes_confs[j].box.y);float x2 = (std::min)(boxes_confs[i].box.x + boxes_confs[i].box.width, boxes_confs[j].box.x + boxes_confs[j].box.width);float y2 = (std::min)(boxes_confs[i].box.y + boxes_confs[i].box.height, boxes_confs[j].box.y + boxes_confs[j].box.height);float w = (std::max)(0.0f, x2 - x1);float h = (std::max)(0.0f, y2 - y1);float inter = w * h;float ovr = inter / (area[i] + area[j] - inter);if (ovr >= threshold) { isSuppressed[j] = true; }}}boxes.clear();confs.clear();classIds.clear();for (int i = 0; i < boxes_confs.size(); ++i){if (!isSuppressed[i]){boxes.push_back(boxes_confs[i].box);confs.push_back(boxes_confs[i].conf);classIds.push_back(boxes_confs[i].id);}}
}int main(int argc, char* argv[])
{std::string imgpath = "zidane.jpg";Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "yolov5s");Ort::SessionOptions session_options;session_options.SetIntraOpNumThreads(1);//设置线程数session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED);//启用模型优化策略//CUDA option setOrtCUDAProviderOptions cuda_option;cuda_option.device_id = 0;cuda_option.arena_extend_strategy = 0;cuda_option.cudnn_conv_algo_search = OrtCudnnConvAlgoSearchExhaustive;cuda_option.gpu_mem_limit = SIZE_MAX;cuda_option.do_copy_in_default_stream = 1;session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_ALL);session_options.AppendExecutionProvider_CUDA(cuda_option);const wchar_t* model_path = L"yolov5s-det.onnx"; //表示一个指向常量宽字符字符串L"yolov5s.onnx"的指针std::vector<std::string> class_names;std::string classesFile = "coco.names";//加载labelstd::ifstream ifs(classesFile.c_str());//用了classesFile.c_str()函数将字符串classesFile转换为C风格的字符串(即以null结尾的字符数组),并将其作为参数传递给std::ifstream类的构造函数。std::string line;while (getline(ifs, line)) class_names.push_back(line);//第一个参数env是一个ORT环境对象,用于管理ORT会话的资源和配置。//第二个参数model_path是一个指向ONNX模型文件的路径的常量指针,用于指定ORT会话要加载的模型。// 第三个参数session_options是一个ORT会话选项对象,用于配置ORT会话的选项和优化策略。Ort::Session session(env, model_path, session_options);Ort::AllocatorWithDefaultOptions allocator;//通过使用Ort::AllocatorWithDefaultOptions类,可以方便地进行内存分配和管理,而无需手动实现内存分配和释放的细节。size_t num_input_nodes = session.GetInputCount();std::vector<const char*> input_node_names = { "images" };std::vector<const char*> output_node_names = { "output" };const size_t input_tensor_size = 3 * 640 * 640;std::vector<float> input_tensor_values(input_tensor_size);cv::Mat srcimg = cv::imread(imgpath);int newh = 0, neww = 0, padh = 0, padw = 0;cv::Mat dstimg;cv::Vec4d params;cv::Mat letterbox;LetterBox(srcimg, dstimg, params);for (int c = 0; c < 3; c++){for (int i = 0; i < 640; i++){for (int j = 0; j < 640; j++){float pix = dstimg.ptr<uchar>(i)[j * 3 + 2 - c];//转换通道,输入onnx模型的图片通道顺序是RGB,但是opencv存储默认是BGRinput_tensor_values[c * 640 * 640 + i * 640 + size_t(j)] = pix / 255.0;//归一化}}}// create input tensor object from data valuesstd::vector<int64_t> input_node_dims = { 1, 3, 640, 640 };auto memory_info = Ort::MemoryInfo::CreateCpu(OrtArenaAllocator, OrtMemTypeDefault);Ort::Value input_tensor = Ort::Value::CreateTensor<float>(memory_info, input_tensor_values.data(), input_tensor_size, input_node_dims.data(), input_node_dims.size());std::vector<Ort::Value> ort_inputs;ort_inputs.push_back(std::move(input_tensor));//右值引用,避免不必要的拷贝和内存分配操作// score model & input tensor, get back output tensorstd::vector<Ort::Value> output_tensors;for (int i = 0; i < 10; i++){clock_t start_time = clock();output_tensors = session.Run(Ort::RunOptions{ nullptr }, input_node_names.data(), ort_inputs.data(), input_node_names.size(), output_node_names.data(), output_node_names.size());clock_t end_time = clock();std::cout << "inference time: " << static_cast<double>(end_time - start_time) / CLOCKS_PER_SEC << " seconds" << std::endl;}// Get pointer to output tensor float valuesconst float* rawOutput = output_tensors[0].GetTensorData<float>();//generate proposalsstd::vector<int64_t> outputShape = output_tensors[0].GetTensorTypeAndShapeInfo().GetShape();size_t count = output_tensors[0].GetTensorTypeAndShapeInfo().GetElementCount();std::vector<float> output(rawOutput, rawOutput + count);std::vector<cv::Rect> boxes;std::vector<float> confs;std::vector<int> classIds;int numClasses = (int)outputShape[2] - 5;int elementsInBatch = (int)(outputShape[1] * outputShape[2]);float confThreshold = 0.5;	//置信度阈值float iouThreshold = 0.5;	//iou阈值for (auto it = output.begin(); it != output.begin() + elementsInBatch; it += outputShape[2]){float clsConf = *(it + 4);if (clsConf > confThreshold){int centerX = (int)(*it);int centerY = (int)(*(it + 1));int width = (int)(*(it + 2));int height = (int)(*(it + 3));int x1 = centerX - width / 2;int y1 = centerY - height / 2;boxes.emplace_back(cv::Rect(x1, y1, width, height));// first 5 element are x y w h and obj confidenceint bestClassId = -1;float bestConf = 0.0;for (int i = 5; i < numClasses + 5; i++){if ((*(it + i)) > bestConf){bestConf = it[i];bestClassId = i - 5;}}confs.push_back(clsConf);classIds.push_back(bestClassId);}}//极大值抑制nms(boxes, confs, classIds, iouThreshold);//结果可视化for (size_t i = 0; i < boxes.size(); ++i){cv::rectangle(dstimg, cv::Point(boxes[i].tl().x, boxes[i].tl().y), cv::Point(boxes[i].br().x, boxes[i].br().y), cv::Scalar(0, 0, 255), 1);cv::putText(dstimg, class_names[classIds[i]] + " " + std::to_string(confs[i]), cv::Point(boxes[i].tl().x, boxes[i].tl().y - 5), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(255, 0, 0), 1);}cv::imshow("result", dstimg);cv::waitKey();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/9863.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络专线如何改成SDWAN?

将网络专线改成SDWAN涉及一系列步骤和决策。下面是一个概括的指南&#xff0c;帮助您了解如何将网络专线迁移到SDWAN。 1.需求分析&#xff1a;首先&#xff0c;您需要对现有网络专线的性能、需求和限制进行全面分析。了解各个分支机构的带宽需求、网络延迟、丢包率以及关键应…

阿里云NVIDIA A100 GPU云服务器性能详解及租用费用

阿里云GPU服务器租用费用表包括包年包月、一个小时收费以及学生GPU服务器租用费用&#xff0c;阿里云GPU计算卡包括NVIDIA V100计算卡、T4计算卡、A10计算卡和A100计算卡&#xff0c;GPU云服务器gn6i可享受3折&#xff0c;阿里云百科分享阿里云GPU服务器租用表、GPU一个小时多少…

各种知名游戏的技术分析

介绍一个GitHub&#xff0c;里面包括了市面上的各种游戏的技术分析&#xff0c;包括渲染管线、工作流、技术文章等等&#xff0c;在做某个类型的游戏的时候&#xff0c;可以针对某个游戏去进行技术参考&#xff0c;特别实用。 GitHub - OTFCG/Awesome-Game-Analysis: a compre…

C++那些事之template disambiguator

template disambiguator 1.背景 最近看到一段代码&#xff1a; auto chunk_left first_sort_key.template GetChunk<ArrayType>(left); 请问&#xff0c;这里的.template代表什么意义&#xff1f; 本节将从实际例子出发&#xff0c;探讨这个意义。 2.template disambigu…

数仓学习---16、可视化报表(Superset)

星光下的赶路人star的个人主页 真正的才智是刚毅的志向 文章目录 1、Superset入门1.1 Superset概述1.2 环境说明 2、Superset安装2.1 安装Python环境2.1.1 安装Miniconda2.1.2 创建Python3.7 环境 2.2 Superset部署2.2.1 安装依赖2.2.2 安装Superset2.2.3 启动Superset2.2.4 Su…

【ARM Coresight 系列文章 10.2 - ARM Coresight STM Trace packets】

文章目录 Trace protocolpacket的种类Error packetsVERSION Packets同步 packet 上篇文章&#xff1a;ARM Coresight 系列文章 10.1 - ARM Coresight STM 介绍及使用 下篇文章&#xff1a;ARM Coresight 系列文章 10.3 - ARM Coresight STM 寄存器介绍 及STM DMA 传输介绍 Trac…

WPF实战学习笔记13-创建注册登录接口

创建注册登录接口 添加文件 创建文件 MyToDo.Api ​ ./Controllers/LoginController.cs ​ ./Service/ILoginService.cs ​ ./Service/LoginService.cs MyToDo.Share ./Dtos/UserDto.cs LoginController.cs using Microsoft.AspNetCore.Mvc; using MyToDo.Api.Context;…

vue-pdf 单列显示多个pdf页面

<template><div><pdfv-for"i in numPages":key"i":src"src":page"i"style"display: inline-block; width: 100%"></pdf> <!-- 宽度设置100% 一行只展示一页 --></div> </template&g…

【uni-app2.0】实现登录页记住密码功能

使用uni-app的uni.setStorageSync()和uni.getStorageSync()方法来存储和读取密码 在登录页中添加一个记住密码的u-checkbox选项&#xff0c;并在data里面添加一个rememberPwd的布尔值&#xff0c;在每次点击记住密码change的时候来记录用户的选择 <u-checkbox-group place…

基于java的坦克大战游戏的设计与实现--毕业论文--【毕业论文】

文章目录 本系列校训毕设的技术铺垫文章主体层次摘要&#xff1a;示例摘要的写法 引言&#xff1a;系统分析总体设计总体功能总体功能如图1所示坦克大战总体流程图 详细设计游戏测试结论参考文献参考文献 配套资源 本系列校训 互相伤害互相卷&#xff0c;玩命学习要你管&#…

Linux磁盘管理命令

目录 1. du (disk usage文件和目录占用的磁盘空间) 2. df (disk free 查看磁盘使用情况) 3. lsblk(list block查看块设备挂载情况) 1. du (disk usage文件和目录占用的磁盘空间) du [-ahskm] 目录/文件&#xff08;文件大小可以直接使用ll查看&#xff09; 选项与参数&a…

(八九)如何与InfluxDB交互InfluxDB HTTP API

以下内容来自 尚硅谷&#xff0c;写这一系列的文章&#xff0c;主要是为了方便后续自己的查看&#xff0c;不用带着个PDF找来找去的&#xff0c;太麻烦&#xff01; 第 8 章 前言&#xff1a;如何与InfluxDB交互 1、InfluxDB启动后&#xff0c;会向外提供一套HTTP API。外部程…

正则表达式-速成教程

正则表达式-速成教程 今天遇到一枚程序媛在群里吐槽&#xff0c;并附了截图&#xff1b;然后无意中看到她的一个正则与她的注释描述不一致&#xff0c;就提醒了一下。顺带着给了个速成教程&#xff0c;在这里把这个速成教程贴出来&#xff0c;一是为了自己备份&#xff1b;二是…

QT【day1】

登录框&#xff1a; #include "mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent) {//窗口设置this->setFixedSize(600,600); //大小this->setWindowTitle("MUMU"); //文本内容this->setWindowOpacity(0.8); //透…

力扣 -- 978. 最长湍流子数组

一、题目 二、解题步骤 下面是用动态规划的思想解决这道题的过程&#xff0c;相信各位小伙伴都能看懂并且掌握这道经典的动规题目滴。 三、参考代码 class Solution { public:int maxTurbulenceSize(vector<int>& nums) {int nnums.size();vector<int> f(n);…

k8s中强制删除pv

K8s 集群内有一个已经不再使用的 PV&#xff0c;虽然已经删除了与其关联的 Pod 及 PVC&#xff0c;并对其执行了删除命令&#xff0c;但仍无法正常删除&#xff0c;一直处于 Terminating 状态&#xff1a; 解决办法&#xff1a; 1. 获取pv信息 kubectl get pv 2. 解除pv锁定 …

对话商汤王晓刚:“百模大战”下半场,如何才能突出重围?

点击关注 文 | 姚悦 今年最早发布的那批大模型&#xff0c;现在怎么样了&#xff1f; 近期&#xff0c;商汤科技宣布“商汤日日新SenseNova”大模型体系完成了第一次重大迭代。这距离其发布过去3个月时间。 “每天不断接到用户调用&#xff0c;收到建议反馈后&#xff0c;每隔…

阿里Java开发手册~日志规约

1. 【强制】应用中不可直接使用日志系统 &#xff08; Log 4 j 、 Logback &#xff09; 中的 API &#xff0c;而应依赖使用日志框架 SLF 4 J 中的 API &#xff0c;使用门面模式的日志框架&#xff0c;有利于维护和各个类的日志处理方式统一。 import org.slf4j.Logger…

QT实现用户登录注册功能

本文实例为大家分享了QT实现用户登录注册的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下 1、login.h ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #ifndef LOGIN_H #define LOGIN_H #include <QWidget> namespace Ui { c…

Python - OpenCV机器视觉库的简单使用经验

OpenCV是一个开源的计算机视觉库&#xff0c;它支持多种编程语言&#xff0c;包括Python。下面是Python 3中OpenCV的详细解析&#xff1a; 安装OpenCV 在Python 3中安装OpenCV&#xff0c;可以使用pip命令来安装。例如&#xff0c;在终端中输入以下命令&#xff1a; pip ins…