build_target函数是将box标签和anchor进行匹配,其中FPN特征图为三层,分别为降采样8,16,32,代码展示与解释如下:

def build_targets(p, targets, model):# Build targets for compute_loss(), input targets(image,class,x,y,w,h)获取yolov5网络输出det = model.module.model[-1] if is_parallel(model) else model.model[-1]  # Detect() module获取每层特征图anchor的数量na(=3),和每个batch box标签的个数ntna, nt = det.na, targets.shape[0]  # number of anchors, targets初始化每个batch box的信息:tcls表示类别;tbox表示标记的box和生成的box的左边(x,y,w,h)indices:图像索引,选取的anchor的索引(每层特征图中每个网格初始化3个),每层特征图上选取的网格点坐标(i,j)anch选取的anchor的索引tcls, tbox, indices, anch = [], [], [], []将targets由(n*7)变为(3*n*7) 3个anchor,每个anchor都对应所有的box标签gain = torch.ones(7, device=targets.device)  # normalized to gridspace gainai = torch.arange(na, device=targets.device).float().view(na, 1).repeat(1, nt)  # same as .repeat_interleave(nt)targets = torch.cat((targets.repeat(na, 1, 1), ai[:, :, None]), 2)  # append anchor indices为扩充标记的box添加偏置,具体扩充规则为在下边g = 0.5  # biasoff = torch.tensor([[0, 0],[1, 0], [0, 1], [-1, 0], [0, -1],  # j,k,l,m# [1, 1], [1, -1], [-1, 1], [-1, -1],  # jk,jm,lk,lm], device=targets.device).float() * g  # offsets对每个特征图进行操作,顺序为降采样8-16-32for i in range(det.nl):获取该层特征图中的anchoranchors = det.anchors[i]获取该层特征图的尺寸(1 1 w h w h 1)gain[2:6] = torch.tensor(p[i].shape)[[3, 2, 3, 2]]  # xyxy gain# Match targets to anchors将box坐标转换到特征图上(在box标签生成中,对box坐标进行了归一化,即除以图像的宽高)通过将归一化的box乘以特征图尺度,从而将box坐标投影到特征图上t = targets * gainif nt:当该batch中存在box标签时,获取每个box对应的anchor,并生成符合规定的anchor# Matches获取box和三个anchor对应的长宽比r = t[:, :, 4:6] / anchors[:, None]  # wh ratio如果每个box和anchor的长宽比中最大值小于model.hyp['anchor_t'](4.0),则该box为合适的box,并获取到对应的anchorj = torch.max(r, 1. / r).max(2)[0] < model.hyp['anchor_t']  # compare# j = wh_iou(anchors, t[:, 4:6]) > model.hyp['iou_t']  # iou(3,n)=wh_iou(anchors(3,2), gwh(n,2))t = t[j]  # filter# Offsets获取选择完成的box的中心点左边-gxy(以图像左上角为坐标原点),并转换为以特征图右下角为坐标原点的坐标-gxigxy = t[:, 2:4]  # grid xygxi = gain[[2, 3]] - gxy  # inverse分别判断box的(x,y)坐标是否大于1,并距离网格左上角的距离(准确的说是y距离网格上边或x距离网格左边的距离)距离小于0.5,如果(x,y)中满足上述两个条件,则选中j, k = ((gxy % 1. < g) & (gxy > 1.)).T对转换之后的box的(x,y)坐标分别进行判断是否大于1,并距离网格右下角的距离(准确的说是y距离网格下边或x距离网格右边的距离)距离小于0.5,如果(x,y)中满足上述两个条件,为Turel, m = ((gxi % 1. < g) & (gxi > 1.)).Tj = torch.stack((torch.ones_like(j), j, k, l, m))获取所有符合要求的boxt = t.repeat((5, 1, 1))[j]生成所有box对应的偏置,原始box偏置为0offsets = (torch.zeros_like(gxy)[None] + off[:, None])[j]else:t = targets[0]offsets = 0# Define获取每个box的图像索引和类别b, c = t[:, :2].long().T  # image, class获取box的xy和whgxy = t[:, 2:4]  # grid xygwh = t[:, 4:6]  # grid wh获取每个box所在的网格点坐标gij = (gxy - offsets).long()gi, gj = gij.T  # grid xy indices# Append获取每个anchor索引a = t[:, 6].long()  # anchor indices保存图像序号 anchor序号和网格点坐标indices.append((b, a, gj.clamp_(0, gain[3] - 1), gi.clamp_(0, gain[2] - 1)))  # image, anchor, grid indices获取(x,y)相对于网格点的偏置,以及box的宽高tbox.append(torch.cat((gxy - gij, gwh), 1))  # boxanch.append(anchors[a])  # anchorstcls.append(c)  # classreturn tcls, tbox, indices, anch

重点:对box标记进行扩充:

首先获取box的中心点坐标gxy(以图像左上角为坐标原点),并转换为以特征图右下角为坐标原点的坐标-gxi
            gxy = t[:, 2:4]  # grid xy
            gxi = gain[[2, 3]] - gxy  # inverse

对box的(x,y)坐标分别进行判断是否大于1,并距离网格左上角的距离(准确的说是y距离网格上边或x距离网格左边的距离)距离小于0.5,如果(x,y)中满足上述两个条件,为Ture

j, k = ((gxy % 1. < g) & (gxy > 1.)).T

eg:存在4个box

[ [4.3,2.1]

[2.61,2.45]

[0.37,3.57]

[3.59,4.21] ]

则j=[T F F F] k=[T T F T]

对转换之后的box的(x,y)坐标分别进行判断是否大于1,并距离网格右下角的距离(准确的说是y距离网格下边或x距离网格右边的距离)距离小于0.5,如果(x,y)中满足上述两个条件,为Ture
            l, m = ((gxi % 1. < g) & (gxi > 1.)).T

然后将原始box和扩增的box进行合并
            j = torch.stack((torch.ones_like(j), j, k, l, m))

*********************************************************************************************************************************************************************************************************************

2021.5.7补充

anchor与gt匹配

1.将batch中的gt(box+class)扩张3倍,对应每层featuremap中的3个anchor(n*5-->3*n*5),假定现有的3个anchor和每个gt都一一对应

2.对每层特征图进行相同的操作:

a.将gt信息投影到特征图上

b.将gt中每个box的宽高和anchor的宽高进行做比,将最大比例小于预先设定值的gt保存下来,并与anchor一一对应(只要gt和anchor的宽高比小于某个阈值,则认为该anchor和gt匹配上了)

c.对b中保存下来的gt进行扩充: 1) 保存现有所有的gt   2)保存box中心点坐标Xc距离网格左边的距离小于0.5且坐标大于1的box   3)保存box中心点坐标Yc距离网格上边的距离小于0.5且坐标大于1的box 4)保存box中心点坐标Xc距离网格右边的距离小于0.5且坐标大于1的box   5)保存box中心点坐标Yc距离网格下边的距离小于0.5且坐标大于1的box 将该5中box构成需要的gt

补充:为什么会取距离四边小于0.5的点,是因为等于0.5时,我们认为该box正好落到该网格中,但是小于0.5时,可能是因为在网络不断降采样时,对特征图尺度进行取整导致box中心产生了偏差,所以作者将小于0.5的box减去偏执1,使得box中心移动到相邻的特征图网格中,从而对正样本进行扩充,保证了偏差导致的box错位以及扩充了正样本的个数.<个人理解,不一定对>

3.获取保留的gt中中心点坐标和网格点坐标的偏执与box的wh构成新的box信息(Cx-X,Cy-Y,w,h)

4.最后获取4个向量  a.indice[图像序号,anchor序号,网格点坐标x,网格点坐标y]  b.tbox  box的对应坐标[Cx-X,Cy-Y,w,h] c.anch tbox对应的anchor索引 d.tcls tbox对应的类别

详细信息见上边的代码详解

yolov5代码详解-build_targets(p, targets, model)相关推荐

  1. yolov5代码详解-compute_loss(p, targets, model)

    def compute_loss(p, targets, model): # predictions, targets, modeldevice = targets.device#创建用来保存三层特征 ...

  2. Yolov5代码详解——detect.py

    首先执行扩展包的导入: import argparse import os import platform import sys from pathlib import Path ​ import t ...

  3. yolov5的detect.py代码详解

    目标检测系列之yolov5的detect.py代码详解 前言 哈喽呀!今天又是小白挑战读代码啊!所写的是目标检测系列之yolov5的detect.py代码详解.yolov5代码对应的是官网v6.1版本 ...

  4. Pytorch|YOWO原理及代码详解(二)

    Pytorch|YOWO原理及代码详解(二) 本博客上接,Pytorch|YOWO原理及代码详解(一),阅前可看. 1.正式训练 if opt.evaluate:logging('evaluating ...

  5. Pytorch | yolov3原理及代码详解(二)

    阅前可看: Pytorch | yolov3原理及代码详解(一) https://blog.csdn.net/qq_24739717/article/details/92399359 分析代码: ht ...

  6. Pytorch | yolov3原理及代码详解(一)

    YOLO相关原理 : https://blog.csdn.net/leviopku/article/details/82660381 https://www.jianshu.com/p/d13ae10 ...

  7. YOLOv5算法详解

    目录 1.需求解读 2.YOLOv5算法简介 3.YOLOv5算法详解 3.1 YOLOv5网络架构 3.2 YOLOv5实现细节详解 3.2.1 YOLOv5基础组件 3.2.2 输入端细节详解 3 ...

  8. yolov3代码详解(七)

    Pytorch | yolov3代码详解七 test.py test.py from __future__ import divisionfrom models import * from utils ...

  9. 对比学习:MoCo代码详解

    MoCo算法代码详解 本文代码来源: 1.导入包 2.参数设置 3.数据预处理 4. 模型 4.1moment update key encoder 4.2进队出队 4.3shuffle 4.4损失计 ...

最新文章

  1. Android应用系列:完美运行GIF格式的ImageView(附源码)
  2. 从云端到边缘 AI推动FPGA应用拓展
  3. docker容器运行mysql持久化_docker容器实现数据持久化的两种方式及其区别
  4. python大全1015python大全_python 列表总结大全
  5. [flutter专题]详解AppBar小部件
  6. Jenkins配置jdk(启动报错:Starting Jenkins bash: /usr/bin/java: No such file or directory)
  7. Confluence 6 匿名用户
  8. linux同内核覆盖,Linux内核代码覆盖率 – GCOV
  9. jdbcType和javaType
  10. 3.支付平台架构:业务、规划、设计与实现 --- 支付后端技术实战
  11. linux内存源码分析 - 伙伴系统(释放页框)
  12. Pod 的生命周期及探针
  13. Linux系统升级及内核版本升级
  14. 微信中无法下载APP的解决办法
  15. 2013网易校园招聘笔试题
  16. Android下拉筛选DropDownMenu
  17. VPP DPDK,不是翻墙!!
  18. 1143-最长公共子序列(最长公共子序列)
  19. HEIC文件怎么打开,如何将HEIC格式转换为JPG格式
  20. 浅析项目工作量估算方法

热门文章

  1. c# 使用File.Create创建文件后,正由另一进程使用,因此该进程无法访问此文件解决办法。
  2. 「无接触实习」你准备好了吗?
  3. 青春的样子,不止步于wifi
  4. 2016全球与中国市场运动相机深度研究报告
  5. 你拿着的“流程”是锁链还是指南针?
  6. 关系抽取(RE)的损失函数
  7. Windows系统键盘各键作用和快捷方式
  8. 2.JeeSite 基础—使用 JeeSite 快速开发项目—新建模块、单表代码生成、上传图片、富文本编辑
  9. 干货:如何有效的做好工程采购、分包及合同管理?
  10. Stata无偏性检验(安慰剂检验代码)