YOLO4相对于YOLO3改进的方面:
- CSPDarkNet53+SPP+PANet
- 数据增强
- loss用CIoU做回归loss
- MISH激活函数
CIoU = IoU - \frac{\sigma^2(b,b^{gt})}{c^2}-av
a = \frac{v}{1-IOU+v}
LOSS_{CIOU} = 1- CIoU
Mish = x* tanh(ln(1+e^x))
(1)主干网络
1 CSPDarkNet53
Input[416,416,3]-->
DarknetConv2d_BN_Mish[416,416,32]-->
RestBlock_body * 1 [208,208,64]-->
RestBlock_body * 2 [104,104,128]
RestBlock_body * 8 [52,52,256]--> Conv --> A2
RestBlock_body * 8 [26,26,512]--> Conv --> A3
RestBlock_body * 4 [13,13,1024]-->
Conv * 3 --> A1
2 SPP
A1-->concate( Pooling(5*5) +Pooling(9*9) +Pooling(13*13) +A1 )-->Conv*3--> A4
3 PANet
concat(A3,conv(A4)upsamlping())-->Conv*5-->A5
concat(A2,conv(A5)upsamlping())-->Conv*5-->output1
concat(Downsumpling(output1),A5)-->Conv*5-->output2
concat(Downsumpling(output2),A4)-->Conv*5-->output3
(2) 预测
2.1 yolo = YOLO() # 主干模型
2.2 r_image = yolo.detect_image(image) # 检测目标
2.2.1 boxed_image = letterbox_image(image, new_image_size) # 加入灰条,把图片统一到(416, 416),防止图片失真。
2.2.1.1 根据目标宽高和原图宽高得出对应最小比例。
2.2.1.2 原图片宽高乘以最小比例得到新的宽高。
2.2.1.3 把原始图片放缩到新图片大小。
2.2.1.4 生成一张shape为(416, 416)灰度图片。
2.2.1.5 计算新的宽高与灰度图片的差距,确定新图片在灰度图片上的位置,把新图片粘贴到灰度图片上。
2.2.2 self.boxes, self.scores, self.classes = self.generate() # 预测
2.2.2.1 self.yolo_model = yolo_body(Input(shape=(None,None,3)), num_anchors//3, num_classes) # 模型
2.2.2.2 self.yolo_model.output # 输出特征层 num_anchors = 3
(1) Inputs = [batch_size,416,416,3]
(2) P5_outputs=[batch_size,13,13,num_anchors*(num_classes+5)]
(3) P4_outputs=[batch_size,26,26,num_anchors*(num_classes+5)]
(4) P3_outputs=[batch_size,52,52,num_anchors*(num_classes+5)]
2.2.2.3 self.anchors # 先验框的尺寸 12, 16, 19, 36, 40, 28, 36, 75, 76, 55, 72, 146, 142, 110, 192, 243, 459, 401
2.2.2.4 boxes, scores, classes = yolo_eval(self.yolo_model.output, self.anchors,
num_classes, self.input_image_shape,
score_threshold=self.score, iou_threshold=self.iou)
(1) _boxes, _box_scores = yolo_boxes_and_scores(yolo_outputs[l], anchors[anchor_mask[l]], num_classes, input_shape, image_shape) # 解码
a. box_xy, box_wh, box_confidence, box_class_probs = yolo_head(feats, anchors, num_classes, input_shape) # shape: -1,13,13,3,2; -1,13,13,3,2; -1,13,13,3,1; -1,13,13,3,80
b. boxes = yolo_correct_boxes(box_xy, box_wh, input_shape, image_shape) # 去灰条
c. box_scores = box_confidence * box_class_probs # 物体概率
(2) mask = box_scores >= score_threshold # 筛选出大于阈值的框
(3) nms_index = tf.image.non_max_suppression(
class_boxes, class_box_scores, max_boxes_tensor, iou_threshold=iou_threshold) # 非极大抑制,去掉box重合程度高的框
a. 遍历每一个类别
b. 对某一类别的框按照物体概率从大到小排列,取出概率最大框的下标
c. 计算其它框和第一个框的IoU,保留IoU小于阈值的框
e. 对剩余的框进行b~c的操作,直到剩余框为0
2.2.3 # 设置字体,遍历所有类别,画出对应的框,标记类别和概率
2.3 r_image.show() # 显示预测结果
(3) 训练
3.1 model_body = yolo_body(image_input, num_anchors//3, num_classes) # 创建yolo模型
3.2 yolo_loss # 损失函数
3.2.1 遍历每一个特征层,取出该特征层中存在目标的点的位置
3.2.2 grid, raw_pred, pred_xy, pred_wh = yolo_head(yolo_outputs[l],
anchors[anchor_mask[l]], num_classes, input_shape, calc_loss=True) # 解码
3.2.3 _, ignore_mask = K.control_flow_ops.while_loop(lambda b,*args: b<m, loop_body, [0, ignore_mask]) # 找出忽略的样本
3.2.4 计算CIoU损失作为框的损失
3.2.5 confidence_loss = object_mask * K.binary_crossentropy(object_mask, raw_pred[...,4:5], from_logits=True)+ \
(1-object_mask) * K.binary_crossentropy(object_mask, raw_pred[...,4:5], from_logits=True) * ignore_mask # 计算置信度损失
3.2.6 class_loss = object_mask * K.binary_crossentropy(true_class_probs, raw_pred[...,5:], from_logits=True) # 类别损失
3.2.7 loss += location_loss + confidence_loss + class_loss # 总损失
3.3 训练参数设置:TensorBoard、ModelCheckpoint、EarlyStopping、WarmUpCosineDecayScheduler、model.compile、model.fit_generator
3.4 data_generator() # 数据生成器
3.2.1 image, box = get_random_data_with_Mosaic()
(1) 打开图片,框的位置
(2) 否翻转图片
(3) 对输入进来的图片进行缩放
(4) 进行色域变换
(5) 将图片进行放置,分别对应四张分割图片的位置
(6) 对box进行重新处理
(7) 将图片分割,放在一起
(8) 对框进行进一步的处理
(9) 将box进行调整
3.2.2 image, box = get_random_data()
(1) 对图像进行缩放并且进行长和宽的扭曲
(2) 将图像多余的部分加上灰条
(3) 翻转图像
(4) 色域扭曲
(5) 对box进行调整
3.2.3 y_true = preprocess_true_boxes(box_data, input_shape, anchors, num_classes)
(1) 根据特征图的宽高生成网格作为先验框的中心坐标,中心点结合先验框的宽高得到先验框的左上角和右下角坐标
(2) 把真实框映射在特征图上
(3) 遍历每张图片,计算真实框和哪个先验框最契合
(4) 每个先验框只配对一个真实框
(5) 根据真实框的index和先验框的index确定y_true对应index的值
(4) 评价