目录
简述
在计算机视觉领域,图像分类是一个基础且重要的任务。OpenCV 提供了 dnn 模块,可以方便地加载深度学习模型并实现图像分类。本文将详细介绍如何使用 OpenCV 的 dnn 模块实现图像分类,包括模型导入、使用步骤、支持的模型类型以及完整的代码示例。
1. OpenCV dnn 模块简介
OpenCV 的 dnn 模块是一个深度学习推理模块,支持从多种深度学习框架(如 TensorFlow、Caffe、ONNX 等)导入模型,并实现高效的推理。它不涉及模型训练,主要用于模型的加载和推理。
2. 使用步骤
使用 OpenCV 的 dnn 模块实现图像分类的步骤如下:
- 加载模型:导入预训练的深度学习模型及其配置文件。
- 预处理输入图像:将输入图像转换为模型所需的格式(如调整大小、归一化等)。
- 推理:将预处理后的图像输入模型,获取输出结果。
- 后处理:解析模型的输出,得到最终的分类结果。
3. 如何导入模型
OpenCV 支持从以下框架导入模型:
- Caffe:需要 .prototxt(模型配置文件)和 .caffemodel(模型权重文件)。
- TensorFlow:需要 .pb(模型文件)和 .pbtxt(配置文件,可选)。
- ONNX:直接加载 .onnx 文件。
- Darknet:用于 YOLO 模型,需要 .cfg 和 .weights 文件。
导入模型的通用方法:
import cv2
# 以 Caffe 模型为例
model_weights = "model.caffemodel"
model_config = "model.prototxt"
net = cv2.dnn.readNet(model_weights, model_config)
4. 支持的模型类型
OpenCV 的 dnn 模块支持多种预训练模型,常用的图像分类模型包括:
- AlexNet
- GoogleNet (Inception)
- ResNet
- MobileNet
- SqueezeNet
- VGG
这些模型可以从 OpenCV 的官方 GitHub 仓库或 TensorFlow Model Zoo 等资源中获取。
5. 完整代码示例
以下是一个使用 OpenCV 的 dnn 模块实现图像分类的完整代码示例。
5.1 代码示例
import cv2
from cv2 import dnn
import numpy as np
# 1. 导入模型
# 2. 读取图片、转成张量
# 3. 将张量输入到神经网络中,并进行预测
# 4. 显示结果
config = "D:\\resource\\opencv\\model\\bvlc_googlenet.prototxt"
model = "D:\\resource\\opencv\\model\\bvlc_googlenet.caffemodel"
net = dnn.readNetFromCaffe(config, model)
img = cv2.imread('D:\\resource\\opencv\\smallcat.jpeg')
blob = dnn.blobFromImage(img, 1.0, (224,224), (104,117,123))
net.setInput(blob)
r = net.forward()
classes = []
path = 'D:\\resource\\opencv\\model\\synset_words.txt'
with open(path, 'rt') as f:
classes = [x [x.find(" ") + 1:] for x in f]
order = sorted(r[0], reverse=True)
# 提取匹配结果
z = list(range(3))
img_x = 20
img_y = 70
for i in range(0,3):
z[i] = np.where(r[0]==order[i])[0][0]
text= str(i+1) + ': ' + classes[z[i]].strip() + ', probability: ' + f"{order[i] * 100:.2f}%"
cv2.putText(img, text, (img_x, img_y), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
img_y += 30
# 显示结果
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
这段代码的主要功能是使用预训练的 GoogLeNet 模型对输入的图像进行分类,并在图像上显示概率最大的前 3 个类别及其概率。
5.2 运行结果
5.3 代码解析
导入模型
config = "D:\\resource\\opencv\\model\\bvlc_googlenet.prototxt"
model = "D:\\resource\\opencv\\model\\bvlc_googlenet.caffemodel"
net = dnn.readNetFromCaffe(config, model)
- config:存储了 GoogLeNet 模型的配置文件路径,.prototxt文件定义了模型的网络结构。
- model:存储了 GoogLeNet 模型的预训练权重文件路径,.caffemodel文件包含了训练好的模型参数。
- dnn.readNetFromCaffe:从 Caffe 框架的配置文件和权重文件中加载深度学习模型。
读取图片并转成张量
img = cv2.imread('D:\\resource\\opencv\\smallcat.jpeg')
blob = dnn.blobFromImage(img, 1.0, (224,224), (104,117,123))
- cv2.imread:读取本地图像。
- dnn.blobFromImage:将图像转换为适合输入到神经网络的格式(即张量)。
blobFromImage 接口参数说明如下:
- img:输入的图像。
- 1.0:缩放因子,这里不进行缩放。
- (224, 224):输出图像的尺寸,GoogLeNet 模型要求输入图像的尺寸为 224x224。
- (104, 117, 123):均值减法,用于归一化图像数据。
将张量输入到神经网络中并进行预测
net.setInput(blob)
r = net.forward()
- net.setInput:将转换后的张量设置为神经网络的输入。
- net.forward:执行前向传播,得到模型的预测结果。r是一个 NumPy 数组,包含了模型对输入图像的分类概率。
读取类别标签
classes = []
path = 'D:\\resource\\opencv\\model\\synset_words.txt'
with open(path, 'rt') as f:
classes = [x [x.find(" ") + 1:] for x in f]
- 打开synset_words.txt文件,该文件包含了模型可以识别的所有类别的标签。
- 使用列表推导式提取每行中第一个空格之后的部分,作为类别标签,并存储在classes列表中。
对预测结果进行排序
order = sorted(r[0], reverse=True)
- r[0]:取出预测结果的第一个维度,即每个类别的概率。
- sorted:对概率进行降序排序,得到概率最大的类别排在前面。
提取匹配结果并在图像上显示
z = list(range(3))
img_x = 20
img_y = 70
for i in range(0,3):
z[i] = np.where(r[0]==order[i])[0][0]
text= str(i+1) + ': ' + classes[z[i]].strip() + ', probability: ' + f"{order[i] * 100:.2f}%"
cv2.putText(img, text, (img_x, img_y), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
img_y += 30
- z:用于存储概率最大的前 3 个类别的索引。
- np.where:找到概率值等于order[i]的索引。
- text:生成显示在图像上的文本,包括排名、类别标签和概率。
- cv2.putText:在图像上绘制文本。
显示结果
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
- cv2.imshow:显示包含预测结果的图像。
- cv2.waitKey(0):等待用户按下任意键。
- cv2.destroyAllWindows:释放所有打开的窗口。
6. 总结 & 资源下载
本文介绍了如何使用 OpenCV 的 dnn 模块实现图像分类,包括模型导入、使用步骤、支持的模型类型以及完整的代码示例。OpenCV 的 dnn 模块为深度学习模型的推理提供了简单高效的接口,适合快速部署和测试。
链接:https://pan.baidu.com/s/1LVn5OW-0d05wIPi_xc3XWA?pwd=csdn
提取码:csdn