【深度学习】【Opencv】【GPU】python/C++调用onnx模型【基础】
【深度学习】【Opencv】【GPU】python/C++调用onnx模型【基础】
提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论
文章目录
- 【深度学习】【Opencv】【GPU】python/C++调用onnx模型【基础】
- 前言
- Python版本OpenCV
- Windows平台安装OpenCV
- opencv调用onnx模型
- C++版本OpenCV_GPU
- Windows平台编译安装OpenCV
- opencv调用onnx模型
- 总结
前言
OpenCV是一个基于BSD许可发行的跨平台计算机视觉和机器学习软件库(开源),可以运行在Linux、Windows、Android和Mac OS操作系统上。可以将pytorch中训练好的模型使用ONNX导出,再使用opencv中的dnn模块直接进行加载使用。
系列学习目录:
【CPU】Pytorch模型转ONNX模型流程详解
【GPU】Pytorch模型转ONNX格式流程详解
【ONNX模型】快速部署
【ONNX模型】多线程快速部署
【ONNX模型】opencv_cpu调用onnx
【ONNX模型】opencv_gpu调用onnx
Python版本OpenCV
Windows平台安装OpenCV
博主在win10环境下装anaconda环境,而后搭建onnx模型运行所需的openCV环境。
# 搭建opencv环境
conda create -n opencv_onnx_gpu python=3.10.9 -y
# 激活环境
activate opencv_onnx_gpu
博主使用opencv-4.8.0版本,GPU版本不能直接通过pip下载安装进行使用,必须要在本地进行编译。编译过程具体参考博主的博文windows10下opencv4.8.0-cuda Python版本源码编译教程。
import cv2
cv2.__version__
opencv调用onnx模型
随便拷贝一组数据用来测试数据GPU版本相比于CPU版本在速度上的提升。在项目路径下博主拷贝了CAMO数据集。
将PFNet.onnx也拷贝到项目路径下。
使用opencv并调用gpu完成了整个推理流程。
import cv2
import numpy as np
import glob
import os
import timedef readImagesInFolder(folderPath,images):fileNames = glob.glob(os.path.join(folderPath, '*.jpg'))for fileName in fileNames:bgrImage = cv2.imread(fileName, cv2.IMREAD_COLOR)if bgrImage is not None:rgbImage = cv2.cvtColor(bgrImage, cv2.COLOR_BGR2RGB)images.append(rgbImage)def transformation(image, targetSize, mean, std):resizedImage = cv2.resize(image, targetSize, interpolation=cv2.INTER_AREA)normalized = resizedImage.astype(np.float32)normalized /= 255.0normalized -= meannormalized /= stdreturn normalizeddef loadModel(onnx_path):net = cv2.dnn.readNetFromONNX(onnx_path)return netdef main():# 图片存放文件路径folderPath = "D:/deeplean_demo/opencv_onnx_gpu/CAMO/c"rgbImages = []readImagesInFolder(folderPath, rgbImages)# 加载ONNX模型onnx_path = "D:/deeplean_demo/opencv_onnx_gpu/PFNet.onnx"net = loadModel(onnx_path)# 设置CUDA为后端# net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)# net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)output_probs = []output_layer_names = net.getUnconnectedOutLayersNames()# 定义目标图像大小target_size = (416, 416)# 定义每个通道的归一化参数mean = (0.485, 0.456, 0.406) # 均值std = (0.229, 0.224, 0.225) # 标准差# 开始计时start = time.time()for rgb_image in rgbImages:# 获取图像的大小original_size = (rgb_image.shape[1], rgb_image.shape[0])# 图片归一化normalized = transformation(rgb_image, target_size, mean, std)print(normalized.shape[:2])blob = cv2.dnn.blobFromImage(normalized)# 将Blob设置为模型的输入net.setInput(blob)# 运行前向传播output_probs = net.forward(output_layer_names)# 获取最完整的预测prediction = output_probs[3]# 预测图变maskmask = cv2.resize(np.squeeze(prediction)* 255.0, original_size, interpolation=cv2.INTER_AREA)end = time.time()# 计算耗时elapsed_time = end - start# 打印耗时print("Elapsed time:", elapsed_time, "seconds")if __name__ == "__main__":main()
gpu模式下250张图片只用了大约13秒。
假设注释掉与gou相关的代码
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)
cpu模式下250张图片就用了大约95秒。
C++版本OpenCV_GPU
Windows平台编译安装OpenCV
博主使用opencv-4.8.0版本,GPU版本不能直接通过官网下载exe进行使用,必须要在本地进行编译。编译过程具体参考博主的博文【windows10下opencv4.8.0-cuda C++版本源码编译教程】。
编译完成后,在输出的文件夹内找到install文件,将其拷贝合适的位置。
博主新建了一个名为opencv_gpu的文件夹,并将install重命名位build放在其中。
打开VS 2019:新建新项目---->空项目---->配置项目---->项目路径以及勾选“将解决方案和项目放在同一目录中---->点击创建。
在解决方案–>源文件–>右键添加新建项。这里暂时可以默认空着不做处理。
设置OpenCV路径:项目---->属性。假设没有新建cpp文件,空项目的属性页就不会存在C/C++这一项目。
添加附加包含目录:Release | x64---->C/C+±—>常规---->附加包含目录。
D:\C++_demo\opencv_gpu\build\x64\vc16\bin
D:\C++_demo\opencv_gpu\build\bin
D:\C++_demo\opencv_gpu\build\include
D:\C++_demo\opencv_gpu\build\include\opencv2
链接器:Release | x64---->链接器---->常规---->附加包含目录。
D:\C++_demo\opencv_gpu\build\x64\vc16\lib
链接器:Release | x64---->链接器---->输入---->附加依赖项。
在D:\C++_demo\opencv_gpu\build\x64\vc16\lib下找到附加依赖项的文件。
opencv_world480.lib
在Release x64模式下测试,将opencv_world480.dll文件复制到自己项目的Release下。
没有Release目录时,需要在Release | x64模式下运行一遍代码,代码部分在下一节提供,读者可以先行新建文件复制代码。
D:\C++_demo\opencv_gpu\build\x64\vc16\bin
===>
D:\C++_demo\opencv_onnx_gpu\x64\Releas
这里博主为了方便安装的是release版本的,读者可以安装debug版本的,流程基本一致,只需要将属性的Release | x64变成Debug | x64,然后附加依赖项由opencv_world480.lib变成opencv_world480d.lib,再将opencv_world480d.dll文件复制到自己项目的Release下。前提是你编译了debug版本oepncv。
opencv调用onnx模型
随便拷贝一组数据用来测试数据GPU版本相比于CPU版本在速度上的提升。在项目路径下博主拷贝了CAMO数据集。
将PFNet.onnx也拷贝到项目路径下。
将python版本的opencv转化成对应的c++版本的,发现输出的效果完全一致,onnx模型可以作为c++的接口来供其他应用调用。
#include <iostream>
#include <string>
#include <vector>
#include<opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
using namespace std;
void readImagesInFolder(const std::string& folderPath, std::vector<cv::Mat>& images)
{cv::String path(folderPath + "/*.jpg"); // 这里假设你的图片格式是.jpg,如果是其他格式请相应修改std::vector<cv::String> fileNames;cv::glob(path, fileNames, true); // 通过glob函数获取文件夹内所有符合格式的文件名cv::Mat rgbImage;for (const auto& fileName : fileNames){ // 使用imread函数读取图片cv::Mat bgrImage = cv::imread(fileName, cv::IMREAD_COLOR); // 图片格式转化bgr-->rgbif (!bgrImage.empty()){cv::cvtColor(bgrImage, rgbImage, cv::COLOR_BGR2RGB);images.push_back(rgbImage);}}
}cv::Mat transformation(const cv::Mat& image, const cv::Size & targetSize, const cv::Scalar& mean, const cv::Scalar& std) {cv::Mat resizedImage;//图片尺寸缩放cv::resize(image, resizedImage, targetSize, 0, 0, cv::INTER_AREA);cv::Mat normalized;resizedImage.convertTo(normalized, CV_32F);cv::subtract(normalized / 255.0, mean, normalized);cv::divide(normalized, std, normalized);return normalized;
}
cv::dnn::Net loadModel(const string& onnx_path) {cv::dnn::Net net = cv::dnn::readNetFromONNX(onnx_path);return net;
}
int main()
{ // 图片存放文件路径string folderPath = "D:/C++_demo/opencv_onnx_gpu/CAMO/c";std::vector<cv::Mat> rgbImages;readImagesInFolder(folderPath, rgbImages);// string image_path = "./animal-1.jpg";// 加载ONNX模型string onnx_path = "D:/C++_demo/opencv_onnx_gpu/PFNet.onnx";cv::dnn::Net net = loadModel(onnx_path);// 设置CUDA为后端net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);cv::Mat output_prob;std::vector<cv::Mat> output_probs;std::vector<cv::String> output_layer_names = net.getUnconnectedOutLayersNames();// 定义目标图像大小cv::Size targetSize(416, 416);// 定义每个通道的归一化参数cv::Scalar mean(0.485, 0.456, 0.406); // 均值cv::Scalar std(0.229, 0.224, 0.225); // 标准差// 开始计时auto start = chrono::high_resolution_clock::now();for (const auto& rgbImage : rgbImages) {// 获取图像的大小cv::Size originalSize(rgbImage.cols, rgbImage.rows);//cv::imshow("输入窗口", rgbImage);//cv::waitKey(0);//cv::destroyAllWindows();// 图片归一化cv::Mat normalized = transformation(rgbImage, targetSize, mean, std);std::cout << normalized.size() << std::endl;cv::Mat blob = cv::dnn::blobFromImage(normalized);// 将Blob设置为模型的输入net.setInput(blob);// 运行前向传播net.forward(output_probs, output_layer_names);// 获取最完整的预测cv::Mat prediction = output_probs[3];// 预测图变maskcv::Mat mask;cv::resize(prediction.reshape(1, 416) * 255.0, mask, originalSize, 0, 0, cv::INTER_AREA);}auto end = std::chrono::high_resolution_clock::now();// 计算耗时std::chrono::duration<double> elapsed = end - start;double elapsedTime = elapsed.count();// 打印耗时std::cout << "Elapsed time: " << elapsedTime << " seconds" << std::endl;return 0;
}
gpu模式下250张图片只用了大约16秒。
假设注释掉与gou相关的代码
net.setPreferableBackend(cv::dnn::DNN_BACKEND_CUDA);
net.setPreferableTarget(cv::dnn::DNN_TARGET_CUDA);
cpu模式下250张图片就用了大约95秒。
总结
尽可能简单、详细的介绍Python和C++下Opencv_GPU调用ONNX模型的流程。
相关文章:

【深度学习】【Opencv】【GPU】python/C++调用onnx模型【基础】
【深度学习】【Opencv】【GPU】python/C调用onnx模型【基础】 提示:博主取舍了很多大佬的博文并亲测有效,分享笔记邀大家共同学习讨论 文章目录 【深度学习】【Opencv】【GPU】python/C调用onnx模型【基础】前言Python版本OpenCVWindows平台安装OpenCVopencv调用onnx模型 C版本…...

Oracle update 关联更新优化方法
关联更新顾名思义就是指,更新的数据从关联的表中获取并update到目标表。并且该SQL将会是一个天然的嵌套循环。有两种优化思路解决: 1、PLSQL 根据rowid更新 是否需要加order by rowid的考量: 如果buffer cache足够大,能够放得下要…...
USB协议学习(一)帧格式以及协议抓取
USB协议学习(一)帧格式以及协议抓取 笔者来聊聊MPU的理解 这里写自定义目录标题 USB协议学习(一)帧格式以及协议抓取MPU的概念以及作用MPU的配置新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式…...
前端工程化知识系列(8)
目录 71.你有经验使用TypeScript或Flow等类型检查工具来提高前端代码的可维护性和质量吗?72. 如何处理前端应用的搜索引擎优化(SEO)问题,特别是在单页面应用(SPA)中?73. 你了解渐进式Web应用&am…...

UnrealEngine iOS 打包 —— 签名证书(cer、p12)生成
官方文档 docs.unrealengine.com/5.3/zh-CN/setting-up-ios-tvos-and-ipados-provisioning-profiles-and-signing-certificates-for-unreal-engine-projects 打开 ProjectSettings -> Platforms -> iOS 可以看到签名证书配置 需要拓展名为 .cer 和 .p12 的一对证书和密钥…...

【广州华锐互动】VR高层火灾应急疏散演练提供一种无风险的逃生体验
在科技进步的今天,我们已经能够利用虚拟现实(VR)技术来模拟各种紧急情况,其中就包括高楼火灾逃生。VR高层火灾应急疏散演练系统是一种新兴的技术,它使用虚拟现实环境来模拟高楼火灾的实际情况,为人们提供一…...
定档通知2024中国(上海)国际品牌叉车展览会
时 间:2024年7月24~26日 地 点:上海国家会展中心 ◆ 》》》展会概况: 叉车在“搬运设备”中扮演着非常重要的角色,是机械化装卸、堆垛和短距离运输的高效设备。近年来,在“节能环保,…...

Ubuntu编译安装colmap遇到的几个问题以及解决
总体安装过程已经很明白了,写的人很多了,我就不赘述了,可以参考这里或者其他博客。我主要记录几个我遇到的问题以及解决方法。 1、cmake报错:No CMAKE_CUDA_COMPILER could be found. 这个原因是没找到cuda和nvcc目录࿰…...

【Qt上位机】打开本地表格文件并获取其中全部数据
前言 其实本文所实现的功能并非博主要实现的全部功能,只是全部功能中的一小部分,这里只是为了记录一下实现方法,防止后续忘记,仅供参考。 文章目录 一、实现效果二、UI设计三、程序设计3.1 选择本地表格文件3.2 获取表格总行列数3…...

香港服务器选纯国际线路上网稳定吗?
关于香港服务器的线路,我们平时接触较多的分三大类,即纯国际线路、回国专线和香港本地线路。三者价格上存有差距,原因体现在线路和网络质量上,当然这些会关系到服务器的速度和稳定性。譬如,有些用户在选择了纯国…...

USB PD3.1
目前我们大多数Type-C接口仍然采用的是PD3.0快充协议,按当前用户的使用场景来看功率也完全够用,那么PD3.1快充协议是什么?USB PD3.1到底有没有必要? 不妨我们先了解一下PD3.1: 5月25日,USB-IF协会推出了USB Type-C线…...
unity面试八股文 - 基础篇
委托是什么? event 关键字有什么用? 委托: 委托是一种特殊类型的对象,它包含了对一个方法的引用。简单来说,委托就像是一个安全的函数指针。它允许我们创建可在运行时动态更改其引用方法的变量,并且可以指向类中定义…...

构建高效问题解答平台:使用Cpolar和Tipas在Ubuntu上搭建专属问答网站
文章目录 前言2.Tipask网站搭建2.1 Tipask网站下载和安装2.2 Tipask网页测试2.3 cpolar的安装和注册 3. 本地网页发布3.1 Cpolar临时数据隧道3.2 Cpolar稳定隧道(云端设置)3.3 Cpolar稳定隧道(本地设置) 4. 公网访问测试5. 结语 前…...

前馈型BP神经网络
1.感知机和激活函数 感知机,是构成神经网络的基本单位,一个感知机可以接收n个输入X(x1,x2,x3…xn)T(每个输入,可以理解为一种特征),n个输入对应n个权值W(w1,w2,w3…wn),此外还有一个偏置项b&am…...

数据库实验一:学生信息管理系统数据库结构搭建和表的创建
实验项目名称:学生信息管理系统数据库结构搭建和表的创建 实验目的与要求实验原理与内容1. 数据库的组织结构2. 数据库的分离和附加3. 数据库表的创建,修改和删除 实验过程与结果1. 根据学生信息管理系统创建相关的数据库2. 数据库表初步设计及实现3. 实…...

解决 vscode使用Prettier格式化js文件报错:Cannot find module ‘./parser-babylon‘
报错如下: ["ERROR" - 11:48:58] Error formatting document. ["ERROR" - 11:48:58] Cannot find module ./parser-babylon Require stack: - d:\VueCode\VueProject\myqqmusic\node_modules\prettier\index.js - c:\Users\Administrator.SKY-2…...

汉服商城小程序的作用是什么
汉服在日常生活中越来越常见,大街小巷也有不少年轻人装扮甚是漂亮帅气,有些地区甚至还有相关的比赛等,作为近几年曝光的服饰,汉服市场规模持续增加中,各地线上线下商家也多了起来。 然而在实际经营中,汉服…...

9月大型语言模型研究论文总结
大型语言模型(llm)在今年发展迅速,随着新一代模型不断地被开发,研究人员和工程师了解最新进展变得非常重要。本文总结9-10月期间发布了一些重要的LLM论文。 这些论文涵盖了一系列语言模型的主题,从模型优化和缩放到推理、基准测试和增强性能…...

微信小程序--小程序框架
目录 前言: 一.框架基本介绍 1.整体结构: 2.页面结构: 3.生命周期: 4.事件系统: 5.数据绑定: 6.组件系统: 7.API: 8.路由: 9.模块化: 10.全局配置&…...

Java 全栈体系(三)
第一章 Java 基础语法 八、标识符 业内大多数程序员都在遵守阿里巴巴的命名规则。 1. 硬性要求 必须要这么做,否则代码会报错。 必须由数字、字母、下划线_、美元符号$组成。数字不能开头不能是关键字区分大小写的。 2. 软性建议 如果不这么做,代…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
Java如何权衡是使用无序的数组还是有序的数组
在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
Kafka主题运维全指南:从基础配置到故障处理
#作者:张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1:主题删除失败。常见错误2:__consumer_offsets占用太多的磁盘。 主题日常管理 …...