YOLOV5详细解读

这篇具有很好参考价值的文章主要介绍了YOLOV5详细解读。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

YOLOV5检测算法详解

学习前言

本文主要是对基于深度学习的目标检测算法进行细节解读,以YOLOV5为例;

基于深度学习的目标检测整体流程

基于深度学习的目标检测主要包括训练和测试两个部分。
YOLOV5详细解读
YOLOV5详细解读

训练阶段

训练的目的是利用训练数据集进行检测网络的参数学习,其中训练数据集包含大量的视觉图像和标注信息(物体位
置及类别)。训练阶段的主要过程包括数据预处理、检测网络以及标签匹配与损失计算等部分。

1.数据预处理

数据预处理的目的在于增强训练数据多样性,进而提升检测网络的检测能力。
YOLOV5所采用的预处理方式主要有:翻转、缩放、扭曲、色域变换、Mosaic
翻转:

image = image.transpose(Image.FLIP_LEFT_RIGHT)  #利用PIL库对图片直接翻转
box[:, [0,2]] = iw - box[:, [2,0]] #翻转图片后要对目标框同时进行调整

缩放:

#由于实际图像w和h不是相等的,所以采用不失真的resize,将长边resize到和输入尺寸一样大小,然后其余部分
放上灰条

scale = min(w/iw, h/ih) #iw、ih是数据集中图像实际尺寸,w,h为网络输入的图像尺寸,scale为图像缩放因子
nw = int(iw*scale) #图像宽缩放后尺寸
nh = int(ih*scale) #图像长缩放后尺寸
dx = (w-nw)//2  #缩放后图像放在灰度图像上的位置
dy = (h-nh)//2 #缩放后图像放在灰度图像上的位置
image   = image.resize((nw,nh), Image.BICUBIC)  #将输入图像插值到实际缩放后的尺寸大小
new_image   = Image.new('RGB', (w,h), (128,128,128)) #生成一个三通的,大小为(w,h)的灰度图像
new_image.paste(image, (dx, dy)) #将缩放后的实际图像放在灰度图像 (dx, dy)的位置上
image_data  = np.array(new_image, np.float32) #再转换成数组格式

扭曲:

new_ar = iw/ih * self.rand(1-jitter,1+jitter) / self.rand(1-jitter,1+jitter) #iw、ih是数据集中图像实际尺寸,jitter扭曲因子
scale = self.rand(.25, 2)
if new_ar < 1:
   nh = int(scale*h)
   nw = int(nh*new_ar)
else:
   nw = int(scale*w)
   nh = int(nw/new_ar)
   image = image.resize((nw,nh), Image.BICUBIC)

色域变换:

r  = np.random.uniform(-1, 1, 3) * [hue, sat, val] + 1
hue, sat, val   = cv2.split(cv2.cvtColor(image_data, cv2.COLOR_RGB2HSV)) #j将图片转换成HSV格式,再把每个通道分离开来
dtype  = image_data.dtype
x  = np.arange(0, 256, dtype=r.dtype)
lut_hue = ((x * r[0]) % 180).astype(dtype)
lut_sat = np.clip(x * r[1], 0, 255).astype(dtype)
lut_val = np.clip(x * r[2], 0, 255).astype(dtype)
image_data = cv2.merge((cv2.LUT(hue, lut_hue), cv2.LUT(sat, lut_sat), cv2.LUT(val, lut_val))) image_data = cv2.cvtColor(image_data, cv2.COLOR_HSV2RGB)

Mosaic:

train_annotation_path = '1.txt'
with open(train_annotation_path, encoding='utf-8') as f:
    train_lines = f.readlines()
jitter = 0.3
h, w = [640,640]
min_offset_x = rand(0.3, 0.7)
min_offset_y = rand(0.3, 0.7)
image_datas = []
box_datas   = []
index       = 0
lines = sample(train_lines, 3)
lines.append(train_lines[index])
shuffle(lines)  #从训练集中随机取4张图片进行拼接
for line in lines:
    line_content = line.split()
    image = Image.open(line_content[0])
    image = cvtColor(image)
    iw, ih = image.size
    box = np.array([np.array(list(map(int,box.split(',')))) for box in line_content[1:]])
    new_ar = iw / ih * rand(1 - jitter, 1 + jitter) / rand(1 - jitter, 1 + jitter)
    scale = rand(.4, 1)
    if new_ar < 1:
        nh = int(scale * h)
        nw = int(nh * new_ar)
    else:
        nw = int(scale * w)
        nh = int(nw / new_ar)
    image = image.resize((nw, nh), Image.BICUBIC)
    if index == 0:  #分别计算出四张图片分别摆放的位置
        dx = int(w * min_offset_x) - nw
        dy = int(h * min_offset_y) - nh
    elif index == 1:
        dx = int(w * min_offset_x) - nw
        dy = int(h * min_offset_y)
    elif index == 2:
        dx = int(w * min_offset_x)
        dy = int(h * min_offset_y)
    elif index == 3:
        dx = int(w * min_offset_x)
        dy = int(h * min_offset_y) - nh
    new_image = Image.new('RGB', (w, h), (128, 128, 128))
    new_image.paste(image, (dx, dy))
    image_data = np.array(new_image)

    index = index + 1
    box_data = []
    if len(box) > 0:  #对box重新进行处理,超出边界,都要将其限制在图像里面
        np.random.shuffle(box)
        box[:, [0, 2]] = box[:, [0, 2]] * nw / iw + dx
        box[:, [1, 3]] = box[:, [1, 3]] * nh / ih + dy
        box[:, 0:2][box[:, 0:2] < 0] = 0
        box[:, 2][box[:, 2] > w] = w
        box[:, 3][box[:, 3] > h] = h
        box_w = box[:, 2] - box[:, 0]
        box_h = box[:, 3] - box[:, 1]
        box = box[np.logical_and(box_w > 1, box_h > 1)]
        box_data = np.zeros((len(box), 5))
        box_data[:len(box)] = box

    image_datas.append(image_data)
    box_datas.append(box_data)
cutx = int(w * min_offset_x)
cuty = int(h * min_offset_y)
new_image = np.zeros([h, w, 3])
new_image[:cuty, :cutx, :] = image_datas[0][:cuty, :cutx, :]
new_image[cuty:, :cutx, :] = image_datas[1][cuty:, :cutx, :]
new_image[cuty:, cutx:, :] = image_datas[2][cuty:, cutx:, :]
new_image[:cuty, cutx:, :] = image_datas[3][:cuty, cutx:, :] 
new_image       = np.array(new_image, np.uint8)
merge_bbox = []
for i in range(len(bboxes)): #在四张拼接图上面对框进行调整,防止其超出界限
    for box in bboxes[i]:
          tmp_box = []
          x1, y1, x2, y2 = box[0], box[1], box[2], box[3]

          if i == 0:
             if y1 > cuty or x1 > cutx:
                  continue
             if y2 >= cuty and y1 <= cuty:
                        y2 = cuty
             if x2 >= cutx and x1 <= cutx:
                        x2 = cutx

           if i == 1:
                    if y2 < cuty or x1 > cutx:
                        continue
                    if y2 >= cuty and y1 <= cuty:
                        y1 = cuty
                    if x2 >= cutx and x1 <= cutx:
                        x2 = cutx

            if i == 2:
                    if y2 < cuty or x2 < cutx:
                        continue
                    if y2 >= cuty and y1 <= cuty:
                        y1 = cuty
                    if x2 >= cutx and x1 <= cutx:
                        x1 = cutx

             if i == 3:
                    if y1 > cuty or x2 < cutx:
                        continue
                    if y2 >= cuty and y1 <= cuty:
                        y2 = cuty
                    if x2 >= cutx and x1 <= cutx:
                        x1 = cutx
             tmp_box.append(x1)
             tmp_box.append(y1)
             tmp_box.append(x2)
             tmp_box.append(y2)
             tmp_box.append(box[-1])
             merge_bbox.append(tmp_box)
2.检测网络

检测网络一般包括主干特征提取网络、特征融合网络以及预测网络

主干特征提取网络
YOLOV5采用CSPDarknet作为特征提取网络,结构如图所示:
YOLOV5详细解读
(1)Focus结构
实际上就是矩阵的切片索引操作,在每个通道上的w和h方向上分别每隔一个像素点进行取值,最终一个通道图像变成四个通道图像,最终3通道变成12通道,将图片空间信息转换到通道维度,
YOLOV5详细解读

class Focus(nn.Module):
    def __init__(self, c1, c2, k=1, s=1, p=None, g=1, act=True):  # ch_in, ch_out, kernel, stride, padding, groups
        super(Focus, self).__init__()
        self.conv = Conv(c1 * 4, c2, k, s, p, g, act)

    def forward(self, x):
        return self.conv(torch.cat([x[..., ::2, ::2], x[..., 1::2, ::2], x[..., ::2, 1::2], x[..., 1::2, 1::2]], 1))

(2)Csplayer结构
借鉴了CSPnet结构,实际上是残差结构里面嵌套着残差结构,self.cv2是是大残差边,self.m是嵌套的残差结构,

class C3(nn.Module):
    # CSP Bottleneck with 3 convolutions
    def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, number, shortcut, groups, expansion
        super(C3, self).__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(2 * c_, c2, 1)  # act=FReLU(c2)
        self.m = nn.Sequential(*[Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)])

    def forward(self, x):
        return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), dim=1))

class Bottleneck(nn.Module):
    # Standard bottleneck
    def __init__(self, c1, c2, shortcut=True, g=1, e=0.5):  # ch_in, ch_out, shortcut, groups, expansion
        super(Bottleneck, self).__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c_, c2, 3, 1, g=g)
        self.add = shortcut and c1 == c2

    def forward(self, x):
        return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))

(3)SPP结构
通过不同池化核大小的最大池化进行特征提取,提高网络的感受野。

class SPP(nn.Module):
    # Spatial pyramid pooling layer used in YOLOv3-SPP
    def __init__(self, c1, c2, k=(5, 9, 13)):
        super(SPP, self).__init__()
        c_ = c1 // 2  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c_ * (len(k) + 1), c2, 1, 1)
        self.m = nn.ModuleList([nn.MaxPool2d(kernel_size=x, stride=1, padding=x // 2) for x in k])

    def forward(self, x):
        x = self.cv1(x)
        return self.cv2(torch.cat([x] + [m(x) for m in self.m], 1))

YOLOV5详细解读

特征聚合网络
YOLOV5是采用FPN+PAN的结构进行特征聚合,将主干网络后三部分提取的特征层进行聚合,浅层特征通过下采样,与深层特征进行拼接,深层特征也会采用上采样,与浅层特征进行拼接,同时还会采用借鉴CSPnet设计的CSP2结构,加强网络特征融合的能力。

预测网络
YOLOV5采用一个卷积层得到最后的结果

yolo_head = nn.Conv2d(c1, len(anchors_mask[2]) * (5 + num_classes), 1) #最后的输出通道数为3个特征层上的预测结果,包括预测框四个参数、置信度、,所有类别的概率
3.标签分配与损失计算

标签分配主要是为检测器预测提供真实值,在目标检测中,标签分配的准则包括交并比准则、距离准则、似然估计准则、二分匹配。然后基于标签分类的结果,采用损失函数计算分类和回归等任务的损失,并利用反向传播算法更新检测网络的权重,常用的分类损失函数有交叉熵损失函数、聚焦损失函数、平滑L1损失函数‘、交并比IOU损失函数、GIOU损失函数

YOLOV5
训练时正样本的选取分为两步:寻找最优先验框;匹配特征点;
寻找最优先验框
YOLOV5在三个特征层上设置了9个先验框,用这9个先验框和GT进行宽高比的计算,将先验框宽高除以GT宽高,同时GT宽高除以先验框宽高,取二者中的大值,然后将这9个比值和提前设置好的阈值进行对比,小于阈值,就说明该先验框的大小是和真实框比较接近的,可以用来作为正样本进行训练的

匹配特征点
我们在上一步选取了最优先验框,确定好了尺寸,但是还没有确定先验框的位置,所以我们计算真实框落在哪个网格内,则该网格的左上角特征点则为一个负责预测的特征点,同时为了增加正样本的数量,找出离真实框中心点最近的两个网格,因此一个真实框会对应三个特征点,每个特征点上的先验框大小由上一步确定。

损失计算
损失由三部分组成,回归损失、置信度损失、分类损失;
回归损失:利用网络得到的调整参数,对之前取得的先验框进行就算修正,得到预测框,利用真实框和预测框计算IOU损失;

置信度损失:根据特征点和正负样本是否包含物体计算交叉熵损失;

分类损失:根据真实框的种类和预测结果的种类计算交叉熵损失;

测试阶段

将测试图像输入训练好的检测网络中,得到预测结果,然后进行解码、非极大值抑制等后处理操作,最终识别出图像中存在物体的类别及位置信息;

NMS
非极大值抑制实际上跟冒泡排序原理是一样的,只不过,nms要先取出某一类别的置信度最大的那个预测框,然后将它和其他剩下的预测框进行IOU计算,如果重叠较大,则将该预测框删掉,如果重叠较小,也会同时将该框进行输出;知道所有重叠较大的预测框被剔除掉;

参考了Bubbliiiing大佬的代码和博客,十分感谢文章来源地址https://www.toymoban.com/news/detail-445201.html

到了这里,关于YOLOV5详细解读的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • YOLOv5目标检测学习(1):yolo系列算法的基础概念

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 关于深度学习目标检测,有许多概念性的东西需要先了解一下。这里主要以基于深度学习的目标检测算法的部署实现来学习。 以yolov5为例: 使用YOLOv5进行车辆和行人的目标检测通常涉及以下步骤: 数据

    2024年04月09日
    浏览(54)
  • YOLOV5详细解读

    本文主要是对基于深度学习的目标检测算法进行细节解读,以YOLOV5为例; 基于深度学习的目标检测主要包括训练和测试两个部分。 训练阶段 训练的目的是利用训练数据集进行检测网络的参数学习,其中训练数据集包含大量的视觉图像和标注信息(物体位 置及类别)。训练阶

    2024年02月04日
    浏览(37)
  • 深度学习||YOLO(You Only Look Once)深度学习的实时目标检测算法(YOLOv1~YOLOv5)

    目录 YOLOv1: YOLOv2: YOLOv3: YOLOv4: YOLOv5: 总结: YOLO(You Only Look Once)是一系列基于深度学习的实时目标检测算法。 自从2015年首次被提出以来,YOLO系列不断发展,推出了多个版本,包括YOLOv1, YOLOv2, YOLOv3, YOLOv4, 和YOLOv5等。下面是对YOLO系列的详解: 提出时间 : 2015年。 主要贡献 :

    2024年02月20日
    浏览(51)
  • YOLOv5 + Flask + Vue实现基于深度学习算法的垃圾检测系统源码+数据库

    YOLOv5🚀 :高效、准确的目标检测算法,实时识别检测图像和视频中的各种对象 PyTorch :机器学习框架,以动态计算图为基础,具有灵活性和易用性 OpenCV :计算机视觉库,提供了丰富的图像和视频处理功能 Vue3 :采用 Vue3 + script setup 最新的 Vue3 组合式 API Element Plus :Element

    2024年02月22日
    浏览(41)
  • 【计算机视觉面经四】基于深度学习的目标检测算法面试必备(RCNN~YOLOv5)

    目标检测算法主要包括:【两阶段】目标检测算法、【多阶段】目标检测算法、【单阶段】目标检测算法。 什么是两阶段目标检测算法,与单阶段目标检测有什么区别? 两阶段目标检测算法因需要进行两阶段的处理:1)候选区域的获取,2)候选区域分类和回归,也称为基于

    2024年03月27日
    浏览(58)
  • 目标检测论文解读复现之十:基于YOLOv5的遥感图像目标检测(代码已复现)

    前言        此前出了目标改进算法专栏,但是对于应用于什么场景,需要什么改进方法对应与自己的应用场景有效果,并且多少改进点能发什么水平的文章,为解决大家的困惑,此系列文章旨在给大家解读最新目标检测算法论文,帮助大家解答疑惑。解读的系列文章,本人

    2024年02月06日
    浏览(40)
  • 目标检测算法之YOLOv5在乒乓球赛事中运动员行为分析领域的应用实例详解(基础版--上)

    目录 YOLOv5乒乓球赛事中运动员行为分析 优化措施 优化代码 继续优化 在乒乓球赛事中,YOLOv5可以应用于运动员行为分析,通过实时识别和追踪运动员的动作,帮助教练分析技术动作,或者为观众提供更丰富的观赛体验。下面是一个简单的应用实例和相关代码片段。 首先,需

    2024年02月22日
    浏览(81)
  • YOLOv5源码逐行超详细注释与解读(5)——配置文件yolov5s.yaml

    在YOLOv5中网络结构采用 yaml 作为配置文件,之前我们也介绍过,YOLOv5配置了4种不同大小的网络模型,分别是 YOLOv5s、YOLOv5m、YOLOv5l、YOLOv5x ,这几个模型的结构基本一样, 不同的是depth_multiple模型深度和width_multiple模型宽度这两个参数 。 就和我们买衣服的尺码大小排序一样,

    2023年04月16日
    浏览(47)
  • 目标检测算法之YOLOv5的应用实例(零售业库存管理、无人机航拍分析、工业自动化领域应用的详解)

    在零售业库存管理中,YOLOv5可以帮助自动化商品识别和库存盘点过程。通过使用深度学习模型来实时识别货架上的商品,零售商可以更高效地管理库存,减少人工盘点的时间和成本。以下是一个使用YOLOv5进行商品识别的Python脚本示例:

    2024年02月20日
    浏览(77)
  • yolov5行人检测算法

    PaddleDetection/pphuman_mot.md at release/2.6 · PaddlePaddle/PaddleDetection · GitHub Object Detection toolkit based on PaddlePaddle. It supports object detection, instance segmentation, multiple object tracking and real-time multi-person keypoint detection. - PaddleDetection/pphuman_mot.md at release/2.6 · PaddlePaddle/PaddleDetection https://github.com/

    2024年02月08日
    浏览(39)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包