Jupyter AI

15 目标检测之YOLO与SSD

📅 发表日期: 2024年8月13日

分类: 📷OpenCV 教程

👁️阅读: --

目标检测是计算机视觉中的一个重要任务,涉及到在图片或视频中识别和定位多个对象。近年来,随着深度学习技术的快速发展,基于深度学习的目标检测方法得到了广泛的应用。其中,YOLO(You Only Look Once)和 SSD(Single Shot MultiBox Detector)是两个非常流行且高效的方法。在本篇教程中,我们将详细探讨这两种检测算法,包括它们的原理、实现以及如何在 OpenCV 中使用它们。

YOLO(You Only Look Once)

YOLO 是一种基于卷积神经网络(CNN)的实时目标检测系统。这种方法的主要思想是将整个图像作为网络的输入,并在单个前向传播中同时进行目标的定位和分类。与传统的目标检测方法不同,YOLO 将检测问题转化为回归问题。

YOLO 的工作原理

YOLO 将输入图像划分为 S x S 的网格,每个网格负责预测一个边界框和对应的类概率。每个网格单元输出的信息包括:

  • 边界框的中心坐标 (x,y)(x, y)
  • 边界框的宽度和高度 (w,h)(w, h)
  • 某个类的置信度 P(Class)P(Class)

最终,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