【yolo】目标检测预测框生成流程浅析, 含示例

yolov5 预测框生成

配置文件

首先是配置文件, 我们在配置文件中可以看到这样的配置项

# YOLOv5 🚀 by Ultralytics, AGPL-3.0 license
 
# 定义一些模型超参数
nc: 80  # 类别
depth_multiple: 0.33  # 模型深度 系数
width_multiple: 0.50  # 模型宽度 系数
anchors:
  - [10,13, 16,30, 33,23]  # P3/8 用于检测小目标的三个初始框(anchors)
  - [30,61, 62,45, 59,119]  # P4/16 用于检测中目标的三个初始框(anchors)
  - [116,90, 156,198, 373,326]  # P5/32 用于检测大目标的三个初始框(anchors)
  
# YOLOv5 v6.0 backbone 主干网络
backbone:
  # [from, number, module, args] # from是指输入来自那里,number是指模块重复数量,module是模块组件的名称,args是创建模型需要的参数
  [[-1, 1, Conv, [64, 6, 2, 2]],  # 0-P1/2 第0层,相对原图做了2倍下采样
   [-1, 1, Conv, [128, 3, 2]],  # 1-P2/4 第1层,相对原图做了4倍下采样
   [-1, 3, C3, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8 第3层,相对原图做了8倍下采样
   [-1, 6, C3, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16 第5层,相对原图做了16倍下采样
   [-1, 9, C3, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32 第7层,相对原图做了32倍下采样
   [-1, 3, C3, [1024]],
   [-1, 1, SPPF, [1024, 5]],  # 9 第9层
  ]
 

关于模型深度系数模型宽度系数可以看这篇文档 链接

简单来说, 模型深度系数就是配置文件中 模型重复次数 ∗ 模型深度系数 模型重复次数 * 模型深度系数 模型重复次数模型深度系数

模型宽度系数就是 模型输出维度 ( a r g s 的第一个参数 ) ∗ 模型深度系数 模型输出维度(args的第一个参数) * 模型深度系数 模型输出维度(args的第一个参数)模型深度系数

我们主要关注的是锚点配置项

anchors:
  - [10,13, 16,30, 33,23]  # P3/8 用于检测小目标的三个初始框(anchors)
  - [30,61, 62,45, 59,119]  # P4/16 用于检测中目标的三个初始框(anchors)
  - [116,90, 156,198, 373,326]  # P5/32 用于检测大目标的三个初始框(anchors)

[10,13, 16,30, 33,23] 表示三组数据, 分别对应宽高, 是对应特征图缩小 8 倍时对应的参数, 其他类似, 后续我们将提到相关参数的使用方式

模型输出

yolov5 版本的模型流程如下图所示:

在这里插入图片描述

这个流程图模拟的输入图片维度为 [640,640,3] 会得到3个不同尺度的输出:80x80(640/8)、40x40(640/16)、20x20(640/32)分别对应着特征图缩小8倍, 缩小16倍, 缩小32倍 , 输出模块为CSP2_1

anchors:
  - [10,13, 16,30, 33,23]  # P3/8
  - [30,61, 62,45, 59,119]  # P4/16
  - [116,90, 156,198, 373,326]  # P5/32

其中,80x80代表浅层的特征图(P3),包含较多的低层级信息,适合用于检测小目标,所以这一特征图所用的anchor尺度较小;同理,20x20代表深层的特征图(P5),包含更多高层级的信息,如轮廓、结构等信息,适合用于大目标的检测,所以这一特征图所用的anchor尺度较大。另外的40x40特征图(P4)上就用介于这两个尺度之间的anchor用来检测中等大小的目标。yolov5之所以能高效快速地检测跨尺度目标,这种对不同特征图使用不同尺度的anchor的思想功不可没。

在neck过程后, 最后还有一个 Prediction 的过程, 特征图的宽高不变, 但是维度发现改变, 均变成 (4 + 1 + 类别数) * 3

对应一个缩小系数为 8 的特征图, (160,92,256) ==> (1,3, 60,92,85)

在这里插入图片描述

到这一步后, 我们就可以得到我们所需要的内容了, 也就是维度 85 对应的前4个值, 坐标x,y和宽高w,h

下图给出了一些解释, 当前得到的x和y, w和h 是一个不确定大小的数, 后面我们需要对其进行处理

在这里插入图片描述

处理模型输出

xywh格式, 即边界框由中心坐标(x,y)和框的长宽(w,h)来表示,YOLO中采用的主要是这种形式。

现在, 我们的任务是根据模型的输出得到预测框的实际位置

img

由锚框的生成方法可知,它是以某个划分格子的中心坐标,以一定长宽比生成的,但在YOLO中预测框,则是以某个格子的左上角坐标为原点进行偏移的。

我们将特征图上一个格子称为grid , 比如说一个(640,640,3)的图片进行特征图提取后, 缩小32倍后的尺寸是 (20,20) , 那么这个特征图就有 20 ∗ 20 = 400 20 * 20 = 400 2020=400 个grid , 因为每个 grid 可以对应原图上的一片像素点, 我们可以得到每个 grid 的左上角真实坐标 , 我们将其缩小stride倍的值记作 ( c x , c y ) (c_x,c_y) (cx,cy)

已知 sigmoid 函数, 我们定义
σ ( x ) = 1 1 + e − x = e x e x + 1 σ(x)=\frac1{1+e^{-x}}=\frac{e^x}{e^x+1} σ(x)=1+ex1=ex+1ex
在这里插入图片描述

我们设置每个网格获得目标预测值为:坐标( t x , t y ) t_x,t_y) tx,ty)和宽高 ( t w , t h ) (t_w,t_h) (tw,th), 分别对应输出维度85的前四个值

定义坐标( b x , b y ) b_x,b_y) bx,by)和宽高 ( b w , b h ) (b_w,b_h) (bw,bh)为真实的预测框

按照下式计算该网格的目标坐标和目标框大小
b x = ( σ ( t x ) ∗ 2 + c x ) ∗ s t r i d e b y = ( σ ( t y ) ∗ 2 + c y ) ∗ s t r i d e b w = ( σ ( t w ) ∗ 2 ) 2 ∗ a n c h o r [ 0 ] b h = ( σ ( t h ) ∗ 2 ) 2 ∗ a n c h o r [ 1 ] b_x=(\sigma(t_x)^*2+c_x) * stride \\ b_y=(\sigma(t_y)^*2+c_y) * stride\\ b_w=(\sigma(t_w)*2)^2* anchor[0]\\ b_h=(\sigma(t_h)*2)^2 * anchor[1] bx=(σ(tx)2+cx)strideby=(σ(ty)2+cy)stridebw=(σ(tw)2)2anchor[0]bh=(σ(th)2)2anchor[1]

anchor 就是我们配置文件配置的数值

anchors:
  - [10,13, 16,30, 33,23]  # P3/8 用于检测小目标的三个初始框(anchors)
  - [30,61, 62,45, 59,119]  # P4/16 用于检测中目标的三个初始框(anchors)
  - [116,90, 156,198, 373,326]  # P5/32 用于检测大目标的三个初始框(anchors)

当特征图为缩小8倍时, 有三组anchor分别为 (10,13) (16,39) (33,23) , 假设这里使用的是第一个anchor, 那么 anchor[0] = 10 , anchor[1] = 13

在yolo.py中代码是在Detect类中(下面代码是用于检测时的处理方式, 如果是训练时的处理方式有一些改动)

else:  # Detect (boxes only)
    xy, wh, conf = x[i].sigmoid().split((2, 2, self.nc + 1), 4)
    xy = (xy * 2 + self.grid[i]) * self.stride[i]  # xy self.stride = [8,16,32] 对应缩小的倍率
    wh = (wh * 2) ** 2 * self.anchor_grid[i]  # wh
    y = torch.cat((xy, wh, conf), 4)

针对输入图像736x1280, 经目标框坐标变换后,得到所有网格中的目标框张量[1, 57960,85]。57960=(40x23+80x46+160x92)x3 是所有网格的目标框数量。

40x23 : 32倍缩小特征图

80x46 : 16倍缩小特征图

160x92 : 8倍缩小特征图

示例

对一张 736x1280 的图片(假设yolo没有进行图像缩放), 当进行8倍缩略图时,

s t r i d e = 8 stride = 8 stride=8

第二行第二个grid坐标为 ( c x , c y ) = ( 92 / 8 , 160 / 8 ) (c_x,c_y)=(92 / 8,160 / 8) (cx,cy)=(92/8,160/8)

a n c h o r = [ 10 , 13 ] anchor = [10,13] anchor=[10,13]

( t x , t y ) = ( 1.69 , − 6.3 ) , (t_x,t_y)=(1.69,-6.3), (tx,ty)=(1.69,6.3), ( t w , t h ) = ( 1.03 , 2.6 ) (t_w,t_h)=(1.03,2.6) (tw,th)=(1.03,2.6)
b x = ( σ ( t x ) ∗ 2 + c x ) ∗ s t r i d e = ( 0.674 + 11.5 ) ∗ 8 = 97.394 b y = ( σ ( t y ) ∗ 2 + c y ) ∗ s t r i d e = ( 0.003 + 20 ) ∗ 8 = 160.024 b w = ( σ ( t w ) ∗ 2 ) 2 ∗ a n c h o r [ 0 ] = 0.5534 ∗ 10 = 5.534 b h = ( σ ( t h ) ∗ 2 ) 2 ∗ a n c h o r [ 1 ] = 3.198 ∗ 13 = 41.58 b_x=(\sigma(t_x)^*2+c_x) * stride = (0.674 + 11.5) * 8 = 97.394\\ b_y=(\sigma(t_y)^*2+c_y) * stride = (0.003 + 20) * 8 = 160.024\\ b_w=(\sigma(t_w)*2)^2* anchor[0] = 0.5534 * 10 = 5.534\\ b_h=(\sigma(t_h)*2)^2 * anchor[1] = 3.198 * 13 = 41.58 bx=(σ(tx)2+cx)stride=(0.674+11.5)8=97.394by=(σ(ty)2+cy)stride=(0.003+20)8=160.024bw=(σ(tw)2)2anchor[0]=0.553410=5.534bh=(σ(th)2)2anchor[1]=3.19813=41.58

即中心点为 (97,394,160.024) 宽高为(5.534,41.58)像素

参考

https://blog.csdn.net/qq_41204464/article/details/130229847

https://blog.csdn.net/weixin_44238733/article/details/121180095

https://blog.csdn.net/lzzzzzzm/article/details/120621582

https://blog.csdn.net/qq_27278957/article/details/120036450

https://blog.csdn.net/weixin_43427721/article/details/123608508?spm=1001.2014.3001.5506

https://blog.csdn.net/lzzzzzzm/article/details/120621582

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值