只会预测一组
conditional class probabilities.2层全连接层
定位
和 Recall
上表现差!加入了BN层,加速收敛。减少权重初始化的依赖。防止过拟合舍弃dropout。
不同与上面的1,这次,每个anchor box都要预测一组条件类别概率!因此也就是 S × S × B ∗ ( 5 + C ) S\times S\times B*(5+C) S×S×B∗(5+C)
抛弃全连接层,使用全卷积层FCN
使用了5个Anchor Boxes机制,mAP降低了0.3%,但是recall上升了7%.
32
,为了方便,就用32的倍数,范围为(320,608)=(10,19)*329
个anchor boxes!如下图,上面 是带有全连接层
的神经网络,我们需要的预测的是4个类别的概率。
同理我们也可以用 卷积
神经网络 构成一样的结构。
只要通过一个和前一层被卷积张量一样大小
的kernel size,就行了。
下图是 5 × 5 × 16 5 \times\ 5 \times16 5× 5×16输入张量和400 个 5 × 5 × 16 5 \times 5 \times16 5×5×16卷积体
卷积后得到 1 × 1 × 400 1\times1\times400 1×1×400张量,也就是和上图的400神经元的全连接层等价。
以往的滑动窗口目标检测,就是选择一个框大小,然后在原图上从左到右从上到下,一次次滑动,然后得到一次次预测。
每一次滑动就有一个预测向量(车,人,树…)。我们可以通过预测向量中最大的概率对应的框作为预测框。
滑动框的缺点:
重复计算,诶? 因此自然而然想到用卷积来操作,因为本身就和卷积操作相似了。
输入张量矩阵
经过多层卷积层后,得到一个多维的输出张量矩阵
。这个输出矩阵,可以看做是对每一个输入张量矩阵中的相同滑动框大小,不同位置的预测值!作为FCN,YOLOv3本是可以改变输入大小的
无视图片大小。但是,实际上,由于各种问题,我们可能希望保持不变的输入大小,而这些问题只会在实现算法时浮出水面。
Feature map通过最后一层 1 × 1 1\times1 1×1 卷积后得到 Prediction Map(预测图)
Prediction Map
中每一个Cell
预测了固定数目
的回归框。
Depth-wise, we have ( B x (4+1 + C) ) entries in the feature map:
深度方向上,最后的feature map 有 ( B x (5 +C) ) 个元素,每个BOX有5+C个预测值
( o b j e c t n e n e s S c o r e + C l a s s e s P r o b a b i l i t y + t x + t y + t w + t h ) ∗ B o u d i n g B o x e s ( objectnenesScore+ClassesProbability+ t_x +t_ y +t_ w +t_h )* BoudingBoxes (objectnenesScore+ClassesProbability+tx+ty+tw+th)∗BoudingBoxes
o b j e c t n e n e s S c o r e = c o n f i d e n c e = P ( o b j e c t ) ∗ I O U P r e d T r u t h objectnenes \space Score = confidence =P(object)*IOU_{Pred}^{Truth} objectnenes Score=confidence=P(object)∗IOUPredTruth
举例如下:
下图大小为13 x 13
标签框
的中心 落在(7,7),因此这个cell负责预测
狗,这个尺度上(13*13尺度)可以预测3个Bouding box。
实际上,yolo有三个尺度图的预测,下图只是一个13*13大小的如同格子一样
的预测图,每个预测图的每个格子预测了不同大小的三个框。
检测大尺度(13,13) | 中尺度 (26,26) | 检测小尺度(52,52) |
---|---|---|
小一点的三个固定框10,13, 16,30, 33,23, | 中等的三个固定框 30,61, 62,45, 59,119, | 大的三个固定框 116,90, 156,198, 373,326 |
总结一下!
我们找到了哪个格子
负责预测我们的物体,但是框的大小怎么预测??
传送门
借用Andrew的动图:
蓝色花括号代表着Anchors,如果里面有目标,则希望对应的部分,objectiveness score=1
预测边界框的宽度和高度可能是有意义的,但在实践中,这会导致在训练过程中出现不稳定的梯度。相反,大多数现代object detector预测log_space transformation ,或者简单地偏移到预定义的默认包围框(称为锚)。
Then, these transforms are applied to the anchor boxes to obtain the prediction.
YOLO v3 has three anchors, which result in prediction of three bounding boxes per cell.
负责检测狗的框将是和标签框
具有最大IOU
的Anchor框
。
请再看图:
这里的
t x , t y , t w , t h t_x ,t_y, t_w, t_h tx,ty,tw,th
这四个坐标并不是最终(绘制)的坐标,而是相对中心的偏离scale坐标!
bx, by, bw, bh are the x,y center co-ordinates, width and height of our prediction. tx, ty, tw, th is what the network outputs. cx and cy are the top-left co-ordinates of the grid. pw and ph are anchors dimensions for the box.
bx, by, bw, bh are the x,y center co-ordinates, width and height of our prediction.
注意:
这个 b w , b h b_w,b_h bw,bh是相对于feature map大小的=归一化比例=,比如你的 b w , b h b_w,b_h bw,bh 为 ( 0.3 , 0.8 ) (0.3,0.8) (0.3,0.8),那么你的实际预测框的大小为 ( 13 × 0.3 , 13 × 0.8 ) (13\times0.3,13\times0.8) (13×0.3,13×0.8)
学习过后,中心的红框子的概率基本为1,周围的各自概率接近1,边缘的格子为0
在yolov3之前使用softmax预测类别概率,但是导致的问题就是,如果目标属于某一类,它就不能属于另一类。这在Woman和Person这种分类情况下就不使用。因此就是用sigmoid来预测。
三个预测尺度:
412 × 412 412\times412 412×412大小的图片输入
检测大尺度(13,13) | 中尺度 (26,26) | 检测小尺度(52,52) |
---|---|---|
32 | 16 | 8 |
跨尺度说明产生了很多预测框(10647个框),怎么筛选到最终的1个框
3 × ( 13 × 13 ) + 3 × ( 26 × 26 ) + 3 × ( 52 × 52 ) = 10647 3\times(13\times13)+3\times(26\times26)+3\times(52\times52)=10647 3×(13×13)+3×(26×26)+3×(52×52)=10647
网络结构图,concatenate目的是把前面的位置信息和后面的语义信息融合
def bbox_iou(box1, box2):
"""
Returns the IoU of two bounding boxes
"""
#Get the coordinates of bounding boxes
b1_x1, b1_y1, b1_x2, b1_y2 = box1[:,0], box1[:,1], box1[:,2], box1[:,3]
b2_x1, b2_y1, b2_x2, b2_y2 = box2[:,0], box2[:,1], box2[:,2], box2[:,3]
#get the corrdinates of the intersection rectangle
inter_rect_x1 = torch.max(b1_x1, b2_x1)
inter_rect_y1 = torch.max(b1_y1, b2_y1)
inter_rect_x2 = torch.min(b1_x2, b2_x2)
inter_rect_y2 = torch.min(b1_y2, b2_y2)
#Intersection area
inter_area = torch.clamp(inter_rect_x2 - inter_rect_x1 + 1, min=0) * torch.clamp(inter_rect_y2 - inter_rect_y1 + 1, min=0)
#Union Area
b1_area = (b1_x2 - b1_x1 + 1)*(b1_y2 - b1_y1 + 1)
b2_area = (b2_x2 - b2_x1 + 1)*(b2_y2 - b2_y1 + 1)
iou = inter_area / (b1_area + b2_area - inter_area)
return iou
layer filters size input output
0 conv 32 3 x 3 / 1 416 x 416 x 3 -> 416 x 416 x 32 0.299 BF
1 conv 64 3 x 3 / 2 416 x 416 x 32 -> 208 x 208 x 64 1.595 BF
2 conv 32 1 x 1 / 1 208 x 208 x 64 -> 208 x 208 x 32 0.177 BF
3 conv 64 3 x 3 / 1 208 x 208 x 32 -> 208 x 208 x 64 1.595 BF
4 Shortcut Layer: 1
5 conv 128 3 x 3 / 2 208 x 208 x 64 -> 104 x 104 x 128 1.595 BF
6 conv 64 1 x 1 / 1 104 x 104 x 128 -> 104 x 104 x 64 0.177 BF
7 conv 128 3 x 3 / 1 104 x 104 x 64 -> 104 x 104 x 128 1.595 BF
8 Shortcut Layer: 5
9 conv 64 1 x 1 / 1 104 x 104 x 128 -> 104 x 104 x 64 0.177 BF
10 conv 128 3 x 3 / 1 104 x 104 x 64 -> 104 x 104 x 128 1.595 BF
11 Shortcut Layer: 8
12 conv 256 3 x 3 / 2 104 x 104 x 128 -> 52 x 52 x 256 1.595 BF
13 conv 128 1 x 1 / 1 52 x 52 x 256 -> 52 x 52 x 128 0.177 BF
14 conv 256 3 x 3 / 1 52 x 52 x 128 -> 52 x 52 x 256 1.595 BF
15 Shortcut Layer: 12
16 conv 128 1 x 1 / 1 52 x 52 x 256 -> 52 x 52 x 128 0.177 BF
17 conv 256 3 x 3 / 1 52 x 52 x 128 -> 52 x 52 x 256 1.595 BF
18 Shortcut Layer: 15
19 conv 128 1 x 1 / 1 52 x 52 x 256 -> 52 x 52 x 128 0.177 BF
20 conv 256 3 x 3 / 1 52 x 52 x 128 -> 52 x 52 x 256 1.595 BF
21 Shortcut Layer: 18
22 conv 128 1 x 1 / 1 52 x 52 x 256 -> 52 x 52 x 128 0.177 BF
23 conv 256 3 x 3 / 1 52 x 52 x 128 -> 52 x 52 x 256 1.595 BF
24 Shortcut Layer: 21
25 conv 128 1 x 1 / 1 52 x 52 x 256 -> 52 x 52 x 128 0.177 BF
26 conv 256 3 x 3 / 1 52 x 52 x 128 -> 52 x 52 x 256 1.595 BF
27 Shortcut Layer: 24
28 conv 128 1 x 1 / 1 52 x 52 x 256 -> 52 x 52 x 128 0.177 BF
29 conv 256 3 x 3 / 1 52 x 52 x 128 -> 52 x 52 x 256 1.595 BF
30 Shortcut Layer: 27
31 conv 128 1 x 1 / 1 52 x 52 x 256 -> 52 x 52 x 128 0.177 BF
32 conv 256 3 x 3 / 1 52 x 52 x 128 -> 52 x 52 x 256 1.595 BF
33 Shortcut Layer: 30
34 conv 128 1 x 1 / 1 52 x 52 x 256 -> 52 x 52 x 128 0.177 BF
35 conv 256 3 x 3 / 1 52 x 52 x 128 -> 52 x 52 x 256 1.595 BF
36 Shortcut Layer: 33
37 conv 512 3 x 3 / 2 52 x 52 x 256 -> 26 x 26 x 512 1.595 BF
38 conv 256 1 x 1 / 1 26 x 26 x 512 -> 26 x 26 x 256 0.177 BF
39 conv 512 3 x 3 / 1 26 x 26 x 256 -> 26 x 26 x 512 1.595 BF
40 Shortcut Layer: 37
41 conv 256 1 x 1 / 1 26 x 26 x 512 -> 26 x 26 x 256 0.177 BF
42 conv 512 3 x 3 / 1 26 x 26 x 256 -> 26 x 26 x 512 1.595 BF
43 Shortcut Layer: 40
44 conv 256 1 x 1 / 1 26 x 26 x 512 -> 26 x 26 x 256 0.177 BF
45 conv 512 3 x 3 / 1 26 x 26 x 256 -> 26 x 26 x 512 1.595 BF
46 Shortcut Layer: 43
47 conv 256 1 x 1 / 1 26 x 26 x 512 -> 26 x 26 x 256 0.177 BF
48 conv 512 3 x 3 / 1 26 x 26 x 256 -> 26 x 26 x 512 1.595 BF
49 Shortcut Layer: 46
50 conv 256 1 x 1 / 1 26 x 26 x 512 -> 26 x 26 x 256 0.177 BF
51 conv 512 3 x 3 / 1 26 x 26 x 256 -> 26 x 26 x 512 1.595 BF
52 Shortcut Layer: 49
53 conv 256 1 x 1 / 1 26 x 26 x 512 -> 26 x 26 x 256 0.177 BF
54 conv 512 3 x 3 / 1 26 x 26 x 256 -> 26 x 26 x 512 1.595 BF
55 Shortcut Layer: 52
56 conv 256 1 x 1 / 1 26 x 26 x 512 -> 26 x 26 x 256 0.177 BF
57 conv 512 3 x 3 / 1 26 x 26 x 256 -> 26 x 26 x 512 1.595 BF
58 Shortcut Layer: 55
59 conv 256 1 x 1 / 1 26 x 26 x 512 -> 26 x 26 x 256 0.177 BF
60 conv 512 3 x 3 / 1 26 x 26 x 256 -> 26 x 26 x 512 1.595 BF
61 Shortcut Layer: 58
62 conv 1024 3 x 3 / 2 26 x 26 x 512 -> 13 x 13 x1024 1.595 BF
63 conv 512 1 x 1 / 1 13 x 13 x1024 -> 13 x 13 x 512 0.177 BF
64 conv 1024 3 x 3 / 1 13 x 13 x 512 -> 13 x 13 x1024 1.595 BF
65 Shortcut Layer: 62
66 conv 512 1 x 1 / 1 13 x 13 x1024 -> 13 x 13 x 512 0.177 BF
67 conv 1024 3 x 3 / 1 13 x 13 x 512 -> 13 x 13 x1024 1.595 BF
68 Shortcut Layer: 65
69 conv 512 1 x 1 / 1 13 x 13 x1024 -> 13 x 13 x 512 0.177 BF
70 conv 1024 3 x 3 / 1 13 x 13 x 512 -> 13 x 13 x1024 1.595 BF
71 Shortcut Layer: 68
72 conv 512 1 x 1 / 1 13 x 13 x1024 -> 13 x 13 x 512 0.177 BF
73 conv 1024 3 x 3 / 1 13 x 13 x 512 -> 13 x 13 x1024 1.595 BF
74 Shortcut Layer: 71
75 conv 512 1 x 1 / 1 13 x 13 x1024 -> 13 x 13 x 512 0.177 BF
76 conv 1024 3 x 3 / 1 13 x 13 x 512 -> 13 x 13 x1024 1.595 BF
77 conv 512 1 x 1 / 1 13 x 13 x1024 -> 13 x 13 x 512 0.177 BF
78 conv 1024 3 x 3 / 1 13 x 13 x 512 -> 13 x 13 x1024 1.595 BF
79 conv 512 1 x 1 / 1 13 x 13 x1024 -> 13 x 13 x 512 0.177 BF
80 conv 1024 3 x 3 / 1 13 x 13 x 512 -> 13 x 13 x1024 1.595 BF
81 conv 18 1 x 1 / 1 13 x 13 x1024 -> 13 x 13 x 18 0.006 BF
82 yolo
83 route 79
84 conv 256 1 x 1 / 1 13 x 13 x 512 -> 13 x 13 x 256 0.044 BF
85 upsample 2x 13 x 13 x 256 -> 26 x 26 x 256
86 route 85 61
87 conv 256 1 x 1 / 1 26 x 26 x 768 -> 26 x 26 x 256 0.266 BF
88 conv 512 3 x 3 / 1 26 x 26 x 256 -> 26 x 26 x 512 1.595 BF
89 conv 256 1 x 1 / 1 26 x 26 x 512 -> 26 x 26 x 256 0.177 BF
90 conv 512 3 x 3 / 1 26 x 26 x 256 -> 26 x 26 x 512 1.595 BF
91 conv 256 1 x 1 / 1 26 x 26 x 512 -> 26 x 26 x 256 0.177 BF
92 conv 512 3 x 3 / 1 26 x 26 x 256 -> 26 x 26 x 512 1.595 BF
93 conv 18 1 x 1 / 1 26 x 26 x 512 -> 26 x 26 x 18 0.012 BF
94 yolo
95 route 91
96 conv 128 1 x 1 / 1 26 x 26 x 256 -> 26 x 26 x 128 0.044 BF
97 upsample 2x 26 x 26 x 128 -> 52 x 52 x 128
98 route 97 36
99 conv 128 1 x 1 / 1 52 x 52 x 384 -> 52 x 52 x 128 0.266 BF
100 conv 256 3 x 3 / 1 52 x 52 x 128 -> 52 x 52 x 256 1.595 BF
101 conv 128 1 x 1 / 1 52 x 52 x 256 -> 52 x 52 x 128 0.177 BF
102 conv 256 3 x 3 / 1 52 x 52 x 128 -> 52 x 52 x 256 1.595 BF
103 conv 128 1 x 1 / 1 52 x 52 x 256 -> 52 x 52 x 128 0.177 BF
104 conv 256 3 x 3 / 1 52 x 52 x 128 -> 52 x 52 x 256 1.595 BF
105 conv 18 1 x 1 / 1 52 x 52 x 256 -> 52 x 52 x 18 0.025 BF
106 yolo
mixed_precision = True
try: # Mixed precision training https://github.com/NVIDIA/apex
from apex import amp
except:
print('Apex recommended for faster mixed precision training: https://github.com/NVIDIA/apex')
mixed_precision = False # not installed
def xyxy2xywh(x):
# Convert nx4 boxes from [x1, y1, x2, y2] to [x, y, w, h] where xy1=top-left, xy2=bottom-right
# xy1是左上角, xy2是右下角
y = torch.zeros_like(x) if isinstance(x, torch.Tensor) else np.zeros_like(x)
y[:, 0] = (x[:, 0] + x[:, 2]) / 2 # x center
y[:, 1] = (x[:, 1] + x[:, 3]) / 2 # y center
y[:, 2] = x[:, 2] - x[:, 0] # width
y[:, 3] = x[:, 3] - x[:, 1] # height
return y
def xywh2xyxy(x):
# Convert nx4 boxes from [x, y, w, h] to [x1, y1, x2, y2] where xy1=top-left, xy2=bottom-right
y = torch.zeros_like(x) if isinstance(x, torch.Tensor) else np.zeros_like(x)
y[:, 0] = x[:, 0] - x[:, 2] / 2 # top left x
y[:, 1] = x[:, 1] - x[:, 3] / 2 # top left y
y[:, 2] = x[:, 0] + x[:, 2] / 2 # bottom right x
y[:, 3] = x[:, 1] + x[:, 3] / 2 # bottom right y
return y
def clip_coords(boxes, img_shape):
# Clip bounding xyxy bounding boxes to image shape (height, width)
boxes[:, 0].clamp_(0, img_shape[1]) # x1
boxes[:, 1].clamp_(0, img_shape[0]) # y1
boxes[:, 2].clamp_(0, img_shape[1]) # x2
boxes[:, 3].clamp_(0, img_shape[0]) # y2
def scale_coords(img1_shape, coords, img0_shape, ratio_pad=None):
# Rescale coords (xyxy) from img1_shape to img0_shape
if ratio_pad is None: # calculate from img0_shape
gain = max(img1_shape) / max(img0_shape) # gain = old / new
pad = (img1_shape[1] - img0_shape[1] * gain) / 2, (img1_shape[0] - img0_shape[0] * gain) / 2 # wh padding
else:
gain = ratio_pad[0][0]
pad = ratio_pad[1]
coords[:, [0, 2]] -= pad[0] # x padding
coords[:, [1, 3]] -= pad[1] # y padding
coords[:, :4] /= gain
clip_coords(coords, img0_shape)
return coords