超简单的pyTorch训练->onnx模型->C++ OpenCV DNN推理(附源码地址)

学更好的别人,

做更好的自己。

——《微卡智享》

02d27cd2fb04ea8125f457b29e61b7d8.jpeg

本文长度为1974,预计阅读5分钟

前言

很早就想学习深度学习了,因为平时都是自学,业余时间也有限,看过几个pyTorch的入门,都是一些碎片化的东西,始终串不起来。最近也是正好赶的疫情,出差少了,也是在B站看pyTorch视频时有评论说刘二大人的《pyTorch深度学习实践》讲的好,整个教程看下来后,确实是深入浅出,感觉就是宛然打通自己任督二脉,算是入门了。

pyTorch入门,最重要的还是需要真正用起来,OpenCV中DNN模块就是用来推理的,所以这篇就是专门做一个最简单的例子来验证效果,文章最后有源码的Github地址。

0ff0d9a3d24041e6d11fb0f0863aa52c.png

#实现方式
1pyTorch训练数据
2将pyTorch训练好的数据模型转出为onnx的文件
3使用C++ OpenCV DNN实现推理

配置环境

操作系统:Windows 11 Home

pyTorch相关:Miniconda + pyTorch1.12.1(cpu) + python3.9.12,IDE用的是Visual Studio Code

OpenCV相关:OpenCV 4.5.1 + C++,IDE用的是Visual Studio 2022

原来环境装的是Anaconda全家桶,需要的资源空间大,而Miniconda是最小的conda安装环境,所以这里推荐还是用Miniconda。具体的环境配置及安装方式,网上挺多的,包括视频也有,可以自行搜索一下。

平时办公外接大屏显示器,现在由于工作原因,现在出差较多,为了解决使用大屏的需求,同时出差携带方便,所以换了折叠屏的笔记本,由原来的ASUS灵耀X DUO换成了ASUS 灵耀X Fold,相应的原来还有独立显卡,现在也只能是集成显卡,pyTorch也装的是CPU版本。上几张两个笔记本对比图

c21674c7d6519c005a44cbd52e05cacf.jpeg

7686eb22652659964762a8aad8b0b1a4.jpeg

38533352dd4224d6774e82b2dc1f3472.png

代码实现

774fd61e6cfedeb540a07cf0f9e78db2.png

微卡智享

做一个最简单的训练及推理,那我们就不用图像,就是一个简单的运算,如下图:

e97ef5e2f76030081cf4b39f4a35283d.png

上图中红框代表我要的训练集,我们一眼就可以看出,实现的效果就是输入值乘2得到输出结果,下面两条4.0和100.0用于推理出结果,得到的也应该是8.0和200.0

pyTorch训练

01

定义训练集

a484e8d1aeeec6bee68d4cb1e9966996.png

导入torch包后,我们直接定义输入的x_data为【1,2,3】,输出的结果y_data为【2,4,6】,输入结果打印如下:

f42941468963d713b5d6d1881937c9e7.png

02

定义训练的网络模型及损失函数和优化器

462979809864acc366b447c862a1c7b4.png

训练模型也非常简单,只有Linear全链接层一层,并且在前馈forward函数中没有用到激活函数,直接输出了。损失函数用的MSE,优化器SGD,其中学习率参数设置的0.02(lr=0.02)

03

训练模型

4025631be7ed43ab6760d1e30159afec.png

关于训练,主要就是四个步骤:

  1. forward(前馈)

  2. loss(计算损失函数)

  3. backward(反向传播)

  4. step(优化迭代)

上面我们设置了训练次数为1000次,每100次打印一下loss,最后输出权重值,训练的结果如下:

404d35da7262d8f35a8619fab84e955e.png

04

验证测试及输出onnx模型

d511fca12cae05f21e9ccf6d7704c0f6.png

训练完成后,我们来验证测试结果,分输入了4,8,10,15四个值,打印结果如下:

32f1c12d53cd8a02937e1e4786689940.png

上图中可以看到,预测的结果完全准确,接下来我们就将训练的这个模型导出onnx文件用于OpenCV的推理。

cde05f6aa87499bb8da6ef04acbc5b59.png

  1. 将model模型改为eval(),是设置为推理模式。

  2. 定义一个输入的参数模型dummy_input

  3. 设置输出、输出的参数名称input和output,还有onnx的文件名称

  4. 用torch.onnx.export进行导出,其中verbose=True是将会输出被导出的轨迹的调试描述

成功后当前目录下会生成一个test.onnx的模型文件,这样pyTorch训练的模型这块就完成了,接下来就是看看如果用OpenCV的DNN进行推理。

C++ OpenCV推理

9348ee26fe678bca00960f4116d5a3d6.png

C++ OpenCV DNN推理这块代码也很简单,主要就是定义了dnn::Net,然后指定到onnx模型文件的目录,使用readNetfromOnnx加载模型文件。

输入的参数还是用OpenCV的Mat,因为只输入一个参数,所以这里定义的就是1X1,数据类型输入是float的类型,所以定义的也是CV_32F,将Mat传入到输入参数里,net.setInput(Mat值,输入参数名),第二个参数与我们导出的参数名相同,再通过net.forward(输出参数名)得到返回的结果。
 

8b375a21a0f76c1fecfd8a0d9d6f7ef7.png

代码中我们输入的为1024,所以预测的结果为2048,完全正确,这样一个最简单的pyTorch训练模型转出onnx,然后用C++ OpenCV推理的Demo就完成了。

c0b4e255eefd8743fe0fe71285b31e5d.png

微卡智享

源码地址

https://github.com/Vaccae/OpenCVDemoCpp.git

点击阅读原文可以看到“码云”的代码地址

6d0e571f5eec544d746ca8ff5a362c31.png

往期精彩回顾

8fc8fd206a22120d4778889490d0a50f.jpeg

Kotlin在协程中使用Select表达式选择最快结果

 

14c33670fd4b6f1c84122cee9d19c45a.jpeg

C++ OpenCV手动截取图像做透视变换

 

0a2a58bcdb71e468a78ee17a128c2370.jpeg

使用OpenCV做个简单的颜色提取器

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
下面是一个简单C++ OpenCV DNN 推理代码示例,使用 ONNX 格式的 U-Net 模型进行语义分割: ```c++ #include <opencv2/dnn/dnn.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/highgui/highgui.hpp> using namespace cv; using namespace cv::dnn; int main(int argc, char** argv) { // 读取模型文件 const string model_file_path = "unet.onnx"; Net net = readNetFromONNX(model_file_path); // 读取输入图像 const string input_file_path = "input.jpg"; Mat input_image = imread(input_file_path); // 预处理输入图像 Mat input_blob = blobFromImage(input_image, 1.0 / 255.0, Size(572, 572), Scalar(0, 0, 0), true, false); // 运行推理 Mat output_blob; net.setInput(input_blob); net.forward(output_blob); // 后处理输出结果 Mat output_image; output_blob = output_blob.reshape(1, 388 * 388); output_blob.convertTo(output_blob, CV_8UC1, 255.0); applyColorMap(output_blob, output_image, COLORMAP_JET); // 显示输出结果 imshow("Output", output_image); waitKey(0); return 0; } ``` 这个示例代码假设已经有了一个 ONNX 格式的 U-Net 模型文件 `unet.onnx` 和一个输入图像文件 `input.jpg`。代码中首先使用 `readNetFromONNX` 函数读取了模型文件,然后使用 `imread` 函数读取了输入图像。 接下来,代码中使用 `blobFromImage` 函数将输入图像转换成网络需要的输入格式,并使用 `setInput` 函数将输入数据设置到网络中,使用 `forward` 函数进行推理,得到输出结果。 最后,代码中使用 `reshape` 函数和 `convertTo` 函数对输出结果进行后处理,然后使用 `applyColorMap` 函数将结果可视化,使用 `imshow` 函数显示输出结果,使用 `waitKey` 函数等待用户按下键盘。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Vaccae

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值