【深度学习】【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函数获取文件夹内所有符合格式的文件名for (const auto& fileName : fileNames){   // 使用imread函数读取图片cv::Mat bgrImage = cv::imread(fileName, cv::IMREAD_COLOR); // 图片格式转化bgr-->rgbif (!bgrImage.empty()){	cv::Mat rgbImage;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模型的流程。

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

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

相关文章

vue 自定义指令

vue 自定义指令 指令 和mounted 是什么关系 &#xff1f; **创建 工程&#xff1a; H:\java_work\java_springboot\vue_study ctrl按住不放 右键 悬着 powershell H:\java_work\java_springboot\js_study\Vue2_3入门到实战-配套资料\01-随堂代码素材\day05\准备代码\04-自定…

反转链表(java)

大家好我是苏麟今天说一说链表常见的简单题目 . BM1 反转链表 牛客BM1 反转链表 : 描述 : 给定一个单链表的头结点(该头节点是有值的&#xff0c;比如在下图&#xff0c;它的val是1)&#xff0c;长度为n&#xff0c;反转该链表后&#xff0c;返回新链表的表头。 分析 : …

云上攻防-云原生篇K8s安全Config泄漏Etcd存储Dashboard鉴权Proxy暴露

文章目录 云原生-K8s安全-etcd未授权访问云原生-K8s安全-Dashboard未授权访问云原生-K8s安全-Configfile鉴权文件泄漏云原生-K8s安全-Kubectl Proxy不安全配置 云原生-K8s安全-etcd未授权访问 攻击2379端口&#xff1a;默认通过证书认证&#xff0c;主要存放节点的数据&#x…

【Linux-常用命令-基础命令-复制-copy-命令-笔记】

【Linux-常用命令-基础命令-复制文件-copy-命令-笔记】 1、前言2、操作3、自己的实践 1、前言 最近&#xff0c;在使用Linux的时&#xff0c;使用相关基础命令是&#xff0c;总是容易忘记&#xff0c;上网一搜&#xff0c;大部分都写的比较繁琐&#xff0c;我就找下复制命令&a…

Anylogic 读取和写入Excel文件

1、选择面板-连接-Excel文件&#xff0c;拖入到视图中 然后在excel文件的属性中进行绑定外部excel文件。 绑定完之后&#xff0c;在你需要读取的地方进行写代码&#xff0c; //定义开始读取的行数 //这里设为2&#xff0c;是因为第一行是数据名称 int row12; //读取excel文件信…

[开源]MIT开源协议,基于Vue3.x可视化拖拽编辑,页面生成工具

一、开源项目简介 AS-Editor 基于 Vue3.x 可视化拖拽编辑&#xff0c;页面生成工具。提升前端开发效率&#xff0c;可集成至移动端项目作为通过定义 JSON 直接生成 UI 界面。 二、开源协议 使用MIT开源协议 三、界面展示 四、功能概述 基于Vue可视化拖拽编辑&#xff0c;…

Web3 整理React项目 导入Web3 并获取区块链信息

上文 WEB3 创建React前端Dapp环境并整合solidity项目&#xff0c;融合项目结构便捷前端拿取合约 Abi 我们用react 创建了一个 dapp 项目 并将前后端代码做了个整合 那么 我们就来好好整理一下 我们的前端react的项目结构 我们在 src 目录下创建一个 components 用来存放我们的…

视频怎么压缩?视频太大这样处理变小

在当今时代&#xff0c;视频已经成为了我们日常生活中不可或缺的一部分&#xff0c;然而&#xff0c;视频文件往往非常大&#xff0c;给我们的存储和传输带来了很大的不便&#xff0c;那么&#xff0c;如何有效地压缩视频呢&#xff1f; 一、使用压缩软件 首先我们给大家分享一…

python的搜索引擎系统设计与实现 计算机竞赛

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; python的搜索引擎系统设计与实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;5分创新点&#xff1a;3分 该项目较为新颖&#xff…

5.覆盖增强技术——PUCCHPUSCH

PUSCH增强方案的标准化工作 1.PUSCH重复传输类型A增强&#xff0c;包括两种增强机制&#xff1a;增加最大重复传输次数&#xff0c;以及基于可用上行时隙的重复传输次数技术方式。 2.基于频域的解决方案&#xff0c;包括时隙间/时隙内跳频的增强 3.支持跨多个时隙的传输块&…

Hadoop3教程(六):HDFS中的DataNode

文章目录 &#xff08;63&#xff09;DataNode工作机制&#xff08;64&#xff09;数据完整性&#xff08;65&#xff09;掉线时限参数设置参考文献 &#xff08;63&#xff09;DataNode工作机制 DataNode内部存储了一个又一个Block&#xff0c;每个block由数据和数据元数据组…

1-k8s1.24-底座搭建-基于containerd

文章目录 一、服务器准备二、安装Containerd三、安装k8s四、安装部署dashboard ps&#xff1a;第一遍搭建ks8的时候&#xff0c;由于k8s在1.24版本之后就放弃了对docker的支持&#xff0c;如果要继续使用docker需要自己加载插件。所以一开始就是直接使用 k8s1.24containerd进行…

基于下垂控制的孤岛双机并联逆变器环流抑制MATLAB仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 在实际应用中逆变器都是并联运行的,但是逆变器的并联运行也存在不少问题,由于线路阻抗差异、各个逆变器输出端瞬时电压幅值不同等,都容易导致环流的出现。环流会导致逆变器损耗增加,从而影响微电网的输出效率…

Megatron-LM GPT 源码分析(二) Sequence Parallel分析

引用 本文基于开源代码 https://github.com/NVIDIA/Megatron-LM &#xff0c;延续上一篇Megatron-LM GPT 源码分析&#xff08;一&#xff09; Tensor Parallel分析 通过对GPT的模型运行示例&#xff0c;从三个维度 - 模型结构、代码运行、代码逻辑说明 对其源码做深入的分析。…

Spring Boot中的常用注解

Spring Boot中的常用注解 深入探讨Spring Boot中的常用注解摘要引言一、认识Spring BootSpring Boot简介和核心概念核心概念详解1. 自动配置2. 起步依赖3. 嵌入式Web服务器 二、Spring中常用注解Spring框架中的关键注解概览Spring框架中的关键注解概览1. Autowired2. Component…

GaussDB for openGauss部署形态

前言 华为云数据库GaussDB是华为自主创新研发的分布式关系型数据库&#xff0c;具有高性能、高可用、高安全、低成本的特点&#xff0c;本文带你详细了解GaussDB数据库的部署形态。 1、GaussDB部署形态三种类型 GaussDB部署形态&#xff1a;单机 独立部署是将数据库组件部署…

prometheus获取kubelet接口监控数据

一、前言 k8s集群的kubelet服务内部有自带的cadvisor服务用于收集k8s集群的监控数据&#xff0c;所以可以通过调用kubelet的接口就能获取pod的资源监控数据&#xff0c;在新版本的k8s中&#xff0c;kubelet的监控数据获取端口为10250端口&#xff0c;老版本的是10255端口 二、…

基于Scrapyd与Gerapy部署scrapy爬虫方案【可用于分布式爬虫部署】

scrapyd部署爬虫 Scrapyd 是一个基于 Scrapy 的开源项目&#xff0c;它提供了一个简单的方式来部署、运行和监控 Scrapy 爬虫。它是一个用于集成 Scrapy 爬虫到分布式架构中的工具&#xff0c;允许您在分布式环境中运行爬虫&#xff0c;并提供了一组 Web API&#xff0c;用于管…

docker入门加实战—部署Java和前端项目

docker入门加实战—部署Java和前端项目 部署之前&#xff0c;先删除nginx&#xff0c;和自己创建的dd两个容器&#xff1a; docker rm -f nginx dd部署Java项目 作为演示&#xff0c;我们的Java项目比较简单&#xff0c;提供了一个接口&#xff1a; 配置文件连接docker里的m…

ios safari 浏览器跳转页面没有自适应

今天开发遇到了一个问题&#xff0c;当用户点击浏览器中的表单进行注册时&#xff0c;表单元素会放大&#xff0c;随后跳转页面无法还原到初始状态。 这是因为如果 的 font-size 被设定为 16px 或更大&#xff0c;那么 iOS 上的 Safari 将正常聚焦到输入表单中。但是&#xff…