YOLO的Python实现以及 OpenCV - 教程

YOLOPython实现以及OpenCV

Darknet实现YOLO

从头开始开发YOLO模型不容易,故而大家要使用预训练模型在项目里进行目标检测。你可能在https://pjreddie.com里到所有可用的预训练模型。这是Joseph C. Redmon的主页,他是Darknet的维护者。

注意DarknetCCUDA开发的开源神经网络框架,它很快,很容易安装,支持CpU GpU计算。

在子页 (https://pjreddie.com/darknet/yolo/), 你可以找到 YOLO算法的所有信息。你可以从这个网页下载多个预训练模型的权重。对于每一个模型,你需要二个记录:

  • 一个.cfg文件,它包含网络结构.

  • 一个.weights文件,它涵盖训练后的权重

为了给你这些材料的内容,.cfg文件包含利用的层的信息等,示例如:

[convolutional]batch_normalize=1filters=64

size=3

stride=1pad=1

activation=leaky

这告诉你有特殊的卷积层。最关键的信息是:

  • Network architecture

  • Anchor boxes

  • Number of classes

  • Learning rate and other parameters used

  • Batch size

其它文件(.weights)具备预训练权重以进行推断。注意它们不能保存为Keras兼容的格式(.h5文件),所以它们不能加载到Keras模型,除非你先转换。

有一些非标准的工具可以转换这些文档,因为格式不是固定的( YOLOv2YOLOv3有些不同)。假如你感兴趣以YOLO v2,你可以使用YAD2K (另一个是Darknet 2 Keras),可以在https://github.com/allanzelener/YAD2K里找到。

注意这不能处理YOLOv3 .cfg材料。相信我,我试过。但是如果你满意YOLOv2,你可以用这个目录的代码转换.weight文件到Keras友好的格式。有个目录实现了YOLOv3 的转换,在https://github.com/qqwweee/keras-yolo3。它有些局限,只是它是转换的很好的起点。应用就是但是有便好的办法,使用预训练模型,那就OpenCV,后面我们会看到。

Darknet检测对象

假如你只是想对图像进行分类,最容易的办法是按darknet网站的指示。大家看一下如何做。如果你应用LinuxMacOS X系统,这些指令有用。Windows里,你要安装gcc和别的工具。如网站所述,安装只需要几行代码:

git clone https://github.com/pjreddie/darknetcd darknet

make

wget https://pjreddie.com/media/files/yolov3.weights

这里你就可以进行目标检测了:

./darknet detect cfg/yolov3.cfg yolov3.weights table.jpg

注意,权重文件很大,下载时要注意这一点,使用CPU这很慢,MacBook Pro 2018需要18秒来下载。见图7-2

7-2. YOLOv3使用darknet进行图像检测

黙认使用0.25通过的阈值。不过你能够运用不同的参数。你必须改变XYZ到你想要的值。

黙认使用0.25的阈值。但是你可能使用不同的参数。你必须改变XYZ到你想要的值。.

这个方法于于目标检测很好,但是很难在python项目里使用。要这样做,你需要在你的代码里使用预训练的模型。有几个方法,最容易的是运用opencv通过库。如果你处理图像,你很可能已经使用过这个库。要是你没有听说过,建议你试一下,因为它是处理图像很有名的库。你能够看官网https://opencv.org.

你可以在网上下载本章的完整代码,然而我们只简单的讨论重要的部分。

你需要安装最新的opencv库。用下面的代码检测版本:

import cv2

print (cv2. version )

我们需要从https://pjreddie.com下载三个记录:

  • coco.names

  • yolov3.cfg

  • yolov3.weights

coco.names包含了预训练模型能分类的标签。yolov3.cfgyolov3.weights是模型配置参数(前面已讨论过)且我们必须采用权重。为了你方便,yolov3.weights大约240MB容量,你可以下载ZIP 文件自http://toe.lt/r。在代码里我们需要指明文件在哪里。例如,你使用下面的代码:

weightsPath = "yolo-coco/yolov3.weights"configPath = "yolo-coco/yolov3.cfg"

你要改变文件的位置。OpenCV供应了函数来加载权重而不需要转换它们:

net = cv2.dnn.readNetFromDarknet(configPath, weightsPath)

这很舒服,由于你不应该分析和写加载函数。它返回模型对象供你后面推断。如果你记得本章开始的讨论,你要得到输出层来得到所有需要的信息,像边框和预测分类。我们用下面的代码很容易做到:

ln = net.getLayerNames()

ln = [ln[i[0] - 1] fori in net.getUnconnectedOutLayers()]

getUnconnectedOutLayers()函数返回带用unconnected输出的层, 正是我们想要的。ln这量含有下面的层:

['yolo_82', 'yolo_94', 'yolo_106']

然后我们要改变图像大小到416x416并归一化它:

blob = cv2.dnn.blobFromImage(image, 1/ 255.0, (416, 416),swapRB=True, crop=False)

然后用它作为模型的输入:

net.setInput(blob)

然后我们用forward()函数向前传递给训练模型:

layerOutputs = net.forward(ln)

预测分类就是我们还没有结束,不要休息。我们要提取边框,我们保存在列表里,然后是置信,继而.

我们初始化列表:

boxes = []confidences= []classIDs= []

之后我们遍历各层并提取我们要的信息。

for output in layerOutputs:for detection in output:

现在分数保存在第5个检测变量的元素里,我们提取分类用np.argmax(scores):

scores = detection[5:]classID = np.argmax(scores)

置信度是预测分类的分值:

confidence = scores[classID]

我们想要预测置信度大于0的。大家选择限度为0.15。预测边框包含于检测变量的前4个里:

box = detection[0:4] * np.array([W, H, W, H])(centerX, centerY, width, height) = box.astype("int")

要是你记得,YOLO预测边框的中心点,所在我们要的提取左上角位置:

x = int(centerX - (width/ 2))y = int(centerY - (height/ 2))

然后我们将发现的值添加到列表

boxes.append([x, y, int(width), int(height)])confidences.append(float(confidence))classIDs.append(classID)

然后我们应用non-maxima抑制(上一节讨论过)OpenCV也提供了函数:

idxs = cv2.dnn.NMSBoxes(boxes, confidences, 0.6,0.2)

函数需要下面的参数:

  • 边框集合(保存于boxes变量)

  • 置信度集合(保存于confidences变量)

  • 按分值过滤边框的阈值(前面代码是0.6)

  • non-maximum抑制的阈值(前面的代码是0.2)

然我们得到准确的位置:

for i in idxs.flatten():

# extract the bounding box coordinates(x, y)= (boxes[i][0], boxes[i][1])

(w, h) = (boxes[i][2], boxes[i][3])

你可以在图7-3看到结果。

7-3. YOLOv3OpenCV获得的结果

这正是它应有的与图7-2通过一样的结果。另外,大家有预测边框的概率。你能够看到这是多么的容易。你只需要添加几行代码到你的工程。

这正是它应有的与图7-2通过一样的结果。另外,我们有预测边框的概率。你能够看到这是多么的容易。你只得添加几行代码到你的任务。

记住大家使用预训练模型只能检测数据集里的对象。假如你要用不同的对象,你要微调模型,或重新训练模型。从头训练模型超出了本书的范围。可是下一节我会给你一些提示。

posted @ 2025-08-18 20:25  yfceshi  阅读(36)  评论(0)    收藏  举报