当前位置: 首页 > news >正文

新版OpenCV5.0在ONNX模型的推理应用

1、OpenCV5.0的新特性

OpenCV5 是架构级大改版,彻底清理老旧 C 接口、重写 DNN 推理引擎、原生支持视觉大模型、硬件加速体系重构,最低编译标准升级至 C++17。

1.1 ONNX应用新特性

DNN 深度学习引擎是OpenCV5.0版本的最大升级。主要新特性如下:

1)全新自研推理引擎双引擎共存
新引擎默认自动启用,兼容动态输入 shape、复杂子图、现代 ONNX 算子;旧经典引擎可手动降级兼容老模型
ONNX算子覆盖率从 4.x 的22% 暴涨至 80%+,YOLO、SAM、LLaVA、ResNet、Diffusion 等主流模型直接导入无压力

移除老旧 Caffe、Darknet 模型解析器,全面转向 ONNX 标准格式
2)原生支持 VLM 视觉语言大模型
内置 Tokenizer、Attention、KV 缓存、解码模块,可直接部署看图问答、图像描述类多模态模型(LLaVA 等),不用额外套推理框架
3)推理加速扩展
可对接 ONNX Runtime 后端;CPU 矢量优化大幅提速,GPU/CUDA 支持后续迭代补齐;支持量化 INT8/FP16 轻量化推理。

1.2 语言与编译底层大清理

1) 彻底废弃 C 语言 API
所有旧版cvCreateImage、cvMat等 C 接口全部移除,仅保留现代 C++、Python 绑定,代码体积大幅精简
2)C++ 最低标准强制 C++17
全面使用 std 智能指针、 constexpr、结构化绑定等现代语法,内存管理更安全,消除大量兼容宏代码
3)Python 绑定全面现代化
支持命名参数传参,不用死记函数参数顺序
类型对齐 NumPy,无隐式转换 bug;异常报错信息精准易懂
pip 一键分包:opencv-python基础、opencv-contrib-python扩展模块,版本严格锁死 5.0.0
4)新增多语言绑定:Swift、Julia 官方支持完善.

和OpenCV4.x比较如下表所示:

维度OpenCV 4.xOpenCV 5.0
C 接口兼容保留彻底删除
C++ 标准C++11 起步强制 C++17
ONNX 覆盖~22%>80%
大模型仅 CNN 检测VLM 多模态原生支持
硬件加速碎片化 ifdef统一 HAL 插件架构
FLANN独立模块内置 Annoy 替代

2 下载及安装

OpenCV5.0下载地址为:https://github.com/opencv/opencv/releases

下载页面如下图所示:

按上图下载opencv-5.0.0-windows.exe并解压

3.Qt5.12环境下读取图像并显示

我用的Qt5.12环境采用的编译器为VS2017,QT的pro文件配置主要要设置成C++ 17,注意包含的头文件和库文件。如下图所示:

#CONFIG += c++11 CONFIG += c++17 SOURCES += \ main.cpp \ mainwindow.cpp HEADERS += \ mainwindow.h FORMS += \ mainwindow.ui #Added By Lzy # OpenCV5.0 路径,改成你本地实际路径 #OPENCV_PATH = D:/opencv480/build OPENCV_PATH = D:/opencv500/build INCLUDEPATH += $${OPENCV_PATH}/include LIBS += -L$${OPENCV_PATH}/x64/vc16/lib \ #-lopencv_world480 -lopencv_world500

部署推理的代码如下图所示

// 定义检测结果结构体 struct Detection { int class_id; float confidence; cv::Rect box; }; // 1. 参数配置 const std::string model_path = "Onnx/best.onnx"; const std::string image_path = "./11.jpg"; const float conf_threshold = 0.25f; const float nms_threshold = 0.45f; const cv::Size target_size(640, 640); std::vector<std::string> class_names = {"Node"}; cv::dnn::Net net; // 图像等比例缩放平铺(Letterbox)预处理,使检测更精准 cv::Mat letterbox(const cv::Mat& source, cv::Size target_size, cv::Scalar bg_color = cv::Scalar(114, 114, 114)) { int col = source.cols; int row = source.rows; float _max = std::max(col, row); cv::Mat result = cv::Mat::zeros(_max, _max, CV_8UC3); result.setTo(bg_color); source.copyTo(result(cv::Rect(0, 0, col, row))); cv::Mat resized; cv::resize(result, resized, target_size); return resized; } // static bool bFlag=true; // 2. 加载模型 (OpenCV 5.0.0 深度优化了 readNet 引擎) if(bFlag) { net = cv::dnn::readNet(model_path); bFlag=false; } // 如果有 NVIDIA CUDA 环境,取消注释以下两行以开启硬件加速 // net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA); // net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA); // 3. 读取并预处理图像 cv::Mat frame = cv::imread(image_path); if (frame.empty()) { std::cerr << "无法读取图像: " << image_path << std::endl; return ; } // 缩放到 640x640 cv::Mat letterbox_img = letterbox(frame, target_size); // 计算原始尺寸到缩放尺寸的比例,用于恢复坐标边界框 float scale = std::max(frame.cols, frame.rows) / 640.0f; // 创建模型的输入 Blob (YOLO 标准:像素值除以 255.0,交换 R 与 B 通道) cv::Mat blob; cv::dnn::blobFromImage(letterbox_img, blob, 1.0 / 255.0, target_size, cv::Scalar(), true, false); net.setInput(blob); // 4. 前向推理 std::vector<cv::Mat> outputs; net.forward(outputs, net.getUnconnectedOutLayersNames()); // 5. 解析输出 (YOLOv11 输出形状为 [1, 84, 8400]) cv::Mat raw_data = outputs[0]; raw_data = raw_data.reshape(1, raw_data.size[1]); // 变更为 84 x 8400 的 2D 矩阵 cv::transpose(raw_data, raw_data); // 转置为 8400 x 84 float* data = (float*)raw_data.data; int rows = raw_data.rows; // 8400 个候选框 int dimensions = raw_data.cols; // 84 (4个坐标 + 80个类别置信度) int num_classes = dimensions - 4; std::vector<int> class_ids; std::vector<float> confidences; std::vector<cv::Rect> boxes; for (int i = 0; i < rows; ++i) { // 指向当前候选框的置信度起始位置 float* classes_scores = data + 4; // 寻找最大置信度的类别 cv::Mat scores(1, num_classes, CV_32FC1, classes_scores); cv::Point class_id_point; double max_class_socre; cv::minMaxLoc(scores, 0, &max_class_socre, 0, &class_id_point); if (max_class_socre > conf_threshold) { // 提取中心坐标及宽高 (x_center, y_center, width, height) float cx = data[0]; float cy = data[1]; float w = data[2]; float h = data[3]; // 转换成左上角坐标,并映射回原图尺寸 int left = static_cast<int>((cx - 0.5 * w) * scale); int top = static_cast<int>((cy - 0.5 * h) * scale); int width = static_cast<int>(w * scale); int height = static_cast<int>(h * scale); class_ids.push_back(class_id_point.x); confidences.push_back(static_cast<float>(max_class_socre)); boxes.push_back(cv::Rect(left, top, width, height)); } data += dimensions; // 跳到下一个候选框 } // 6. 执行非极大值抑制 (NMS) 过滤重叠框 std::vector<int> nms_indices; cv::dnn::NMSBoxes(boxes, confidences, conf_threshold, nms_threshold, nms_indices); // 7. 绘制检测框 for (int idx : nms_indices) { cv::Rect box = boxes[idx]; float conf = confidences[idx]; int class_id = class_ids[idx]; // 边界限制,防止框超出图片范围 box.x = std::max(0, box.x); box.y = std::max(0, box.y); box.width = std::min(box.width, frame.cols - box.x); box.height = std::min(box.height, frame.rows - box.y); // 绘制目标框 cv::rectangle(frame, box, cv::Scalar(0, 255, 0), 2); // 绘制置信度标签 std::string label =/* "Class " + std::to_string(class_id)*/ class_names[class_id]+ ": " + cv::format("%.2f", conf); int baseLine; cv::Size label_size = cv::getTextSize(label, cv::FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine); cv::rectangle(frame, cv::Point(box.x, box.y - label_size.height), cv::Point(box.x + label_size.width, box.y + baseLine), cv::Scalar(0, 255, 0), cv::FILLED); cv::putText(frame, label, cv::Point(box.x, box.y), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 0), 1); } // 8. 展示与保存结果 //cv::imshow("YOLOv11 OpenCV5.0 C++ Detection", frame); //cv::imwrite("result.jpg", frame); //cv::waitKey(0); QImage qImg = cvMat2QImage(frame); QPixmap pix = QPixmap::fromImage(qImg); // 自适应缩放,保持比例 pix = pix.scaled(ui->labelShow->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); ui->labelShow->setPixmap(pix);

运行效果如下:

切换不同的OpenCV4.8.0和OpenCV5.0.0库编译及推理测试结果如下:

OpenCV4.8.0平均推理耗时421ms

OpenCV5.0.0平均推理耗时265ms

可见OpenCV5.0对推理速度进行了优化。

http://www.jsqmd.com/news/996445/

相关文章:

  • 2026年比较好的工厂临建打包箱/新疆打包箱房横向对比厂家推荐 - 行业平台推荐
  • 你的PRBS生成器够快吗?聊聊并行化在SerDes测试中的性能优化技巧
  • AI Agent 的Human-in-the-Loop工程实践:何时停下来问人,如何设计ApprovalFlow
  • 老师制作上课课件怎么选?2026年5款文字转语音在线工具,满足不同授课音频需求
  • Adapter Tuning实战:如何像搭乐高一样,为你的大模型添加可插拔的‘技能模块’?
  • 063、Skill 调试与版本管理:更新策略、兼容性处理、测试与回归验证
  • 2026年成都租车行业观察:商务接待与川西川藏线用车如何选? - 优质品牌商家
  • 数字示波器参数大全:从入门到精通(九)
  • Microchip USB Hub配置实战:如何让你的集线器变身多协议快充站(支持BC1.2/CDP/DCP/SE1)
  • 2026年PPT转PDF保姆级教程:PowerPoint和WPS详细操作指南
  • 终极猫抓资源嗅探指南:3步快速搞定网页视频音频下载
  • 从STL算法到现代C++:Lambda捕获列表[ ]、[=]、[]的进阶玩法与性能考量
  • FPGA HDMI输出避坑指南:搞懂OSERDESE2级联与TMDS直流平衡,告别屏幕花屏
  • 2026年桥架厂家综合实力评价:技术、交付与服务全景分析 - 优质品牌商家
  • 告别‘糊’图:手把手调优你的立体匹配模型,用高频信息提升AR渲染与避障精度
  • MyBatis 中,#{} 和 ${}的区别
  • 从钢琴键盘到五线谱:手把手教你‘数’出A大调为什么是三个升号(附调号推导实战)
  • AI巨头激战:Claude神话版与GPT5.6对决,这周模型圈太炸了
  • Unix垃圾回收器重制版:重写过程、漏洞分析与复现方法揭秘
  • Windows虚拟网络声卡Scream:轻松实现局域网音频传输的完整教程
  • 从ChatGPT到芯片验证:AI如何‘读懂’SystemVerilog代码并帮你找Bug?
  • AI能预测下一条谣言吗?网络谣言传播背后的技术攻防战
  • 从零构建企业级网络监控:LibreNMS实战部署与核心功能解析
  • 5大核心功能:League Akari如何成为英雄联盟玩家的智能游戏助手
  • 2026年宜宾全屋定制品牌怎么选?从环保板材到五行美学,六家本地企业深度解析! - 优质品牌商家
  • 064、社区 Skill 最佳实践:代码审查、安全审查、测试驱动开发的技能化
  • Wan2.2-VAE:16×16×4高效压缩技术的终极指南
  • 深入拆解:连续J/F-1模式Doherty功放中的ZTC与Zpmn网络,如何用ADS进行阻抗控制与谐波优化?
  • Fiddler抓取HTTPS请求数据乱码问题的完整解决方案与步骤指南
  • NDS游戏资源编辑终极指南:如何使用Tinke零基础提取和修改任天堂DS游戏文件