[C++][cmake]基于C++在windows上onnxruntime+opencv部署yolo26-obb的旋转框检测onnx模型

yolo26已经正式发布了,因此使用C++代码实现YOLO26-obb旋转框检测的onnx模型部署,首先看yolo11n-obb网络结构,发现输出shape是1x20x21504

再来看看yolo26n-obb网络结构输出,输出shape是1x300x7

安装好yolo26环境,要求ultralytics==8.4.0,转换命令
yolo export model=yolo26n-obb.pt format=onnx opset=12
测试环境:
vs2019
cmake==3.30.1
onnxruntime-win-x64-gpu-1.20.1
opencv==4.9.0
运行步骤:
先删除build文件夹
然后打开CMakeLists.txt里面opencv和onnxruntime路径
重新cmake后会生成exe
测试命令:切换到exe路径后执行
测试图片:
YOLO26_ort --input=test.jpg
测试摄像头:
YOLO26_ort --input=0 [--gpu] 注意运行gpu需要安装onnxruntime-win-x64-gpu-1.20.1对应cuda这个官方可以查询到,测试cuda12.4+cudnn9.4.1可以其他版本应该也可以看要求
测试视频:
YOLO26_ort --input=test_video.mp4 --output=result.mp4 --conf=0.3

调用代码:

#include <iostream> #include <opencv2/opencv.hpp> #include <chrono> #include <algorithm> #include "YOLO26Obb.hpp" //注意如果onnx上推理显示为空,很可能是导出onnx问题,需要设置opset=12 struct Args { std::string model_path = "./yolo26n-obb.onnx"; std::string classes_path = "./labels.txt"; std::string input_path = "./P0032.png"; std::string output_path = "./output.jpg"; bool use_gpu = false; float conf_threshold = 0.25f; float iou_threshold = 0.25f; bool help = false; }; void print_help() { std::cout << "YOLOv26 C++ OBB\n\n"; std::cout << "Usage: ./yolo26_ort [options]\n\n"; std::cout << "Options:\n"; std::cout << " --model <path> Path to ONNX model file (default: ./yolo26n-obb.onnx)\n"; std::cout << " --classes <path> Path to class names file (default: ./labels.txt)\n"; std::cout << " --input <path> Path to input video/image file or camera device index (default: ./P0032.png)\n"; std::cout << " --output <path> Path to output video/image file (default: ./output.jpg)\n"; std::cout << " --gpu Use GPU acceleration if available (default: false)\n"; std::cout << " --conf <value> Confidence threshold (default: 0.25)\n"; std::cout << " --iou <value> IoU threshold for NMS (default: 0.25)\n"; std::cout << " --help Show this help message\n\n"; std::cout << "Examples:\n"; std::cout << " yolo26_ort --input=test_video.mp4 --output=result.mp4 --conf=0.3\n"; std::cout << " yolo26_ort --input=0 --gpu # Use webcam with GPU and obb\n"; std::cout << " yolo26_ort --input=test.jpg # Image obb\n"; } Args parse_args(int argc, char *argv[]) { Args args; for (int i = 1; i < argc; ++i) { std::string arg(argv[i]); if (arg == "--help" || arg == "-h") { args.help = true; } else if (arg.find("--model=") == 0) { args.model_path = arg.substr(8); } else if (arg.find("--classes=") == 0) { args.classes_path = arg.substr(10); } else if (arg.find("--input=") == 0) { args.input_path = arg.substr(8); } else if (arg.find("--output=") == 0) { args.output_path = arg.substr(9); } else if (arg == "--gpu") { args.use_gpu = true; } else if (arg.find("--conf=") == 0) { args.conf_threshold = std::stof(arg.substr(7)); } else if (arg.find("--iou=") == 0) { args.iou_threshold = std::stof(arg.substr(6)); } else { std::cerr << "Unknown argument: " << arg << std::endl; } } return args; } bool is_camera_input(const std::string &input) { try { std::stoi(input); return true; } catch (const std::exception &) { return false; } } bool is_image_file(const std::string &input) { std::string lower = input; std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); return lower.find(".jpg") != std::string::npos || lower.find(".jpeg") != std::string::npos || lower.find(".png") != std::string::npos || lower.find(".bmp") != std::string::npos; } void draw_fps(cv::Mat &frame, double fps) { std::string fps_text = "FPS: " + std::to_string(static_cast<int>(fps)); cv::putText(frame, fps_text, cv::Point(10, 30), cv::FONT_HERSHEY_SIMPLEX, 1.0, cv::Scalar(0, 255, 0), 2); } int main(int argc, char *argv[]) { Args args = parse_args(argc, argv); if (args.help) { print_help(); return 0; } std::cout << "YOLOv26 C++ OBB\n"; std::cout << "============================================\n"; std::cout << "Model: " << args.model_path << "\n"; std::cout << "Classes: " << args.classes_path << "\n"; std::cout << "Input: " << args.input_path << "\n"; std::cout << "Output: " << args.output_path << "\n"; std::cout << "GPU: " << (args.use_gpu ? "enabled" : "disabled") << "\n"; std::cout << "Confidence threshold: " << args.conf_threshold << "\n"; std::cout << "IoU threshold: " << args.iou_threshold << "\n"; std::cout << "\n"; YOLO26OBBDetector detector(args.model_path, args.classes_path, args.use_gpu); if (is_image_file(args.input_path)) { std::cout << "Processing single image: " << args.input_path << std::endl; cv::Mat image = cv::imread(args.input_path); if (image.empty()) { std::cerr << "Error: Cannot read image file: " << args.input_path << std::endl; return -1; } cv::Mat result = image.clone(); auto start_time = std::chrono::high_resolution_clock::now(); auto detections = detector.detect(image, args.conf_threshold, args.iou_threshold); auto end_time = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time); std::cout << "Detection completed in " << duration.count() << "ms" << std::endl; std::cout << "Detected " << detections.size() << " objects" << std::endl; detector.drawBoundingBox(result, detections); std::string output_path = args.output_path; if (output_path == "./output.jpg") { size_t dot_pos = args.input_path.find_last_of('.'); std::string base_name = args.input_path.substr(0, dot_pos); output_path = base_name + "_result.jpg"; } cv::imwrite(output_path, result); std::cout << "Result saved to: " << output_path << std::endl; cv::Mat display_result; double scale = std::min(1280.0 / result.cols, 720.0 / result.rows); cv::Size display_size(result.cols * scale, result.rows * scale); cv::resize(result, display_result, display_size); cv::imshow("YOLOv26 Result", display_result); cv::waitKey(0); return 0; } cv::VideoCapture cap; if (is_camera_input(args.input_path)) { int camera_id = std::stoi(args.input_path); cap.open(camera_id); std::cout << "Opening camera " << camera_id << std::endl; } else { cap.open(args.input_path); std::cout << "Opening video file: " << args.input_path << std::endl; } if (!cap.isOpened()) { std::cerr << "Error: Cannot open input source: " << args.input_path << std::endl; return -1; } int frame_width = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_WIDTH)); int frame_height = static_cast<int>(cap.get(cv::CAP_PROP_FRAME_HEIGHT)); double fps = cap.get(cv::CAP_PROP_FPS); if (fps <= 0) fps = 30.0; std::cout << "Video properties: " << frame_width << "x" << frame_height << " @ " << fps << " FPS\n\n"; cv::VideoWriter writer; if (!is_camera_input(args.input_path)) { int fourcc = cv::VideoWriter::fourcc('m', 'p', '4', 'v'); writer.open(args.output_path, fourcc, fps, cv::Size(frame_width, frame_height)); if (!writer.isOpened()) { std::cerr << "Error: Cannot open output video file: " << args.output_path << std::endl; return -1; } std::cout << "Output will be saved to: " << args.output_path << std::endl; } auto start_time = std::chrono::high_resolution_clock::now(); int frame_count = 0; double avg_fps = 0.0; cv::Mat frame; std::cout << "\nProcessing... Press 'q' to quit.\n\n"; while (true) { auto frame_start = std::chrono::high_resolution_clock::now(); if (!cap.read(frame)) { if (is_camera_input(args.input_path)) { std::cerr << "Error reading from camera" << std::endl; break; } else { std::cout << "End of video file reached" << std::endl; break; } } cv::Mat result = frame.clone(); auto detections = detector.detect(frame, args.conf_threshold, args.iou_threshold); detector.drawBoundingBox(result, detections); auto frame_end = std::chrono::high_resolution_clock::now(); auto frame_duration = std::chrono::duration_cast<std::chrono::milliseconds>(frame_end - frame_start); double current_fps = 1000.0 / frame_duration.count(); frame_count++; avg_fps = (avg_fps * (frame_count - 1) + current_fps) / frame_count; draw_fps(result, current_fps); if (is_camera_input(args.input_path)) { cv::imshow("YOLOv26 OBB", result); char key = cv::waitKey(1) & 0xFF; if (key == 'q' || key == 27) { break; } } if (writer.isOpened()) { writer.write(result); } if (!is_camera_input(args.input_path) && frame_count % 30 == 0) { std::cout << "Processed " << frame_count << " frames, Average FPS: " << static_cast<int>(avg_fps) << std::endl; } } cap.release(); if (writer.isOpened()) { writer.release(); } cv::destroyAllWindows(); auto end_time = std::chrono::high_resolution_clock::now(); auto total_duration = std::chrono::duration_cast<std::chrono::seconds>(end_time - start_time); std::cout << "\nProcessing completed!\n"; std::cout << "Total frames processed: " << frame_count << std::endl; std::cout << "Total time: " << total_duration.count() << " seconds\n"; std::cout << "Average FPS: " << static_cast<int>(avg_fps) << std::endl; return 0; }

最后测试效果:

源码地址:https://download.csdn.net/download/FL1623863129/92566174

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

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

相关文章

交通仿真软件:VISSIM_(10).宏观交通仿真应用

宏观交通仿真应用 在交通仿真领域&#xff0c;宏观交通仿真主要关注交通流的整体行为&#xff0c;而不是单个车辆的详细运动。这种仿真方法适用于大规模交通网络的分析&#xff0c;可以帮助规划师和工程师了解交通流在不同时间和空间上的分布情况&#xff0c;从而优化交通网络设…

互联网服务提供商:掌控网络接入的底层逻辑

当你打开浏览器访问网页或通过终端发起 SSH 连接时&#xff0c;数据流必须经过特定的物理基础设施。ISP&#xff08;Internet Service Provider&#xff09;&#xff0c;即互联网服务提供商&#xff0c;正是负责搭建并维护这些基础设施的机构。它不仅是每月收取宽带费用的商业公…

CDN 工作原理:空间换取时间的网络架构

在互联网数据的传输过程中&#xff0c;物理距离是影响加载速度的核心要素之一。光速虽然极快&#xff0c;但在复杂的网络拓扑和层层路由转发中&#xff0c;数据包从地球一端传输到另一端必然产生显著的延迟。内容分发网络&#xff08;CDN&#xff09;的设计初衷&#xff0c;并非…

交通仿真软件:VISSIM_(11).交通仿真结果分析与评价

交通仿真结果分析与评价 在交通仿真软件&#xff08;如VISSIM&#xff09;中&#xff0c;结果分析与评价是一个至关重要的步骤&#xff0c;它不仅帮助我们理解仿真过程中发生的交通现象&#xff0c;还能提供优化交通系统和规划的重要依据。本节将详细介绍如何在VISSIM中进行交通…

交通仿真软件:VISSIM_(8).动态交通分配

动态交通分配 动态交通分配的原理 动态交通分配&#xff08;Dynamic Traffic Assignment, DTA&#xff09;是交通仿真中的一个重要模块&#xff0c;它用于模拟交通流量在路网中的动态分配过程。与静态交通分配不同&#xff0c;动态交通分配考虑了时间因素&#xff0c;即交通流量…

导师严选10个AI论文网站,自考学生轻松搞定毕业论文!

导师严选10个AI论文网站&#xff0c;自考学生轻松搞定毕业论文&#xff01; AI 工具如何助力自考论文写作&#xff1f; 在当前的学术环境中&#xff0c;越来越多的学生开始借助 AI 工具来辅助论文写作。尤其是对于自考学生而言&#xff0c;时间紧、任务重&#xff0c;如何高效地…

停止“装富”,做个隐形富人

不显山露水的富裕&#xff1a;普通家庭的长期理财之道 灯火可亲的家庭账本 你家客厅的那盏灯&#xff0c;稳吗&#xff1f; 前两天晚上回家&#xff0c;把车停在楼下&#xff0c;我没急着上楼&#xff0c;而是习惯性地抬头看了看万家灯火 。 看着那些窗户&#xff0c;我常在想…

2026出差旅行充电宝品牌深度解析:从安全技术到场景适配的五大头部产品全链路拆解。 - 品牌推荐

在2026年价值驱动的商旅出行阶段,如何在充电宝这一看似成熟的市场中,锁定技术专业、安全可靠且真正解决差旅痛点的产品,已成为频繁出行人士的关键议题。真正的价值,取决于品牌是否拥有核心防护技术,并具备在复杂差…

实用指南:《K8s 网络入门到进阶:Service 与 Ingress 原理、部署方案及核心区别对比》

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2026年靠谱出差旅行充电宝品牌严选推荐:这五款产品的长期口碑与防护实力经得起考验。 - 品牌推荐

随着全球商务与休闲旅行活动全面复苏,移动电子设备已成为差旅人士不可或缺的“数字器官”,其续航保障设备——充电宝的安全性与可靠性,正从单纯的电力补充工具,演变为关乎个人隐私与数据安全的关键防线。在酒店、机…

出差充电宝怎么选?2026年最新兼顾安全与续航的终极选择指南与品牌推荐。 - 品牌推荐

随着全球商务与休闲旅行活动的全面复苏,差旅人群对移动电子设备的依赖达到前所未有的高度。充电宝,作为保障设备持续在线的“能量心脏”,其角色已从简单的续航工具,演变为关乎工作效率、信息安全乃至个人隐私的关键…

2026年靠谱商旅充电宝品牌严选推荐:这五家企业的防护技术与产品实力经得起考验。 - 品牌推荐

随着全球商务与休闲出行频率的持续回升,差旅场景下的个人电子设备续航与数据隐私安全问题日益凸显。对频繁出行的用户而言,选择一款兼具大容量、快充、便携性,尤其是能有效防范公共环境数据泄露风险的充电宝,已从简…

浅析自定义/review命令与Cursor内置Agent Review代码审核功能效果对比与工作区别

之前我有整理一个自定义的代码审核命令,然后 Cursor 也有内置 Agent Review 功能,最近在使用的时候发现:我自定义命令基本可以把问题检查出来,且会给修改建议,及优先修复建议(基本给的都挺准的),但是同样的情况…

web入门61-70

web61 分析代码还是一样c=show_source(flag.php); web62 分析代码依旧一样c=show_source(flag.php); web63 分析代码和上一关一样web64 分析代码一样web65 分析代码一样web66 分析代码首先用c=print_r(scandir("/…

linux内核 - 进程管理和调度(基于6.19内核)

一&#xff1a;概述所有现代操作系统都能够同时运行多个进程——至少在用户看来是这样。如果系统只有一个处理器&#xff0c;那么在任意时刻实际上只能运行一个程序。在多处理器系统中&#xff0c;真正能够并行运行的进程数量取决于物理 CPU 的数量。内核和处理器通过以极快的速…

揭秘正则表达式的基础语法与应用

正则表达式是强大的文本处理工具。从字符类到量词&#xff0c;再到分组与选择&#xff0c;本篇文章将带你深入了解正则表达式的基础语法和在实际场景中的广泛应用。无论你是初学者还是需要快速复习&#xff0c;本篇都将为你提供详尽而易于理解的指引。一、正则表达式属性(修饰符…

突破类别围墙:当YOLO学会“看图说话”——开放世界交互式视觉感知系统

想象一下,你指着监控画面问:“那个穿红色衣服、正在奔跑的人是谁?” AI不仅能框出目标,还能回答:“是昨天下午出现在公园的李某。” 这不是科幻,而是视觉-语言模型赋予YOLO的开放世界感知能力。 在传统目标检测领域,YOLO已接近“天花板”——COCO数据集的80个类别、VOC的…

驱动开发系列75 - Zink OpenGL 到 Vulkan 转换层解析

目录 一:概述 二:架构概述 (一): Zink设计原则: (二): Zink 核心数据结构: (三):Zink 资源管理: (四):批处理状态管理 1. 主要函数: 2. 命令缓冲区类型: (五):描述符管理 (六):着色器管理 (七) :管线状态管理 (八):交换链管理 (九): 绘…

驱动开发系列76 - Mesa NIR 通用中间语言表示

一:概述 NIR 是Mesa 的通用中间表示,适用于所有图形API和硬件后端。本文介绍下NIR的设计架构。包括NIR核心数据结构,NIR优化过程,NIR降级和验证。 二:架构概览 NIR 作为Mesa中所有着色器的汇聚点,提供了一种通用表示,使得不同前端语言(GLSL、SPIRV、TGSI)和后端(LLV…

深入解析Sentinel熔断机制 - 详解

深入解析Sentinel熔断机制 - 详解2026-01-17 19:10 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !impor…