OpenCV dnn模块 分类模型Resnet50 OpenCV dnn模块部署 .onnx模型

 一、资源介绍

项目需要,需要基于opencv的dnn模块来调用resnet模型,需要resnet模型先训练,之后再导出onnx。

二、导出ONNX

下载yolov5源码

```bash
# 下载yolov5源码
git clone https://github.com/ultralytics/yolov5.git
# 切换到yolov5工程目录
cd yolov5
# 使用tag从远程创建本地v6.2 分支
git branch v6.2 v6.2

```bash
python3 export.py --weights ./weights/resnet50.pt --include torchscript
```

三、openCV DNN 模块支持的深度学习框架

OpenCV DNN 模块支持许多流行的深度学习框架。以下是 OpenCV DNN 模块支持的深度学习框架。

Caffe
要将预训练的 Caffe 模型与 OpenCV DNN 一起使用,我们需要做两件事。一种是包含预训练权重的 model.caffemodel 文件。另一个是具有 .prototxt 扩展名的模型架构文件。它就像一个纯文本文件,具有类似 JSON 的结构,包含所有神经网络层的定义。

TensorFlow
为了加载预训练的 TensorFlow 模型,我们还需要两个文件。模型权重文件和protobuf文本文件包含模型配置。权重文件有一个 .pb 扩展名,它是一个包含所有预训练权重的 protobuf 文件。如果您之前使用过 TensorFlow,您会知道 .pb 文件是我们在保存模型并冻结权重后得到的模型检查点。模型配置保存在 protobuf 文本文件中,该文件具有 .pbtxt 文件扩展名。

Torch和 PyTorch
为了加载 Torch 模型文件,我们需要包含预训练权重的文件。通常,此文件具有 .t7 或 .net 扩展名。但是对于具有 .pth 扩展名的最新 PyTorch 模型,首先转换为 ONNX 是继续进行的最佳方式。转换为 ONNX 后,您可以直接加载它们,因为 OpenCV DNN 支持 ONNX 模型。但是opencv的dnn模块不支持读取pytorch的训练模型文件的。如果想要把pytorch的训练模型.pth文件加载到opencv的dnn模块里,需要先把pytorch的训练模型.pth文件转换到.onnx文件,然后才能载入到opencv的dnn模块里。

Darknet
OpenCV DNN 模块也支持著名的 Darknet 框架。如果他们使用了带有Darknet框架的官方 YOLO 模型。通常,要加载Darknet模型,我们需要一个具有 .weights 扩展名的模型权重文件。对于 Darknet 模型,网络配置文件是 .cfg 文件。

使用从 Keras 和 PyTorch 等不同框架转换为 ONNX 格式的模型
通常,在 PyTorch 或 TensorFlow 等框架中训练的模型可能无法直接与 OpenCV DNN 模块一起使用。在这些情况下,我们通常将模型转换为 ONNX 格式(开放式神经网络交换),然后可以按原样使用,甚至可以转换为其他框架支持的格式,如 TensorFlow 或 PyTorch。要加载 ONNX 模型,我们只需要 OpenCV DNN 模块的 .onnx 权重文件。
 

四、使用 OpenCV DNN模块进行图像分类

	    cv::dnn::Net net = cv::dnn::readNetFromONNX("resnet50.onnx"); // 加载训练好的识别模型		

		cv::Mat image = cv::imread(fileName, cv::IMREAD_COLOR);  // 读取图片
		if (image.empty())
		{
			std::cout << fileName <<"image.empty";
			return 0;
		}
		cv::namedWindow("image", WINDOW_NORMAL);
		cv::imshow("image", image);

		double inpWidth = image.cols;
		double inpHeight = image.rows;
		Scalar img_mean = Scalar(123.675, 116.28, 103.53);
		Scalar img_std = Scalar(0.229, 0.224, 0.225);
		double scale = 0.00390625f;
		cv::Mat blob;
		cv::dnn::blobFromImage(image, blob, scale, Size(inpWidth, inpHeight), img_mean, true, false);
		if (img_std.val[0] != 0.0 && img_std.val[1] != 0.0 && img_std.val[2] != 0.0)
		{
			divide(blob, img_std, blob);
		}

		net.setInput(blob);  // 设置模型输入
		cv::Mat predict = net.forward(); // 推理出结果	
		Point minLoc, maxcLoc;;
		double min, max;
		cv::minMaxLoc(predict, &min, &max, &minLoc, &maxcLoc);

    CV_EXPORTS void blobFromImage(InputArray image, OutputArray blob, double scalefactor=1.0,
                                  const Size& size = Size(), const Scalar& mean = Scalar(),
                                  bool swapRB=false, bool crop=false, int ddepth=CV_32F);

参数说明:
image:使用 imread() 函数读取的输入图像。
scalefactor:此值按提供的值缩放图像。它的默认值为 1,这意味着不执行缩放。
size:这是图像将被调整到的大小。
mean: 平均论点非常重要。这些实际上是从图像的 RGB 颜色通道中减去的平均值。这对输入进行了归一化,并使最终输入对不同的照明尺度保持不变
swapRB:是否交换第一个和最后一个通道,一般需要交换,因为imread()函数以BGR读取图像,而模型需要的是RGB格式。
crop:是否在调整大小后是否裁剪图像
ddepth:输出blob的深度。 选择CV_32F或CV_8U。 默认CV_32F。
 

QQ交流:187100248

猜你喜欢

转载自blog.csdn.net/zhulong1984/article/details/126619764