前言
前一篇实现了ResNet18训练自定义数据集,详细介绍了数据集制作、模型构建及训练,并且介绍了相应模块如何可视化。前面训练阶段是在python环境下进行的,但实际工程部署的时候大都采用C++实现推理,这一篇我们借助OpenCV实现ResNet18推理。
一、准备
1、OpenCV编译及安装
借助OpenCV实现ResNet18推理,首先需要准备好工具,OpenCV源码编译及安装可参考:
2、其他环境
二、OpenCV推理ResNet18
依据前一篇python模型测试脚本来看,主要分为图片预处理和模型预测两大步,但OpenCV的dnn模块读取ONNX格式模型,所以这里分成模型转换,数据预处理和推理三部分。
1、模型转换
将pytorch训练的模型转换为ONNX格式,这里借助torch.onnx.export()
接口进行实现。
- 加载权重
类似模型测试一样,先加载训练好的权重参数
- 准备数据
生成固定大小的随机数,便于后期进行转换
- 模型转换
这里利用torch.onnx.export()
接口进行转换
- 验证转换是否正确
要验证转换是否正确,只需要加载不同模型,对同一份数据进行推理,对比其结果是否正确
- onnx模型简化
有时候转换出来的模型有些算子可以合并,这里采用 ONNX Simplifier库对转换后的模型进行简化处理。
安装完成后执行
打开后可以看到conv, BN层被合并,模型大小也相应变小
2、数据预处理
从python测试脚本可知,数据预处理主要包含以下几步:
现分别将其转换成C++
- 通道转换
lambda x: Image.open(x).convert('RGB')
是将图片的通道格式转换为RGB,这里我们利用OpenCV库读取图片并实现通道格式转换,注意:OpenCV读取图片后默认是BGR格式
- 图片缩放
transforms.Resize((img_size, img_size))
将图片缩放至指定大小,转成OpenCV的话其C++代码如下:
- 归一化处理
transforms.ToTensor()
将数据格式转换成torch张量类型,并将其值转变到[0, 1]的范围。因此这里需要对图片像素值除以255。
- 标准化处理
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
将输入数据减均值后在除以方差。转为C++代码如下:
经过以上过程,图片已经预处理完成。接下来借助OpenCV的DNN模块完成推理。
3、模型推理
将输入数据转换为input,blobFromImage()
接口也可以执行一些缩放、通道转换以及标准化等操作
执行forward()
后会输出模型推理的结果,接下来找出最大值所在的索引即为类别。