[C++][cmake]基于C++在windows上onnxruntime+opencv部署yolo26-pose的姿态估计关键点检测onnx模型

yolo26已经正式发布了,因此使用C++代码实现YOLO26-pose姿态估计的onnx模型部署,首先看yolo11n-pose网络结构,发现输出shape是1x56x8400

再来看看yolo26n-pose网络结构输出,输出shape是1x300x57

可见yolo11和yolo26输出是不一样的是不能共用代码。

安装好yolo26环境,要求ultralytics==8.4.0,转换命令
yolo export model=yolo26n-pose.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 "YOLO26Pose.hpp" //注意如果onnx上推理显示为空,很可能是导出onnx问题,需要设置opset=12 struct Args { std::string model_path = "./yolo26n-pose.onnx"; std::string classes_path = "./pose.yaml"; std::string input_path = "./input.mov"; std::string output_path = "./output.mp4"; bool use_gpu = false; float conf_threshold = 0.25f; float iou_threshold = 0.45f; bool help = false; }; void print_help() { std::cout << "YOLO26 C++ Pose\n\n"; std::cout << "Usage: ./yolo26_ort [options]\n\n"; std::cout << "Options:\n"; std::cout << " --model <path> Path to ONNX model file (default: ./best_fixed.onnx)\n"; std::cout << " --classes <path> Path to class names file (default: ./pose.yaml)\n"; std::cout << " --input <path> Path to input video file or camera device index (default: ./input.mov)\n"; std::cout << " --output <path> Path to output video file (default: ./output.mp4)\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.45)\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 << "YOLO26 C++ Pose\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"; YOLO26PoseDetector 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.drawPosedBoundingBox(result, detections); std::string output_path = args.output_path; if (output_path == "./output.mp4") { 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("YOLO26 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.drawPosedBoundingBox(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("YOLO26 Pose", 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/92566112

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

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

相关文章

银盛支付罚单背后:支付行业商户管理乱象亟待根治

2026年1月&#xff0c;中国人民银行深圳市分行对银盛支付服务股份有限公司开出1584万元罚单&#xff0c;成为2026年支付行业首张千万级罚单。这张罚单直指"违反商户管理规定、违反清算管理规定、违反账户管理规定"三项核心违规&#xff0c;时任董事长陈某同时被罚61万…

迪赛福闪测仪:高效精准,助力制造升级关键装备 - 工业仪器权威说

在工业测量领域,闪测仪(又称一键式影像测量仪)正以其高效、精准的检测能力,成为现代智能制造的关键装备。迪赛福工业互联(深圳)有限公司作为国内知名精密测量机制造商,凭借深厚的技术积淀、卓越的创新能力以及高…

vi 入门教程:五分钟接管你的终端编辑器

vi 入门教程:五分钟接管你的终端编辑器 1. 背景与痛点(Why) 简单的说,vi 是一个文本编辑器。 你可能会问,现在有了 VS Code、Sublime Text 甚至 JetBrains 全家桶,为什么还要去学一个诞生于 1976 年、界面简陋、…

模拟8字轨迹

多传感器信息融合,卡尔曼滤波算法的轨迹跟踪与估计AEKF——自适应扩展卡尔曼滤波算法 AUKF——自适应无迹卡尔曼滤波算法 UKF——无迹卡尔曼滤波算法 三种不同的算法实现轨迹跟踪在轨迹跟踪的江湖里&#xff0c;传感器就像一群各怀绝技的探子——GPS报位置&#xff0c;IMU测加…

2026年度企业出海咨询公司榜单发布:企业出海哪家好?

随着中国企业全球化进入“深水区”&#xff0c;单纯的跨境卖货已无法满足企业增长需求。“企业出海咨询公司哪家好&#xff1f;” 成为了2026年出海圈的高频搜索词。企业在选择合作伙伴时&#xff0c;面临着从战略合规、品牌建设到流量变现的不同路径选择。基于市场口碑、团队背…

学长亲荐2026TOP10AI论文平台:本科生毕业论文必备测评

学长亲荐2026TOP10AI论文平台&#xff1a;本科生毕业论文必备测评 2026年AI论文平台测评&#xff1a;为何要关注这些工具&#xff1f; 随着人工智能技术的不断进步&#xff0c;AI写作工具在学术领域的应用越来越广泛。对于本科生而言&#xff0c;撰写毕业论文不仅是学业的重要环…

SpringBoot下获取resources目录下文件的常用方法

哈喽&#xff0c;大家好&#xff0c;今天给大家带来SpringBoot获取resources目录下文件的常用方法&#xff0c;示例中的方法是读取resources目录下的txt和xlsx文件&#xff0c;并将xlsx导出到excel的简单写法。完整代码放在最后。通过this.getClass()方法获取method1 - method4…

吐血推荐!8款AI论文写作软件测评:本科生毕业论文全攻略

吐血推荐&#xff01;8款AI论文写作软件测评&#xff1a;本科生毕业论文全攻略 2026年AI论文写作工具测评&#xff1a;精准筛选&#xff0c;高效助力本科毕业论文 在当前高校教育环境中&#xff0c;本科生撰写毕业论文面临着诸多挑战&#xff0c;包括选题构思困难、文献资料繁杂…

Java面试场景:互联网大厂如何考核Spring Boot与Kafka应用能力

场景&#xff1a;互联网大厂Java小白求职者面试 超好吃是一位刚毕业的Java程序员&#xff0c;今天他来到了某互联网大厂参加面试&#xff0c;面试官是技术专家刘老师。以下是他们的对话&#xff1a;第一轮问题&#xff1a;Spring Boot与Web开发基础 面试官&#xff1a; “超好吃…

第六篇:告别 setInputAction_XXX!我们给地球装上“事件总线”

View Post第六篇:告别 setInputAction_XXX!我们给地球装上“事件总线”本专栏旨在手把手带你从零开始,基于开源三维地球引擎 **Cesium** 封装一套功能完善、可复用的 **WebGIS 增强型 SDK**。内容涵盖核心封装思路、…

学习进度三:实验 3 Spark 和 Hadoop 的安装

学习进度三:实验 3 Spark 和 Hadoop 的安装1.安装 Hadoop 和 Spark2.HDFS 常用操作3. Spark 读取文件系统的数据 准备工作(1)在 spark-shell 中读取 Linux 系统本地文件“/home/hadoop/test.txt ”,然后统计出文…

209_尚硅谷_继承快速入门应用实例

209_尚硅谷_继承快速入门应用实例1.面向对象编程---快速入门案例和继承带来的便利 2.面向对象编程---案例代码 3.面向对象编程---案例输出

【软考环境架构设计师】四、信息系统基础知识

【软考环境架构设计师】四、信息系统基础知识pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &qu…

ChatGPT是怎么学会接龙的?

ChatGPT是怎么学会接龙的&#xff1f;揭秘大模型训练的第一课 你有没有想过&#xff0c;ChatGPT是怎么学会一个词接一个词地说话的&#xff1f;当你问它"今天天气怎么样"&#xff0c;它为什么能流畅地回答"今天天气晴朗&#xff0c;温度适中&#xff0c;很适合外…

wsl的网络模式有哪几种,有哪些区别?

WSL2(从WSL 2.0.0开始)提供了四种网络模式,它们在网络可见性和配置方式上有明显区别,可以根据自己的开发需求进行选择和配置。为了快速了解,我整理了一张对比表格:模式 核心描述 访问方式 典型场景NAT 默认模式。…

Java企业AI转型实录:JBoltAI破解智能问答系统开发

在AI技术浪潮的推动下&#xff0c;Java企业纷纷踏上智能化转型之路在AI技术浪潮的推动下&#xff0c;Java企业纷纷踏上智能化转型之路&#xff0c;旨在通过AI应用开发提升业务效率和用户体验。我们公司也紧跟时代步伐&#xff0c;决定开发一款智能问答系统&#xff0c;以提供更…

轻量级云文件系统simple-file-server,电脑秒变存储服务器

Simple File Server 一个简单的文件服务器&#xff0c;使用 Go 和 Gin 框架构建&#xff0c;支持文件上传、下载和静态文件服务。 功能特性 文件上传&#xff1a;支持普通文件上传和分片上传&#xff08;multipart upload&#xff09; 文件下载&#xff1a;通过 HTTP GET 请…

JBoltAI的AI应用中台:构建企业智能化的坚实基础

在当今数字化与智能化交织的时代&#xff0c;企业对于AI技术的需求日益增长&#xff0c;如何高效、稳定地集成AI能力成为企业转型的关键。JBoltAI的AI应用中台&#xff0c;作为企业智能化的重要基础设施&#xff0c;不仅为Java生态下的AI应用开发提供了强有力的支撑&#xff0c…

企业上云转型的 “压舱石”—— 云服务器如何破解中小微企业数字化痛点​

​在数字经济加速渗透的今天&#xff0c;中小微企业的数字化转型不再是 “选择题”&#xff0c;而是 “生存题”。但资金有限、技术人才匮乏、运维能力薄弱等现实困境&#xff0c;让众多企业在数字化门口望而却步。云服务器的出现&#xff0c;以 “按需付费、弹性伸缩、简化运维…

基于逻辑回归模型的贷款违约预测(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码

基于逻辑回归模型的贷款违约预测(设计源文件万字报告讲解)&#xff08;支持资料、图片参考_相关定制&#xff09;_文章底部可以扫码 Python大数据分析商业分析商业数据分析机器学习数据可视化 jupyter数据分析项目 [绿圆]贷款违约预测 [绿圆]逻辑回归模型 Python分析报告项目&a…