From b765a5c01c0b1e4564d738e7b07c5bb22309cc36 Mon Sep 17 00:00:00 2001 From: Bubbliiiing <47347516+bubbliiiing@users.noreply.github.com> Date: Sun, 7 Feb 2021 09:00:49 +0800 Subject: [PATCH] Delete yolo4_tiny.py --- nets/yolo4_tiny.py | 279 --------------------------------------------- 1 file changed, 279 deletions(-) delete mode 100644 nets/yolo4_tiny.py diff --git a/nets/yolo4_tiny.py b/nets/yolo4_tiny.py deleted file mode 100644 index 92ebc2f..0000000 --- a/nets/yolo4_tiny.py +++ /dev/null @@ -1,279 +0,0 @@ -from functools import wraps - -import numpy as np -import tensorflow as tf -from keras import backend as K -from keras.layers import (Add, Concatenate, Conv2D, MaxPooling2D, UpSampling2D, - ZeroPadding2D) -from keras.layers.advanced_activations import LeakyReLU -from keras.layers.normalization import BatchNormalization -from keras.models import Model -from keras.regularizers import l2 -from utils.utils import compose - -from nets.CSPdarknet53_tiny import darknet_body - - -#--------------------------------------------------# -# 单次卷积DarknetConv2D -# 如果步长为2则自己设定padding方式。 -# 测试中发现没有l2正则化效果更好,所以去掉了l2正则化 -#--------------------------------------------------# -@wraps(Conv2D) -def DarknetConv2D(*args, **kwargs): - # darknet_conv_kwargs = {'kernel_regularizer': l2(5e-4)} - darknet_conv_kwargs = {} - darknet_conv_kwargs['padding'] = 'valid' if kwargs.get('strides')==(2,2) else 'same' - darknet_conv_kwargs.update(kwargs) - return Conv2D(*args, **darknet_conv_kwargs) - - -#---------------------------------------------------# -# 卷积块 -# DarknetConv2D + BatchNormalization + LeakyReLU -#---------------------------------------------------# -def DarknetConv2D_BN_Leaky(*args, **kwargs): - no_bias_kwargs = {'use_bias': False} - no_bias_kwargs.update(kwargs) - return compose( - DarknetConv2D(*args, **no_bias_kwargs), - BatchNormalization(), - LeakyReLU(alpha=0.1)) - -#---------------------------------------------------# -# 特征层->最后的输出 -#---------------------------------------------------# -def yolo_body(inputs, num_anchors, num_classes): - #---------------------------------------------------# - # 生成CSPdarknet53_tiny的主干模型 - # feat1的shape为26,26,256 - # feat2的shape为13,13,512 - #---------------------------------------------------# - feat1, feat2 = darknet_body(inputs) - - # 13,13,512 -> 13,13,256 - P5 = DarknetConv2D_BN_Leaky(256, (1,1))(feat2) - # 13,13,256 -> 13,13,512 -> 13,13,255 - P5_output = DarknetConv2D_BN_Leaky(512, (3,3))(P5) - P5_output = DarknetConv2D(num_anchors*(num_classes+5), (1,1))(P5_output) - - # 13,13,256 -> 13,13,128 -> 26,26,128 - P5_upsample = compose(DarknetConv2D_BN_Leaky(128, (1,1)), UpSampling2D(2))(P5) - - # 26,26,256 + 26,26,128 -> 26,26,384 - P4 = Concatenate()([P5_upsample, feat1]) - - # 26,26,384 -> 26,26,256 -> 26,26,255 - P4_output = DarknetConv2D_BN_Leaky(256, (3,3))(P4) - P4_output = DarknetConv2D(num_anchors*(num_classes+5), (1,1))(P4_output) - - return Model(inputs, [P5_output, P4_output]) - -#---------------------------------------------------# -# 将预测值的每个特征层调成真实值 -#---------------------------------------------------# -def yolo_head(feats, anchors, num_classes, input_shape, calc_loss=False): - num_anchors = len(anchors) - #---------------------------------------------------# - # [1, 1, 1, num_anchors, 2] - #---------------------------------------------------# - anchors_tensor = K.reshape(K.constant(anchors), [1, 1, 1, num_anchors, 2]) - - #---------------------------------------------------# - # 获得x,y的网格 - # (13, 13, 1, 2) - #---------------------------------------------------# - grid_shape = K.shape(feats)[1:3] - grid_y = K.tile(K.reshape(K.arange(0, stop=grid_shape[0]), [-1, 1, 1, 1]), - [1, grid_shape[1], 1, 1]) - grid_x = K.tile(K.reshape(K.arange(0, stop=grid_shape[1]), [1, -1, 1, 1]), - [grid_shape[0], 1, 1, 1]) - grid = K.concatenate([grid_x, grid_y]) - grid = K.cast(grid, K.dtype(feats)) - - #---------------------------------------------------# - # 将预测结果调整成(batch_size,13,13,3,85) - # 85可拆分成4 + 1 + 80 - # 4代表的是中心宽高的调整参数 - # 1代表的是框的置信度 - # 80代表的是种类的置信度 - #---------------------------------------------------# - feats = K.reshape(feats, [-1, grid_shape[0], grid_shape[1], num_anchors, num_classes + 5]) - - #---------------------------------------------------# - # 将预测值调成真实值 - # box_xy对应框的中心点 - # box_wh对应框的宽和高 - #---------------------------------------------------# - box_xy = (K.sigmoid(feats[..., :2]) + grid) / K.cast(grid_shape[::-1], K.dtype(feats)) - box_wh = K.exp(feats[..., 2:4]) * anchors_tensor / K.cast(input_shape[::-1], K.dtype(feats)) - box_confidence = K.sigmoid(feats[..., 4:5]) - box_class_probs = K.sigmoid(feats[..., 5:]) - - #---------------------------------------------------------------------# - # 在计算loss的时候返回grid, feats, box_xy, box_wh - # 在预测的时候返回box_xy, box_wh, box_confidence, box_class_probs - #---------------------------------------------------------------------# - if calc_loss == True: - return grid, feats, box_xy, box_wh - return box_xy, box_wh, box_confidence, box_class_probs - -#---------------------------------------------------# -# 对box进行调整,使其符合真实图片的样子 -#---------------------------------------------------# -def yolo_correct_boxes(box_xy, box_wh, input_shape, image_shape): - #-----------------------------------------------------------------# - # 把y轴放前面是因为方便预测框和图像的宽高进行相乘 - #-----------------------------------------------------------------# - box_yx = box_xy[..., ::-1] - box_hw = box_wh[..., ::-1] - - input_shape = K.cast(input_shape, K.dtype(box_yx)) - image_shape = K.cast(image_shape, K.dtype(box_yx)) - - new_shape = K.round(image_shape * K.min(input_shape/image_shape)) - #-----------------------------------------------------------------# - # 这里求出来的offset是图像有效区域相对于图像左上角的偏移情况 - # new_shape指的是宽高缩放情况 - #-----------------------------------------------------------------# - offset = (input_shape-new_shape)/2./input_shape - scale = input_shape/new_shape - - box_yx = (box_yx - offset) * scale - box_hw *= scale - - box_mins = box_yx - (box_hw / 2.) - box_maxes = box_yx + (box_hw / 2.) - boxes = K.concatenate([ - box_mins[..., 0:1], # y_min - box_mins[..., 1:2], # x_min - box_maxes[..., 0:1], # y_max - box_maxes[..., 1:2] # x_max - ]) - - boxes *= K.concatenate([image_shape, image_shape]) - return boxes - -#---------------------------------------------------# -# 获取每个box和它的得分 -#---------------------------------------------------# -def yolo_boxes_and_scores(feats, anchors, num_classes, input_shape, image_shape, letterbox_image): - #-----------------------------------------------------------------# - # 将预测值调成真实值 - # box_xy : -1,13,13,3,2; - # box_wh : -1,13,13,3,2; - # box_confidence : -1,13,13,3,1; - # box_class_probs : -1,13,13,3,80; - #-----------------------------------------------------------------# - box_xy, box_wh, box_confidence, box_class_probs = yolo_head(feats, anchors, num_classes, input_shape) - #-----------------------------------------------------------------# - # 在图像传入网络预测前会进行letterbox_image给图像周围添加灰条 - # 因此生成的box_xy, box_wh是相对于有灰条的图像的 - # 我们需要对齐进行修改,去除灰条的部分。 - # 将box_xy、和box_wh调节成y_min,y_max,xmin,xmax - #-----------------------------------------------------------------# - if letterbox_image: - boxes = yolo_correct_boxes(box_xy, box_wh, input_shape, image_shape) - else: - box_yx = box_xy[..., ::-1] - box_hw = box_wh[..., ::-1] - box_mins = box_yx - (box_hw / 2.) - box_maxes = box_yx + (box_hw / 2.) - - input_shape = K.cast(input_shape, K.dtype(box_yx)) - image_shape = K.cast(image_shape, K.dtype(box_yx)) - - boxes = K.concatenate([ - box_mins[..., 0:1] * image_shape[0], # y_min - box_mins[..., 1:2] * image_shape[1], # x_min - box_maxes[..., 0:1] * image_shape[0], # y_max - box_maxes[..., 1:2] * image_shape[1] # x_max - ]) - #-----------------------------------------------------------------# - # 获得最终得分和框的位置 - #-----------------------------------------------------------------# - boxes = K.reshape(boxes, [-1, 4]) - box_scores = box_confidence * box_class_probs - box_scores = K.reshape(box_scores, [-1, num_classes]) - return boxes, box_scores - -#---------------------------------------------------# -# 图片预测 -#---------------------------------------------------# -def yolo_eval(yolo_outputs, - anchors, - num_classes, - image_shape, - max_boxes=20, - score_threshold=.6, - iou_threshold=.5, - letterbox_image=True): - #---------------------------------------------------# - # 获得特征层的数量,有效特征层的数量为3 - #---------------------------------------------------# - num_layers = len(yolo_outputs) - #-----------------------------------------------------------# - # 13x13的特征层对应的anchor是[81,82], [135,169], [344,319] - # 26x26的特征层对应的anchor是[23,27], [37,58], [81,82] - #-----------------------------------------------------------# - anchor_mask = [[6,7,8], [3,4,5], [0,1,2]] if num_layers==3 else [[3,4,5], [1,2,3]] - - #-----------------------------------------------------------# - # 这里获得的是输入图片的大小,一般是416x416 - #-----------------------------------------------------------# - input_shape = K.shape(yolo_outputs[0])[1:3] * 32 - boxes = [] - box_scores = [] - #-----------------------------------------------------------# - # 对每个特征层进行处理 - #-----------------------------------------------------------# - for l in range(num_layers): - _boxes, _box_scores = yolo_boxes_and_scores(yolo_outputs[l], anchors[anchor_mask[l]], num_classes, input_shape, image_shape, letterbox_image) - boxes.append(_boxes) - box_scores.append(_box_scores) - #-----------------------------------------------------------# - # 将每个特征层的结果进行堆叠 - #-----------------------------------------------------------# - boxes = K.concatenate(boxes, axis=0) - box_scores = K.concatenate(box_scores, axis=0) - - #-----------------------------------------------------------# - # 判断得分是否大于score_threshold - #-----------------------------------------------------------# - mask = box_scores >= score_threshold - max_boxes_tensor = K.constant(max_boxes, dtype='int32') - boxes_ = [] - scores_ = [] - classes_ = [] - for c in range(num_classes): - #-----------------------------------------------------------# - # 取出所有box_scores >= score_threshold的框,和成绩 - #-----------------------------------------------------------# - class_boxes = tf.boolean_mask(boxes, mask[:, c]) - class_box_scores = tf.boolean_mask(box_scores[:, c], mask[:, c]) - - #-----------------------------------------------------------# - # 非极大抑制 - # 保留一定区域内得分最大的框 - #-----------------------------------------------------------# - nms_index = tf.image.non_max_suppression( - class_boxes, class_box_scores, max_boxes_tensor, iou_threshold=iou_threshold) - - #-----------------------------------------------------------# - # 获取非极大抑制后的结果 - # 下列三个分别是 - # 框的位置,得分与种类 - #-----------------------------------------------------------# - class_boxes = K.gather(class_boxes, nms_index) - class_box_scores = K.gather(class_box_scores, nms_index) - classes = K.ones_like(class_box_scores, 'int32') * c - boxes_.append(class_boxes) - scores_.append(class_box_scores) - classes_.append(classes) - boxes_ = K.concatenate(boxes_, axis=0) - scores_ = K.concatenate(scores_, axis=0) - classes_ = K.concatenate(classes_, axis=0) - - return boxes_, scores_, classes_ - - -- GitLab