目标检测 算法yolov3解惑(一)之三种尺度的检测

def DarknetConv(x, filters, size, strides=1, batch_norm=True):
    if strides == 1:
        padding = 'same'
    else:
        x = ZeroPadding2D(((1, 0), (1, 0)))(x)  # top left half-padding
        padding = 'valid'
    x = Conv2D(filters=filters, kernel_size=size,
               strides=strides, padding=padding,
               use_bias=not batch_norm, kernel_regularizer=l2(0.0005))(x)
    if batch_norm:
        x = BatchNormalization()(x)
        x = LeakyReLU(alpha=0.1)(x)
    return x


def DarknetResidual(x, filters):
    prev = x
    x = DarknetConv(x, filters // 2, 1)
    x = DarknetConv(x, filters, 3)
    x = Add()([prev, x])
    return x


def DarknetBlock(x, filters, blocks):
    x = DarknetConv(x, filters, 3, strides=2)
    for _ in range(blocks):
        x = DarknetResidual(x, filters)
    return x


def Darknet(name=None):
    x = inputs = Input([None, None, 3])
    x = DarknetConv(x, 32, 3)
    x = DarknetBlock(x, 64, 1)
    x = DarknetBlock(x, 128, 2)  # skip connection
    x = x_36 = DarknetBlock(x, 256, 8)  # skip connection
    x = x_61 = DarknetBlock(x, 512, 8)
    x = DarknetBlock(x, 1024, 4)
    return tf.keras.Model(inputs, (x_36, x_61, x), name=name)
    
yolov3最突出的特点是它可以在三种不同的尺度上进行检测。代码如下
    #这里体现了yolov3 模型的多尺度,就是同时提取模型的多层特征
    #如下的 x_36, x_61, x
    x_36, x_61, x = Darknet(name='yolo_darknet')(x)
并且特征层的提取到输出还有一定的交叉
    #仅仅是x 特征的输出
    output_0 = YoloOutput(512, len(masks[0]), classes, name='yolo_output_0')(x)
    #同时融合 (x, x_61)的输出
    x = YoloConv(256, name='yolo_conv_1')((x, x_61))
    output_1 = YoloOutput(256, len(masks[1]), classes, name='yolo_output_1')(x)
    
    #同时融合 (x, x_36)的输出
    x = YoloConv(128, name='yolo_conv_2')((x, x_36))
    output_2 = YoloOutput(128, len(masks[2]), classes, name='yolo_output_2')(x)
def YoloV3(size=None, channels=3, anchors=yolo_anchors,
           masks=yolo_anchor_masks, classes=80, training=False):
    
    
    size=None
    channels=3
    anchors=yolo_anchors
    masks=yolo_anchor_masks
    classes=80
    training=False
    x = inputs = Input([size, size, channels], name='input')
    
    #这里通过输入矩阵x 提取特征
    
    """
    x_36.shape =TensorShape([1, 52, 52, 256])
    x_61.shape = TensorShape([1, 26, 26, 512])
    x.shape    =TensorShape([1, 13, 13, 1024])
    
    
    """
    #这里体现了yolov3 模型的多尺度,就是同时提取模型的多层特征
    #如下的 x_36, x_61, x
    x_36, x_61, x = Darknet(name='yolo_darknet')(x)

    x = YoloConv(512, name='yolo_conv_0')(x)
    
    #仅仅是x 特征的输出
    output_0 = YoloOutput(512, len(masks[0]), classes, name='yolo_output_0')(x)
    #同时融合 (x, x_61)的输出
    x = YoloConv(256, name='yolo_conv_1')((x, x_61))
    output_1 = YoloOutput(256, len(masks[1]), classes, name='yolo_output_1')(x)
    
    #同时融合 (x, x_36)的输出
    x = YoloConv(128, name='yolo_conv_2')((x, x_36))
    output_2 = YoloOutput(128, len(masks[2]), classes, name='yolo_output_2')(x)

    # if training:
    #     return Model(inputs, (output_0, output_1, output_2), name='yolov3')

    boxes_0 = Lambda(lambda x: yolo_boxes(x, anchors[masks[0]], classes),
                     name='yolo_boxes_0')(output_0)
    boxes_1 = Lambda(lambda x: yolo_boxes(x, anchors[masks[1]], classes),
                     name='yolo_boxes_1')(output_1)
    boxes_2 = Lambda(lambda x: yolo_boxes(x, anchors[masks[2]], classes),
                     name='yolo_boxes_2')(output_2)

    outputs = Lambda(lambda x: yolo_nms(x, anchors, masks, classes),
                     name='yolo_nms')((boxes_0[:3], boxes_1[:3], boxes_2[:3]))

    return Model(inputs, outputs, name='yolov3')
posted @ 2022-08-19 22:49  luoganttcc  阅读(23)  评论(0)    收藏  举报