OpenCV 的 DNN(Deep Neural Network)模块是一个强大的工具,可以用来加载和运行预训练的深度学习模型,包括目标检测模型(如 YOLO、SSD 等)。它不需要额外的深度学习框架(如 PyTorch 或 TensorFlow),只需 OpenCV 本身即可推理,非常适合轻量级应用或与 OpenCV 的图像处理功能结合使用。
以下是关于 OpenCV DNN 模块的详细说明,以及如何使用它来实现目标检测(以 YOLOv3 为例)。
特点
- 支持多种模型格式:可以加载 Caffe、TensorFlow、Darknet(YOLO)、ONNX 等格式的模型。
- 跨平台:支持 CPU 和 GPU(需编译支持 CUDA)。
- 轻量:无需安装额外的深度学习框架。
- 与 OpenCV 集成:方便与图像处理、视频流等功能结合。
安装
确保你安装了 OpenCV 的 Python 包。如果需要 GPU 支持,需自行编译 OpenCV 并启用 CUDA。
bash
pip install opencv-python # 基本版本(CPU)
# 或
pip install opencv-contrib-python # 包含更多功能
检查版本:
python
import cv2
print(cv2.__version__) # 例如 4.9.0
使用 OpenCV DNN 运行 YOLOv3 示例
以下是一个使用 OpenCV DNN 模块加载 YOLOv3 模型并进行目标检测的完整示例:
准备工作
-
下载 YOLOv3 的配置文件和权重文件:
yolov3.cfg
:模型配置文件(从 Darknet GitHub 或官方网站下载)。yolov3.weights
:预训练权重文件(约 200MB)。coco.names
:COCO 数据集的类别名称文件(包含 80 个类,如 "person"、"car" 等)。
你可以从以下链接获取:
- YOLOv3 官方页面
- 或直接下载:
linux:
sh
wget https://pjreddie.com/media/files/yolov3.weights
wget https://github.com/pjreddie/darknet/raw/master/cfg/yolov3.cfg
wget https://github.com/pjreddie/darknet/raw/master/data/coco.names
windows:
sh
# 下载 yolov3.weights
Invoke-WebRequest -Uri "https://pjreddie.com/media/files/yolov3.weights" -OutFile "yolov3.weights"
# 下载 yolov3.cfg
Invoke-WebRequest -Uri "https://github.com/pjreddie/darknet/raw/master/cfg/yolov3.cfg" -OutFile "yolov3.cfg"
# 下载 coco.names
Invoke-WebRequest -Uri "https://github.com/pjreddie/darknet/raw/master/data/coco.names" -OutFile "coco.names"
- 将这些文件保存在你的项目目录中。
代码示例
python
import cv2
import numpy as np
# 加载 YOLOv3 模型
net = cv2.dnn.readNetFromDarknet('yolov3.cfg', 'yolov3.weights')
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU) # 或 DNN_TARGET_CUDA 如果有 GPU 支持
# 加载类别名称
with open('coco.names', 'r') as f:
classes = [line.strip() for line in f.readlines()]
# 获取输出层名称
layer_names = net.getLayerNames()
output_layers = [layer_names[i - 1] for i in net.getUnconnectedOutLayers()]
# 打开摄像头
cap = cv2.VideoCapture(0) # 0 表示默认摄像头
while True:
# 读取视频帧
ret, frame = cap.read()
if not ret:
break
# 准备输入图像
height, width = frame.shape[:2]
blob = cv2.dnn.blobFromImage(frame, 1/255.0, (416, 416), swapRB=True, crop=False)
net.setInput(blob)
# 前向传播
outputs = net.forward(output_layers)
# 处理检测结果
boxes = []
confidences = []
class_ids = []
for output in outputs:
for detection in output:
scores = detection[5:]
class_id = np.argmax(scores)
confidence = scores[class_id]
if confidence > 0.5: # 置信度阈值
# 计算边界框坐标
center_x = int(detection[0] * width)
center_y = int(detection[1] * height)
w = int(detection[2] * width)
h = int(detection[3] * height)
x = int(center_x - w / 2)
y = int(center_y - h / 2)
boxes.append([x, y, w, h])
confidences.append(float(confidence))
class_ids.append(class_id)
# 非极大值抑制(NMS)去重
indices = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
# 绘制检测结果
for i in indices:
box = boxes[i]
x, y, w, h = box
label = str(classes[class_ids[i]])
confidence = confidences[i]
color = (0, 255, 0) # 绿色
cv2.rectangle(frame, (x, y), (x + w, y + h), color, 2)
cv2.putText(frame, f"{label} {confidence:.2f}", (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
# 判断是否检测到人
if class_ids[i] == 0: # COCO 数据集中 'person' 的 ID 是 0
print("Person detected!")
# 显示结果
cv2.imshow('YOLOv3 Detection', frame)
# 按 'q' 退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
代码说明
-
加载模型:
cv2.dnn.readNetFromDarknet
加载 Darknet 格式的 YOLOv3 模型。- 你可以选择
DNN_TARGET_CPU
或DNN_TARGET_CUDA
(需编译支持)。
-
输入预处理:
blobFromImage
将图像转换为 YOLO 所需的格式(416x416 是 YOLOv3 的默认输入大小)。
-
输出处理:
- YOLO 输出多个尺度(3 个输出层),需要解析边界框、置信度和类别。
- 使用 NMS(非极大值抑制)去除重叠框。
-
判断检测到人:
- 检查
class_ids[i] == 0
,因为 COCO 数据集中 "person" 的类别 ID 是 0。
- 检查
-
可视化:
- 用
cv2.rectangle
和cv2.putText
绘制边界框和标签。
- 用
优点
- 无需额外深度学习框架,依赖少。
- 与 OpenCV 的其他功能(如视频处理、图像滤波)无缝集成。
- 支持多种模型格式,灵活性高。
缺点
- 推理速度可能不如 PyTorch 或 TensorFlow 原生实现(尤其在 GPU 上)。
- 不支持直接训练模型,仅用于推理。
- 配置 GPU 支持需要手动编译 OpenCV。
支持的其他模型
除了 YOLO,你还可以用 OpenCV DNN 加载:
- SSD (Single Shot MultiBox Detector):
cv2.dnn.readNetFromCaffe
。 - Faster R-CNN:从 TensorFlow 或 ONNX 加载。
- ONNX 模型 :
cv2.dnn.readNetFromONNX
。