深度学习|目标检测与YOLO算法

这篇具有很好参考价值的文章主要介绍了深度学习|目标检测与YOLO算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、目标检测

1.1 目标检测概念

目标检测(object detection)是在给定的图片中精确找到物体所在位置,并标注出物体的类别。物体的尺寸变化范围很大,摆放物体的角度、姿态不确定,而且可以出现在图片任何地方,同时物体也可是多个类别的。

目标检测在多个领域中被广泛使用。例如,在无人驾驶领域,系统需要通过识别拍摄到的视频图像中车辆、行人、道路和障碍的位置来规划行进路线;在安保领域,系统需要检测异常目标,如歹徒或者危险品。

目标检测yolo算法,深度学习,目标检测,算法

 目标检测在目标定位基础上进一步开发,其与图片分类、目标定位的主要区别如下:

Image Classification Classification with Localization Object Detection
图片特点 包含比较大的单个物体 包含比较大的单个物体 包含多类物体
处理方法 将图片输入到多层卷积神经网络中 在图片分类基础上,使神经网络多输出4个单元用来表示物体的边界框(如红框所示) 在分类定位基础上,使神经网络多输出n个单元,代表物体是否属于该类别的物体
输出结果 是/否属于该类别 是/否属于该类别+该物体的位置信息 每个物体是否属于该类别+该物体的位置+是否属于n个类别
具体结果 1个代表属于某类别的值 1个代表属于某类别的值+4个代表边框的值 1个代表物体存在的值+n个属于某类别的值+4个代表边框的值

1.2 目标检测原理

1.2.1 基本原理

目标检测通常采用滑动窗口来进行,即使用一个小窗口,窗口截取到图片上的区域,将该区域输入到卷积神经网络,输出1或0代表该区域内是否有目标,并按照一定的步长滑动窗口,直到遍历整张图片。

目标检测yolo算法,深度学习,目标检测,算法

这种方法相当于对每个窗口的图片做了一个图片分类,但带来的是低计算成本和高精度难以同时满足的现实问题。

1.2.2 滑动窗口卷积实现

滑动窗口的卷积实现即在卷积层上应用这个算法。首先把神经网络的全连接层转化成卷积层, 全连接层可看作是进行一次卷积操作,但在把全连接层转化成卷积层之后,每个窗口截取到的区域存在共享的部分,将神经网络每层所有窗口共享的部分重叠在一起,相当于将整张图片输入神经网络得到的结果。

所以,不必将图片每个区域分别输入神经网络进行检测,直接将整张图片输入进行卷积操作,神经网络就可以识别出对象的位置。

目标检测yolo算法,深度学习,目标检测,算法

1.3 目标检测算法改善

1.3.1 交并比

交并比(IoU:Intersection over Union)函数是用于计算两个边界框交集和并集之比,即下图中S(绿色)/S(蓝色+绿色+黄色)的数值,常用来评价目标检测算法的精度。

目标检测yolo算法,深度学习,目标检测,算法

一般来说,IoU大于等于0.5时说明结果可以接受,即检测结果可接受。如果预测器和实际边界框完美重叠,loU就是1,因为交集就等于并集。通常规定0.5是阈值(threshold),用来判断预测的边界框是否正确,loU越高,边界框越精确。 

目标检测yolo算法,深度学习,目标检测,算法

1.3.2 非极大值抑制

当目标检测窗口格子划分较小时,会出现同时有几个格子里检测到有目标的情况。即图中的一辆汽车可能被检测到多次:

目标检测yolo算法,深度学习,目标检测,算法

可以采用非极大值抑制(Non-max suppression)的方法解决此问题。首先比较所有格子输出结果中检测到物体的概率,由大到小排序,保留概率最大的预测框,然后依次与比它小的预测框求交并比,若交并比很大,则说明这两个预测框很有可能检测的是同一个物体,于是把存在物体概率较低的那个预测框抑制掉。

下图显示的是抑制后的结果: 

目标检测yolo算法,深度学习,目标检测,算法

1.3.3 锚框

目标检测中存在一个问题就是每个格子只能预测一个对象,如果想让一个格子检测出多个对象,就要使用到锚框(Anchor Box)。 

目标检测yolo算法,深度学习,目标检测,算法

 如上图所示,我们使用3×3的网格,可以观察到人和汽车的几何中心几乎在同一个网格,然而传统方法中一个格子只能预测一个对象,而且对于y输出的向量可以检测这三个类别:人、汽车和摩托车,他将无法输出检测结果,所以我必须从两个检测结果中选择一个,这便影响了模型性能,导致一些对象被丢弃无法检测出来。

而引入锚框后,预先定义两个不同形状的锚框,把预测结果和这两个锚框关联起来:

目标检测yolo算法,深度学习,目标检测,算法

因此,定义类别标签时用的向量不再是:

而是重复两次:

前面8个是和Anchor box1相关联,后面8个是和Anchor box2相关联。行人一般符合anchor box1形状,所以用Anchor box1来预测行人回达到很好的效果,这么编码𝑝𝑐 = 1,代表有个行人,用𝑏𝑥, 𝑏𝑦, 𝑏ℎ和𝑏𝑤来编码包住行人的边界框,然后用𝑐1, 𝑐2, 𝑐3(𝑐1 = 1, 𝑐2 = 0, 𝑐3 = 0)来说明这个对象是行人。 汽车一般符合Anchor box2形状,所以用Anchor box2来预测汽车会有很好的效果。

1.4 目标检测程序实现

为说明目标检测基本原理,我们通过一个案例加以阐述。假设有如下一张图(左边是一只狗,右边是一只猫),他们共同构成了图像里的两个主要目标,我们需要对这两个目标进行识别并进行标注

目标检测yolo算法,深度学习,目标检测,算法

首先导入必要的包和模块:

%matplotlib inline
from PIL import Image
import sys
sys.path.append("..")
import d2lzh_pytorch as d2l

d2l.set_figsize()
img = Image.open('img/catdog.jpg') d2l.plt.imshow(img);
# 加分号只显示图

1.4.1 边界框的实现

在目标检测中,我们使用边界框(bounding box)来描述目标位置。边界框通常是一个矩形框,可以由矩形左上角的(x, y)坐标与右下角的(x, y)坐标确定。我们可以根据图中的坐标信息来定义图中猫和狗的边界框。图中坐标原点在图像左上角,原点往右和往下分别定义为x轴和y轴的正方向:

dog_bbox, cat_bbox = [60, 45, 378, 516], [400, 112, 655, 493]

我们可以在图中将边界框画出来检测其是否准确。我们定义一个辅助函数bbox_to_rect,通过其将边界框表示成matplotlib的边界框格式:

def bbox_to_rect(bbox, color):
    # 将边界框(左上x, 左上y, 右下x, 右下y)格式转换成matplotlib格式: 
    # ((左上x, 左上y), 宽, 高)
    return d2l.plt.Rectangle(
        xy=(bbox[0], bbox[1]), width=bbox[2]-bbox[0], 
        height=bbox[3]-bbox[1], fill=False, edgecolor=color, linewidth=2
        )

我们将边界框加载在图像上:

fig = d2l.plt.imshow(img)
fig.axes.add_patch(bbox_to_rect(dog_bbox, 'blue'))
fig.axes.add_patch(bbox_to_rect(cat_bbox, 'red'))

目标检测yolo算法,深度学习,目标检测,算法

 从输出结果可看出,猫和狗两个主要目标的轮廓都在边界框内。

1.4.2 锚框的实现

目标检测算法通常会在输入图像中采样大量区域,然后判断这些区域是否包含我们所要检测的目标,并调整区域边缘从而更准确地预测目标的真实边界框(ground-truth bounding box)。

不同模型使用的区域采样方法可能不同,若以每个像素为中心生成多个大小和宽高比(aspect ratio)不同的边界框,这些边界框就被称为锚框(anchor box)。

先导入相关包和库:

%matplotlib inline
from PIL import Image
import numpy as np
import math
import torch

import sys sys.path.append("..")
import d2lzh_pytorch as d2l

假设输入图像高为h,宽为w。我们分别以图像的每个像素为中心生成不同形状的锚框。设大小为s∈(0,1]且宽高比为r >0,那么锚框的宽和高将分别 为𝑤𝑠𝑟^0.5 和h𝑠𝑟^0.5。当中心位置给定时,已知宽和高的锚框是确定的。

下面我们分别设定好一组大小s1,...,sn和一组宽高比r1,...,rm。如果以每个像素为中心时使用所有的大小与宽高比的组合,输入图像将一共得到 w*h*n*m个锚框。虽然这些锚框可能覆盖了所有的真实边界框,但计算复杂度容易过高。因此,以相同像素为中心的锚框的数量为n+m−1。对于整个输入图像,我们将一共生成w*h(n+m−1)个锚框。

以上生成锚框的方法通过下述的MultiBoxPrior函数实现。当制定输入一组大小和一组宽高比时,该函数将返回输入的所有锚框:

d2l.set_figsize()
img = Image.open('img/catdog.jpg')
w, h = img.size
print("w = %d, h = %d" % (w, h)) # w = 728, h = 561
def MultiBoxPrior(
    feature_map, sizes=[0.75, 0.5, 0.25], ratios=[1, 2, 0.5])
pairs = [] # pair of (size, sqrt(ration))
    for r in ratios:
        pairs.append([sizes[0], math.sqrt(r)])
    for s in sizes[1:]:
        pairs.append([s, math.sqrt(ratios[0])])
    pairs = np.array(pairs)
    ss1 = pairs[:, 0] * pairs[:, 1] # size * sqrt(ration)
    ss2 = pairs[:, 0] / pairs[:, 1] # size / sqrt(ration)
    base_anchors = np.stack([-ss1, -ss2, ss1, ss2], axis=1) / 2
    h, w = feature_map.shape[-2:]
    shifts_x = np.arange(0, w) / w
    shifts_y = np.arange(0, h) / h
    shift_x, shift_y = np.meshgrid(shifts_x, shifts_y)
    shift_x = shift_x.reshape(-1)
    shift_y = shift_y.reshape(-1)

shifts_x和shifts_y是将宽高进行归一化处理然后用meshgrid函数生成一个向量矩阵, 最后reshape成一行向量。

    shifts = np.stack((shift_x, shift_y, shift_x, shift_y), axis=1)
    anchors = shifts.reshape(
              (-1, 1, 4)) + base_anchors.reshape((1, -1, 4))
    return torch.tensor(anchors, dtype=torch.float32).view(1, -1, 4)
X = torch.Tensor(1, 3, h, w) # 构造输入数据
Y = MultiBoxPrior(X, sizes=[0.75, 0.5, 0.25], ratios=[1, 2, 0.5])
Y.shape # torch.Size([1, 2042040, 4])

将reshape之后的向量进行stack操作,之后将得到的shift与原始的base_anchors相加从而自动生成所有的anchor。

下面的例子里 我们访问以(250,250)为中心的第一个锚框。它有4个元素,分别是锚框 左上角的x和y轴坐标和右下角的x和y轴坐标,其中x和y轴的坐标值分别已除 以图像的宽和高,因此值域均为0和1之间。

boxes = Y.reshape((h, w, 5, 4))
boxes[250, 250, 0, :]# * torch.tensor([w, h, w, h],
dtype=torch.float32)

输出如下:

tensor([-0.0316,  0.0706,  0.7184,  0.8206])

为了描绘图像中以某个像素为中心的所有锚框,我们先定义show_bboxes函 数以便在图像上画出多个边界框:

def show_bboxes(axes, bboxes, labels=None, colors=None): 
    def _make_list(obj, default_values=None):
        if obj is None:
            obj = default_values
        elif not isinstance(obj, (list, tuple)):
            obj = [obj]
        return obj
    labels = _make_list(labels)
    colors = _make_list(colors, ['b', 'g', 'r', 'm', 'c'])

为了描绘图像中以某个像素为中心的所有锚框,我们先定义show_bboxes函 数以便在图像上画出多个边界框:

for i, bbox in enumerate(bboxes):
    color = colors[i % len(colors)]
    rect = d2l.bbox_to_rect(bbox.detach().cpu().numpy(), color)#画出边界框
    axes.add_patch(rect)
    if labels and len(labels) > i:
        text_color = 'k' if color == 'w' else 'w'
        axes.text(
                rect.xy[0], rect.xy[1], labels[i],
                va='center', ha='center', fontsize=6, color=text_color,
                bbox=dict(facecolor=color, lw=0)
                )

变量boxes中xx和yy轴的坐标值分别已除以图像的宽和高。在 绘图时,我们需要恢复锚框的原始坐标值,并因此定义了变量bbox_scale,我们可以画出图像中以(250, 250)为中心的所有锚框了。可以看到,大小为 0.75且宽高比为1的锚框较好地覆盖了图像中的狗:

d2l.set_figsize()
fig = d2l.plt.imshow(img)
bbox_scale = torch.tensor([[x, y, w, h]], dtype=torch.float32)
show_bboxes(fig.axes, boxes[250, 250, :, :] * bbox_scale,['s=0.75, r=1', 's=0.75, r=2', 's=0.55,r=0.5', 's=0.5, r=1', 's=0.25, r=1'])

输出如下: 

目标检测yolo算法,深度学习,目标检测,算法

二、YOLO算法

2.1 YOLO算法简述

YOLO(You Only Look Once)是一种基于深度学习的目标检测算法,由Joseph Redmon等人在2015年提出,其最新版本为YOLOv5。

与传统目标检测算法相比,YOLO算法具有以下优点:

  1. 速度快:YOLO算法采用全卷积神经网络实现,可以实现实时目标检测;
  2. 准确率高:YOLO算法采用单个网络结构,能够同时检测多个目标并获得更准确的边界框;
  3. 应用广泛:YOLO算法可处理各种尺寸的物体,不需要对图像进行缩放和裁剪,能够处理任意大小的物体。

YOLO算法的基本思路是将输入图像分割成多个网格,然后对每个网格预测物体的类别和位置。具体来说,YOLO算法采用单个卷积神经网络,在图像的全局信息和局部信息之间进行平衡,并直接预测出每个物体的边界框和类别。

YOLO算法的主要步骤如下:

  1. 将输入图像分成S×S个网格;
  2. 对于每个网格,预测该网格中是否包含物体,以及该物体的边界框和类别;
  3. 计算每个预测边界框与真实边界框之间的损失,更新网络参数;
  4. 在测试阶段,将所有预测边界框进行筛选,得到最终的检测结果。

虽然YOLO算法具有很高的速度和准确率,但其也存在一些缺点,如对小物体的检测效果较差,对于密集目标的检测效果也不尽如人意。此外,YOLO算法的训练过程也较为复杂,需要大量的训练数据和计算资源。

2.2 YOLO v1算法

学习该算法前,首先要分清预测阶段训练阶段。预测阶段是用已经训练好的、现成的网络,去对图片做预测,即做目标检测;训练阶段是利用梯度下降和反向传播来迭代地微调神经元中的权重,并使损失函数最小化,来训练得到一个预测效果更好的模型。

2.2.1 预测阶段

预测阶段使用训练好的卷积神经网络结构如下:

输入 卷积层(24层) 全连接层(2层) 输出
448×448×3的图像 与7×7的过滤器、3×3的过滤器做卷积,最终得到7×7×1024的特征图 拉平填充输入4096个神经元中,再输入到1470个神经元中 将全连接层的输出重塑为7×7×30的张量

目标检测yolo算法,深度学习,目标检测,算法

最后输出的7×7×30的张量中,7×7的原因是yolo将输入的图片划分为7×7的网格,每一个网格需要输出的是一个1×30维的信息,所以最后的输出为7×7×30,输出可视化如下图:

目标检测yolo算法,深度学习,目标检测,算法

YOLO v1是一个单阶段的、端到端的算法,7×7×30的输出包括所有目标的置信度、预测框坐标、类别,上图中以框的粗细代表置信度的高低。 对于每个网格,它都会产生两个预测框,这两个预测框的中心点都落在该网格中,所以YOLO v1最后一共会产生98个预测框。

对于这98个预测框,并不是所有预测框都会被保留,需要进行一系列后处理,将最终结果表现为上图的结果那样。后处理步骤主要包括:置信度过滤(去掉低置信度的预测框)和非极大值抑制(去掉对同一个物体重复检测的预测框)。

首先是置信度过滤,它指的是置信度×每个类别的概率。对于这98个1×20维向量来说,每个向量中同一个位置的值都代表该预测框预测到某种类别的概率,我们可以设定一个阈值,小于这个阈值的全部设为0。

目标检测yolo算法,深度学习,目标检测,算法

其次是非极大值抑制,当得到的每个预测框对某些种类预测的置信度都比较高时,对于某一种类,我们将该种类所在位置的概率从高到低排,再对排序之后的结果进行非极大值抑制。 

目标检测yolo算法,深度学习,目标检测,算法

具体步骤为:除去最高概率,剩下的每一个值代表的预测框都与最高值的预测框计算IoU,如果IoU大于我们设定的阈值,我们就认为这两个框检测的是同一个目标,那么就将较低的概率值置0,否则保留。

目标检测yolo算法,深度学习,目标检测,算法

第一轮比较完成后,除去最高的概率和第二高的概率,剩下概率代表的预测框与第二高的概率的预测框计算IoU,重复上述步骤,直至到达最后一个概率。 

目标检测yolo算法,深度学习,目标检测,算法

对于每个类别都重复上面步骤,完成所有输出的后处理并可视化在图上,即为目标检测的结果。

2.2.2 训练阶段

在训练阶段,每个网格会产生出两个预测框,我们将与ground truth中IoU较大的预测框作为负责拟合ground truth的框,与ground truth的IoU较小的预测框的置信度越低越好。

然后设计一个损失函数,来使负责拟合ground truth的框作为损失函数的最大组成,另一个框的让它的影响尽量的小。损失函数主要由三大部分、五小部分组成:坐标回归误差(主预测框中心点坐标误差+主预测框宽高误差)+置信度回归误差(主预测框置信度误差+另一预测框置信度误差)+类别预测误差(主预测框分类误差)。

2.2.3 优缺点分析

YOLO v1的优缺点主要如下:文章来源地址https://www.toymoban.com/news/detail-763677.html

优点 缺点
单阶段模型,速度很快 输入图像分辨率低,准确率低,定位性能差
能获取全图信息,更好辨别前景和背景 每个网络只能预测一个物体
捕获全图信息,学习能力强 所有网格只能预测7×7=49个物体,小目标和密集目标识别性能差

到了这里,关于深度学习|目标检测与YOLO算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包