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

【深度学习】【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 关联更新优化方法

关联更新顾名思义就是指&#xff0c;更新的数据从关联的表中获取并update到目标表。并且该SQL将会是一个天然的嵌套循环。有两种优化思路解决&#xff1a; 1、PLSQL 根据rowid更新 是否需要加order by rowid的考量&#xff1a; 如果buffer cache足够大&#xff0c;能够放得下要…...

USB协议学习(一)帧格式以及协议抓取

USB协议学习&#xff08;一&#xff09;帧格式以及协议抓取 笔者来聊聊MPU的理解 这里写自定义目录标题 USB协议学习&#xff08;一&#xff09;帧格式以及协议抓取MPU的概念以及作用MPU的配置新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式…...

前端工程化知识系列(8)

目录 71.你有经验使用TypeScript或Flow等类型检查工具来提高前端代码的可维护性和质量吗&#xff1f;72. 如何处理前端应用的搜索引擎优化&#xff08;SEO&#xff09;问题&#xff0c;特别是在单页面应用&#xff08;SPA&#xff09;中&#xff1f;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高层火灾应急疏散演练提供一种无风险的逃生体验

在科技进步的今天&#xff0c;我们已经能够利用虚拟现实&#xff08;VR&#xff09;技术来模拟各种紧急情况&#xff0c;其中就包括高楼火灾逃生。VR高层火灾应急疏散演练系统是一种新兴的技术&#xff0c;它使用虚拟现实环境来模拟高楼火灾的实际情况&#xff0c;为人们提供一…...

定档通知2024中国(上海)国际品牌叉车展览会

时 间&#xff1a;2024年7月24&#xff5e;26日 地 点&#xff1a;上海国家会展中心 ◆ 》》》展会概况&#xff1a; 叉车在“搬运设备”中扮演着非常重要的角色&#xff0c;是机械化装卸、堆垛和短距离运输的高效设备。近年来&#xff0c;在“节能环保&#xff0c…...

Ubuntu编译安装colmap遇到的几个问题以及解决

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

【Qt上位机】打开本地表格文件并获取其中全部数据

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

香港服务器选纯国际线路上网稳定吗?

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

USB PD3.1

目前我们大多数Type-C接口仍然采用的是PD3.0快充协议&#xff0c;按当前用户的使用场景来看功率也完全够用&#xff0c;那么PD3.1快充协议是什么&#xff1f;USB PD3.1到底有没有必要&#xff1f; 不妨我们先了解一下PD3.1: 5月25日&#xff0c;USB-IF协会推出了USB Type-C线…...

unity面试八股文 - 基础篇

委托是什么? event 关键字有什么用&#xff1f; 委托&#xff1a; 委托是一种特殊类型的对象&#xff0c;它包含了对一个方法的引用。简单来说&#xff0c;委托就像是一个安全的函数指针。它允许我们创建可在运行时动态更改其引用方法的变量&#xff0c;并且可以指向类中定义…...

构建高效问题解答平台:使用Cpolar和Tipas在Ubuntu上搭建专属问答网站

文章目录 前言2.Tipask网站搭建2.1 Tipask网站下载和安装2.2 Tipask网页测试2.3 cpolar的安装和注册 3. 本地网页发布3.1 Cpolar临时数据隧道3.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;3.3 Cpolar稳定隧道&#xff08;本地设置&#xff09; 4. 公网访问测试5. 结语 前…...

前馈型BP神经网络

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

数据库实验一:学生信息管理系统数据库结构搭建和表的创建

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

解决 vscode使用Prettier格式化js文件报错:Cannot find module ‘./parser-babylon‘

报错如下&#xff1a; ["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…...

汉服商城小程序的作用是什么

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

9月大型语言模型研究论文总结

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

微信小程序--小程序框架

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

Java 全栈体系(三)

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

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

【JVM】- 内存结构

引言 JVM&#xff1a;Java Virtual Machine 定义&#xff1a;Java虚拟机&#xff0c;Java二进制字节码的运行环境好处&#xff1a; 一次编写&#xff0c;到处运行自动内存管理&#xff0c;垃圾回收的功能数组下标越界检查&#xff08;会抛异常&#xff0c;不会覆盖到其他代码…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

HDFS分布式存储 zookeeper

hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架&#xff0c;允许使用简单的变成模型跨计算机对大型集群进行分布式处理&#xff08;1.海量的数据存储 2.海量数据的计算&#xff09;Hadoop核心组件 hdfs&#xff08;分布式文件存储系统&#xff09;&a…...

MySQL 部分重点知识篇

一、数据库对象 1. 主键 定义 &#xff1a;主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 &#xff1a;确保数据的完整性&#xff0c;便于数据的查询和管理。 示例 &#xff1a;在学生信息表中&#xff0c;学号可以作为主键&#xff…...