15 目标检测之YOLO与SSD
目标检测是计算机视觉中的一个重要任务,涉及到在图片或视频中识别和定位多个对象。近年来,随着深度学习技术的快速发展,基于深度学习的目标检测方法得到了广泛的应用。其中,YOLO
(You Only Look Once)和 SSD
(Single Shot MultiBox Detector)是两个非常流行且高效的方法。在本篇教程中,我们将详细探讨这两种检测算法,包括它们的原理、实现以及如何在 OpenCV 中使用它们。
YOLO(You Only Look Once)
YOLO 是一种基于卷积神经网络(CNN)的实时目标检测系统。这种方法的主要思想是将整个图像作为网络的输入,并在单个前向传播中同时进行目标的定位和分类。与传统的目标检测方法不同,YOLO 将检测问题转化为回归问题。
YOLO 的工作原理
YOLO 将输入图像划分为 S x S 的网格,每个网格负责预测一个边界框和对应的类概率。每个网格单元输出的信息包括:
- 边界框的中心坐标
- 边界框的宽度和高度
- 某个类的置信度
最终,YOLO 会通过 Non-Maximum Suppression(NMS)来整理重叠的边界框,保留最高置信度的边框,得到最终的检测结果。
在 OpenCV 中实现 YOLO
下面是如何在 OpenCV 中使用 YOLO 进行目标检测的简单示例。
1. 下载 YOLO 模型
首先,你需要下载 YOLO 的权重和配置文件。你可以从 YOLO 官方 GitHub 页面下载:
yolov3.weights
yolov3.cfg
coco.names
(类名文件)
2. 代码示例
import cv2
import numpy as np
# 加载 YOLO 模型
net = cv2.dnn.readNet("yolov3.weights", "yolov3.cfg")
layer_names = net.getLayerNames()
output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
# 加载类名
with open("coco.names", "r") as f:
classes = [line.strip() for line in f.readlines()]
# 加载图片
img = cv2.imread("image.jpg")
height, width, _ = img.shape
# 创建输入Blob
blob = cv2.dnn.blobFromImage(img, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
net.setInput(blob)
# 进行前向传播
outs = net.forward(output_layers)
# 解析输出
boxes = []
confidences = []
class_ids = []
for out in outs:
for detection in out:
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)
# 应用非极大抑制
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
# 绘制检测结果
for i in range(len(boxes)):
if i in indexes:
x, y, w, h = boxes[i]
label = str(classes[class_ids[i]])
confidence = confidences[i]
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(img, f"{label} {round(confidence, 2)}", (x, y + 30), cv2.FONT_HERSHEY_PLAIN, 2, (0, 255, 0), 3)
# 显示结果
cv2.imshow("Image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
在上面的代码中,我们使用 OpenCV 的 dnn
模块来加载 YOLO 模型,进行目标检测并绘制出检测到的边界框和标签。
SSD(Single Shot MultiBox Detector)
SSD 是另一种流行的目标检测方法,能够以较高的速度和准确性进行检测。与 YOLO 相似,SSD 也将目标检测问题视为一个回归问题。
SSD 的工作原理
SSD 在不同的特征图上进行检测,并使用默认边界框进行预测。它通过在多层特征图上进行卷积操作,提取多尺度信息以提高检测效果。SSD 可以在添加较少的计算负担的情况下,达到较高的召回率和精度。
在 OpenCV 中实现 SSD
与 YOLO 类似,你同样可以在 OpenCV 中使用 SSD 模型进行目标检测。在运行 SSD 的代码之前,请确保你已经下载了对应的模型文件,比如 SSD MobileNet
或其他类型的 SSD 模型。
代码示例
import cv2
# 加载 SSD 模型
net = cv2.dnn.readNetFromCaffe("deploy.prototxt", "mobilenet.caffemodel")
# 加载图片
img = cv2.imread("image.jpg")
height, width, _ = img.shape
# 创建输入Blob
blob = cv2.dnn.blobFromImage(img, 0.007843, (300, 300), 127.5)
net.setInput(blob)
# 进行前向传播
detections = net.forward()
# 解析输出
for i in range(detections.shape[2]):
confidence = detections[0, 0, i, 2]
if confidence > 0.5: # 设置阈值
class_id = int(detections[0, 0, i, 1])
box = detections[0, 0, i, 3:7] * np.array([width, height, width, height])
(startX, startY, endX, endY) = box.astype("int")
# 绘制检测结果
label