首页 > 其他分享 >OpenCV实现ResNet18推理

OpenCV实现ResNet18推理

时间:2023-07-21 16:44:24浏览次数:44  
标签:ResNet18 img onnx torch OpenCV output 推理 cv

前一篇实现了ResNet18训练自定义数据集,详细介绍了数据集制作、模型构建及训练,并且介绍了相应模块如何可视化。前面训练阶段是在python环境下进行的,但实际工程部署的时候大都采用C++实现推理,这一篇我们借助OpenCV实现ResNet18推理。

一、准备

1、OpenCV编译及安装

借助OpenCV实现ResNet18推理,首先需要准备好工具,OpenCV源码编译及安装可参考:
https://www.cnblogs.com/xiaxuexiaoab/p/15894993.html

2、其他环境

Windows10
visual Studio 2019

二、OpenCV推理ResNet18

依据前一篇python模型测试脚本来看,主要分为图片预处理和模型预测两大步,但OpenCV的dnn模块读取ONNX格式模型,所以这里分成模型转换,数据预处理和推理三部分。

1、模型转换

将pytorch训练的模型转换为ONNX格式,这里借助torch.onnx.export()接口进行实现。

  • 加载权重
    类似模型测试一样,先加载训练好的权重参数
device = torch.device("cuda" if torch.cuda.is_available() else "cpu") 
model = resnet18()
model = nn.Sequential(*list(model.children())[:-1],  # [b, 512, 1, 1] -> 接全连接层 
                          # torch.nn.Flatten(),
                          nn.Linear(512, 2)).to(device)   # 添加全连接层

model.load_state_dict(torch.load("./resnet18-2Class.pth"))
model.eval()

  • 准备数据
    生成固定大小的随机数,便于后期进行转换
img_size = 64
data = torch.randn(1, 3, img_size, img_size).to(device)
  • 模型转换
    这里利用torch.onnx.export()接口进行转换
onnx_save_path = "./resnet18_2class.onnx"
print("Start convert model to onnx...")
torch.onnx.export(model,
                  data,
                  onnx_save_path,
                  opset_version=10,
                  do_constant_folding=True,  # 是否执行常量折叠优化
                  input_names=["input"],  # 输入名
                  output_names=["output"],  # 输出名
                  dynamic_axes={"input": {0: "batch_size"},  # 批处理变量
                                "output": {0: "batch_size"}}
)
print("convert onnx is Done!")
  • 验证转换是否正确
    要验证转换是否正确,只需要加载不同模型,对同一份数据进行推理,对比其结果是否正确
# check
import onnx
import onnxruntime

torch_out = model(data)
print("torch_out: ", torch_out)

onnx_model = onnx.load(onnx_save_path)
onnx.checker.check_model(onnx_model)                 # onnx自带检查工具
print(onnx.helper.printable_graph(onnx_model.graph))   

session = onnxruntime.InferenceSession(onnx_save_path)
inputs = {session.get_inputs()[0].name: data}
onnx_out = session.run(None, inputs)[0]
print("onnx_out: ", onnx_out)

# 对比
def test_diff(o_output, f_output):
    print("Max abs diff: ", (o_output - f_output).abs().max().item())
    assert(o_output.argmax() == f_output.argmax())
    # print(o_output[0][0].item(), f_output[0][0].item())
    print("MSE diff: ", torch.nn.MSELoss()(o_output, f_output).item())

test_diff(torch_out, onnx_out)

  • onnx模型简化
    有时候转换出来的模型有些算子可以合并,这里采用ONNX Simplifier对转换后的模型进行简化处理。
    安装完成后执行
python -m onnxsim  resnet18_2class.onnx resnet18_2class_sim.onnx

打开后可以看到conv, BN层被合并,模型大小也相应变小

2、数据预处理

从python测试脚本可知,数据预处理主要包含以下几步:

现分别将其转换成C++

  • 通道转换
    lambda x: Image.open(x).convert('RGB')是将图片的通道格式转换为RGB,这里我们利用OpenCV库读取图片并实现通道格式转换,注意:OpenCV读取图片后默认是BGR格式
#include "opencv2/imgproc.hpp"
#include <opencv2/highgui.hpp>
#include "opencv2/dnn/dnn.hpp"

std::string imgPath = "./test.png";
cv::Mat img = cv::imread(imgPath);
img.convertTo(img, CV_32FC3);
cv::cvtColor(img, img, cv::COLOR_BGR2RGB);
  • 图片缩放
    transforms.Resize((img_size, img_size))将图片缩放至指定大小,转成OpenCV的话其C++代码如下:
cv::resize(img, img, cv::Size(img_size, img_size));
  • 归一化处理
    transforms.ToTensor()将数据格式转换成torch张量类型,并将其值转变到[0, 1]的范围。因此这里需要对图片像素值除以255。
img = img / 255.0;
  • 标准化处理
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])将输入数据减均值后在除以方差。转为C++代码如下:
std::vector<float> mean_value{ 0.485, 0.456, 0.406 };
std::vector<float> std_value{ 0.229, 0.224, 0.225 };
cv::Mat dst;
std::vector<cv::Mat> rgbChannels(3);
cv::split(img, rgbChannels);
for (auto i = 0; i < rgbChannels.size(); i++)
{
	rgbChannels[i] = (rgbChannels[i] - mean_value[i]) / std_value[i];
}

cv::merge(rgbChannels, dst);

经过以上过程,图片已经预处理完成。接下来借助OpenCV的DNN模块完成推理。

3、模型推理

将输入数据转换为input,blobFromImage()接口也可以执行一些缩放、通道转换以及标准化等操作

# 加载模型
std::string modelPath = "./resnet18_2class_sim.onnx"
cv::dnn::Net net = cv::dnn::readNetFromONNX(modelPath);
std::cout << net.empty() << std::endl;

cv::Mat inputBolb = cv::dnn::blobFromImage(dst);  // 也可进行缩放 通道转换 均值等操作
net.setInput(inputBolb);
cv::Mat result = net.forward();

执行forward()后会输出模型推理的结果,接下来找出最大值所在的索引即为类别。

double minValue, maxValue;    // 最大值,最小值
cv::Point  minIdx, maxIdx;    // 最小值坐标,最大值坐标     
cv::minMaxLoc(result, &minValue, &maxValue, &minIdx, &maxIdx);
std::cout << "res: " << result << std::endl;
/*std::cout << "maxValue: " << maxValue << "maxIdx: " << maxIdx.x << std::endl;
std::cout << "minValue: " << minValue << "minIdx: " << minIdx.x << std::endl;*/
classId = maxIdx.x;

标签:ResNet18,img,onnx,torch,OpenCV,output,推理,cv
From: https://www.cnblogs.com/xiaxuexiaoab/p/17571626.html

相关文章

  • YOLOv6在LabVIEW中的推理部署(含源码)
    前言YOLOv6是美团视觉智能部研发的一款目标检测框架,致力于工业应用。如何使用python进行该模型的部署,官网已经介绍的很清楚了,但是对于如何在LabVIEW中实现该模型的部署,笔者目前还没有看到相关介绍文章,所以笔者在实现YOLOv6ONNX在LabVIEW中的部署推理后,决定和各位读者分享一下......
  • Vscode 编写opencv配置文件
    创建一个新文件夹并在vscode打开,在此文件夹下新建一个.vscode文件夹,再继续新建三个.json文件(tasks.json,launch.json,c_cpp_properties.json)。 c_cpp_properties.json如下,"includePath"添加自己的头文件路径,"compilerPath"改为自己对应的gcc路径。{"configurations":[......
  • Android opencv Mat 创建单位矩阵
    AndroidOpenCVMat创建单位矩阵在计算机视觉和图像处理中,矩阵是一个非常重要的概念。矩阵可以表示图像的像素值、进行图像变换、计算特征向量和特征值等。Android平台上,OpenCV是一个强大的图像处理库,提供了许多矩阵操作的函数和工具。本文将介绍如何使用OpenCV在Android上创建单......
  • OpenCV for .NET获取图片文字
    OpenCVfor.NET获取图片文字随着人工智能的快速发展,图像处理技术在各个领域都得到了广泛应用。而文字识别作为图像处理的一个重要应用之一,能够将图片中的文字提取出来,为后续的文字分析和处理提供基础。OpenCV是一个开源的计算机视觉库,提供了丰富的图像处理和计算机视觉算法。本文......
  • Visual Studio新建项目配置好opencv环境,下次打开这个项目后属性管理器显示未加载visua
    配置opencv环境,可参考这篇博客:(82条消息)opencv之visualstudio开发环境配置(属性管理器+环境变量一劳永逸方便开发的配置方式)_opencv官网下载_仙魁XAN的博客-CSDN博客如出现打开这个项目后属性管理器显示未加载visualC++项目,可参考如下方法:1.解决方法:文件→打开→项目/......
  • python 使用OpenCV进行目标检测和识别的完整示例
    #导入OpenCV库importcv2#加载图像image=cv2.imread('image.jpg')#创建Haar级联分类器cascade_classifier=cv2.CascadeClassifier('haarcascade_frontalface_default.xml')#检测目标图像中的行人gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)faces=ca......
  • VS2017配置OpenCV
    VS2017配置OpenCV0OpenCV介绍OpenCV(OpenSourceComputerVisionLibrary)是一个开源的计算机视觉库,它提供了丰富的图像处理和计算机视觉算法,可用于处理图像和视频数据。OpenCV提供了C语言版本,使开发者可以使用C语言来调用OpenCV提供的功能。OpenCV可以用来进行多种图像处理......
  • 百度飞桨PP-YOLOE ONNX 在LabVIEW中的部署推理(含源码)
    目录前言一、什么是PP-YOLO二、环境搭建1、部署本项目时所用环境2、LabVIEW工具包下载及安装三、模型的获取与转化1、安装paddle2、安装依赖的库3、安装pycocotools4、导出onnx模型(1)导出推理模型(2)安装paddle2onnx(3)转换成onnx格式四、在LabVIEW实现PP-YOLOE的部署推理1、LabVIEW......
  • 使用OpenCV中的DNN模块进行人脸识别的官方示例代码(C++版本):
    chatgpt生成#include<opencv2/core.hpp>#include<opencv2/dnn.hpp>#include<opencv2/imgproc.hpp>#include<opencv2/highgui.hpp>usingnamespacecv;usingnamespacednn;intmain(){//加载模型和配置文件Stringmodel_path="pa......
  • playwright+opencv 过滑块拼图验证码
    前言最近看到浏览器自动化框架playwright,就使用了一下在模拟登录掘金是通过密码登陆时遇到需要通过拼图验证码于是通过查找发现可以通过opencv库解决问题下面是解决过程过程1.首先需要获取到图片,通过查看html可以很容易找到需要的图片2.通过opencv进行图像处理来获取到拼......