yolo探测法
说代码前 简单提一句,you only look once(yolo)这个英文名 是对标滑动窗口探测
滑动窗口要看好几次,yolo只要看一次,因为yolo的特殊标注方式可以将目标检测问题简化为单步回归问题
yolo的标签是:
P:物体存在与否(置信度)
xyxxyy:坐标和长宽
c 类别置信度)
P | x,y,w,h | c |
---|---|---|
物体存在与否(置信度) | 坐标和长宽 | 类别置信度 |
所以一个类别(c=1) 的话 一个标签就有6个值,有多少个格子 多少个anchorbox(一般是3个)再乘
所以一个格子的话 维度就是(5+C)*anchor 重要!
懂了原理 我们就看下代码:
AnchorBox
Yolov4没有用自适应框(就是自己事先写好),了解运作方式对于以后V5自适应框会有更好的理解
我们先看下anchorBox,下面的例子是最小的anchorbox,可以看一下源码的实现方式
num_anchors = 9
stride = 8 ## 另外两个stride16,24
anchor_mask=[0, 1, 2] ## 另外两个anchor[3,4,5] [6,7,8]
anchors=[12, 16, 19, 36, 40, 28, 36, 75, 76, 55, 72, 146, 142, 110, 192, 243, 459, 401]
anchor_step = len(anchors) // num_anchors
masked_anchors = []
#代码很简单 取anchors前6个除以stride
for m in anchor_mask:
masked_anchors += anchors[m * anchor_step:(m + 1) * anchor_step]
masked_anchors = [anchor / stride for anchor in masked_anchors]
#[1.5, 2.0, 2.375, 4.5, 5.0, 3.5] 这个masked_anchors就是我们最小的anchors 怎么用的看下面推理
Yolo推理代码
先从推理看,图片输入网络(看上一章)
代码很长 核心就是用OUT的偏移量和anchor先验框 计算真实框
def yolo_forward(output, conf_thresh, num_classes, anchors, num_anchors, scale_x_y, only_objectness=1,validation=False):
#这就是我上面说的维度确认
assert (output.size(1) == (5 + num_classes) * num_anchors)
# 下面代码 做的事情只有一个 将output的第二维(比如3个anchor):
# [ 2, 2, 1, num_classes, 2, 2, 1, num_classes, 2, 2, 1, num_classes ]
# 的输入 转成 bxy = [ 6 ] bwh = [ 6 ] det_conf = [ 3 ] cls_conf = [ num_classes * 3 ]
bxy_list = []
bwh_list = []
det_confs_list = []
cls_confs_list = []
# 几个anchor 就遍历几次Y标签
for i in range(num_anchors):
#begin end对应一个anchor中所有的标签 对应我上面表格里的东西看!
begin = i * (5 + num_classes)
end = (i + 1) * (5 + num_classes)
# xy标签
bxy_list.append(output[:, begin : begin + 2])
# wh标签
bwh_list.append(output[:, begin + 2 : begin + 4])
# P标签 置信度
det_confs_list.append(output[:, begin + 4 : begin + 5])
# 类别置信度
cls_confs_list.append(output[:, begin + 5 : end])
# 下面代码都是用concat把list合并成torch
# Shape: [batch, num_anchors * 2, H, W]
bxy = torch.cat(bxy_list, dim=1)
# Shape: [batch, num_anchors * 2, H, W]
bwh