YOLOv3 实时目标检测算法解析

YOLOv3算法,由Joseph Redmon、Santosh Divvala、Ross Girshick和Ali Farhadi提出,是一种用于实时目标检测的高效卷积神经网络CNN)。与传统的目标检测方法不同,YOLOv3算法只需对输入图像进行一次前向传播即可完成预测,因此得名“You Only Look Once”。这种算法因其高准确率和实时性而广受欢迎,适用于需要快速响应的场景。

在以往的目标检测系统中,通常会使用定位器或分类器来执行检测过程,然后将模型应用于图像的不同尺度和位置。而YOLO算法则采用全新的方法,它将整个图像作为一个整体输入到单一的神经网络中,然后该网络将图像划分为多个区域,并为每个区域生成边界框以及预测概率。这些生成的边界框会根据预测概率进行加权。

YOLOv3的架构包含24个卷积层和2个全连接层。前20个卷积层后接平均池化层和全连接层,这部分是在使用ImageNet数据集上进行预训练的,ImageNet是一个包含1000类分类的数据集。预训练时使用的图像分辨率为224x224x3。这些层包括3x3的卷积层和1x1的降维层。对于目标检测,最后添加了4个卷积层和2个全连接层来训练网络。由于目标检测需要更精确的细节,因此数据集的分辨率增加到448x448。最终层预测类别概率和边界框。除了最终层使用线性激活函数外,所有其他卷积层都使用leaky ReLU激活函数。输入图像的尺寸为448x448,输出为检测到的对象的类别预测,包含在边界框内。

要实现YOLOv3,首先需要下载预训练的权重和配置文件。可以从以下链接下载YOLOv3-320和YOLOv3-tiny的权重和配置文件:

https://pjreddie.com/darknet/yolo/

接下来,安装OpenCV版本3.4.2.16:

pip install opencv-python==3.4.2.16

下载coco.names文件,并将其放置在项目目录中。

以下是使用预训练权重实现YOLOv3的步骤。首先定义输入,这里使用摄像头实时输入。设置检测置信度阈值和非最大抑制阈值:

import cv2 import numpy as np cap = cv2.VideoCapture(0) whT = 320 confThreshold = 0.5 nmsThreshold = 0.3

然后读取coco.names文件中的类别:

classesFile = 'coco.names' classNames = [] with open(classesFile,'rt') as f: classNames = f.read().rstrip('n').split('n')

初始化权重和配置文件,这里选择了yolov3-tiny,也可以选择yolov3-320。使用OpenCV的darknet模块读取模型配置文件和模型权重文件:

modelConfiguration = 'yolov3.cfg' modelWeights = 'yolov3.weights' net = cv2.dnn.readNetFromDarknet(modelConfiguration, modelWeights) net.setPreferableBackend(cv2.dnn.DNN_BACKEND_DEFAULT) net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU) def findObjects(outputs,img): hT, wT, cT = img.shape bbox = [] classIds = [] confs = [] for output in outputs: for det in output: scores = det[5:] classId = np.argmax(scores) confidence = scores[classId] if confidence > confThreshold: w,h = int(det[2]* wT), int(det[3]*hT) x,y = int((det[0]*wT)-w/2), int((det[1]*hT)-h/2) bbox.append([x,y,w,h]) classIds.append(classId) confs.append(float(confidence)) indices = cv2.dnn.NMSBoxes(bbox, confs,confThreshold,nmsThreshold) for i in indices: i = i[0] box = bbox[i] x,y,w,h = box[0], box[1], box[2], box[3] cv2.rectangle(img, (x,y),(x+w,y+h),(255,0,255),2) cv2.putText(img,f'{classNames[classIds[i]].upper()} {int(confs[i]*100)}%',(x,y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6,(255,0,255),2) while True: success, img = cap.read() blob = cv2.dnn.blobFromImage(img, 1/255,(whT,whT),[0,0,0],crop=False) net.setInput(blob) layerNames = net.getLayerNames() outputNames = [layerNames[i[0]-1] for i in net.getUnconnectedOutLayers()] outputs = net.forward(outputNames) findObjects(outputs,img) cv2.imshow('Image', img) cv2.waitKey(1)
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485