在机器学习和深度学习领域,目标检测是一个非常重要的任务。它涉及到从图像或视频中识别和定位感兴趣的对象。然而,从头开始训练一个模型不仅需要大量的计算资源,而且耗时较长。为了提高效率,转向了速度优先的解决方案。目前,You Only Look Once (YOLO) 是最流行的目标检测方法之一。
YOLO算法的核心思想是,只需一次前向传播就能在给定的图像中检测到对象。这种特性使得YOLO能够以最小的延迟处理实时视频,同时保持合理的准确度。
首先需要导入必要的库。在这个例子中,将使用Keras进行实现。
import cv2
import numpy as np
由于使用的是预训练模型,因此需要下载一些权重和配置文件。可以从指定的链接下载权重文件和配置文件。指定的模型是在MS COCO数据集上训练的,能够识别80个类别的对象。可以从链接下载或复制coco.names文件。
下载所需的文件后,可以继续创建和加载模型。OpenCV提供了一个readNet函数,用于将深度学习网络加载到系统中。深度学习网络必须以支持的格式之一表示,如xml和prototxt。加载模型后,将从coco.names文件中获取模型要识别的类别。然后使用getLayerNames函数检索输出层,并使用getUnConnectedOutLayers函数将它们存储为输出层列表。
# Use readNet to load Yolo
net = cv2.dnn.readNet("./yolov3.weights", "./yolov3.cfg")
# Classes
Classes = []
with open("coco.names", "r") as f:
classes = [line.strip() for line in f.readlines()]
# Define Output Layers
layer_names = net.getLayerNames()
output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
现在可以将图像传递给模型,但模型期望输入图像具有特定的形状。为了使图像的形状与模型输入兼容,将使用blobFromImage函数。该函数将重塑图像并重新排序图像的颜色通道。然后将图像传递给模型以执行前向传播。前向传播输出检测列表。
# reshape, normalize and re-order colors of image using blob
blob = cv2.dnn.blobFromImage(img, 1/255, (416, 416), (0, 0, 0), True, crop=False)
# blob as input
net.setInput(blob)
# Object Detection
results = net.forward(outputlayers)
可以使用这个输出结果来获取每个检测到的对象的边界框坐标。如前所述,然后使用阈值来获取准确的边界框。
# Evaluate class ids, confidence score and bounding boxes for detected objects
class_ids = []
confidences = []
boxes = []
confidence_threshold = 0.5
for result in results:
for detection in result:
scores = detection[5:]
class_id = np.argmax(scores)
confidence = scores[class_id]
if confidence > confidence_threshold:
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)
现在已经得到了边界框坐标,可以继续在检测到的对象上绘制框并标记它。但事先并不知道任何给定对象的出现次数。为了解决这个问题,将使用NMSBoxes函数,它采用非最大抑制。之后,最终显示图像。
# Non-max Suppression
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.4, 0.6)
# Draw final bounding boxes
font = cv2.FONT_HERSHEY_PLAIN
count = 0
for i in range(len(boxes)):
if i in indexes:
x, y, w, h = boxes[i]
label = str(classes[class_ids[i]])
color = COLORS[i]
cv2.rectangle(img, (x, y), (x+w, y+h), color, 2)
cv2.putText(img, label, (x, y-5), font, 1, color, 1)
最后一步是将所有部分整合在一起,并显示检测到的对象的最终图像。
cv2.imshow("Detected_Images", img)
MS COCO数据集可以识别80个不同的类别,包括人。可以通过统计类别‘人’的出现次数,轻松地计算图像中存在的人数。
if int(class_ids[i] == 0):
count += 1