YOLO-V3代码解析系列(四) —— 网络结构(backbone.py)

结构简述

主要用了darknet-53,采用全卷积模式的结构,同时通过级联不同尺度的特征,可以使得网络对不同尺度的目标具有更好的适应性。

网络结构图

  yolo-v3训练过程中,随机选择输入尺度,必须是32的倍数,比如[320,352,384,416,448,480,512,544,576,608]. 下面的结构图,以416x416x3为例,output_stride=[8,16,32],对应的输出分别为52x52x255,26x26x255,13x13x255。由于,8倍尺度降低的感受野更小,所以该尺度适用于检测小目标,相应的,26x26检测中等大小的目标,而13x13适合检测大目标。
  图中,coco数据集的检测类别为80类,所以 255 = 3 *(4+1+80),其中每个 grid cell 预测3个框,4+1分别是边界框的中心和宽高,以及置信度(x,y,w,h)
在这里插入图片描述

代码分析

import core.common as common
import tensorflow as tf


def darknet53(input_data, trainable):
    """ backbone network: darknet53 """
    with tf.variable_scope('darknet'):

        input_data = common.convolutional(input_data, filters_shape=(3, 3,  3,  32), trainable=trainable, name='conv0')
        input_data = common.convolutional(input_data,
                                          filters_shape=(3, 3, 32, 64),
                                          trainable=trainable,
                                          name='conv1',
                                          downsample=True)
        # 定义残差模块:0
        for i in range(1):
            input_data = common.residual_block(input_data,  64,  32, 64, trainable=trainable, name='residual%d' %(i+0))

        input_data = common.convolutional(input_data, filters_shape=(3, 3,  64, 128),
                                          trainable=trainable, name='conv4', downsample=True)
        # 定义残差模块:1,2
        for i in range(2):
            input_data = common.residual_block(input_data, 128,  64, 128, trainable=trainable, name='residual%d' %(i+1))

        input_data = common.convolutional(input_data, filters_shape=(3, 3, 128, 256),
                                          trainable=trainable, name='conv9', downsample=True)

        # 定义残差模块:3-10
        for i in range(8):
            input_data = common.residual_block(input_data, 256, 128, 256, trainable=trainable, name='residual%d' %(i+3))

        route_1 = input_data
        input_data = common.convolutional(input_data, filters_shape=(3, 3, 256, 512),
                                          trainable=trainable, name='conv26', downsample=True)

        # 定义残差模块:11-18
        for i in range(8):
            input_data = common.residual_block(input_data, 512, 256, 512, trainable=trainable, name='residual%d' %(i+11))

        route_2 = input_data
        input_data = common.convolutional(input_data, filters_shape=(3, 3, 512, 1024),
                                          trainable=trainable, name='conv43', downsample=True)

        # 定义残差模块:19-22
        for i in range(4):
            input_data = common.residual_block(input_data, 1024, 512, 1024, trainable=trainable, name='residual%d' %(i+19))

        return route_1, route_2, input_data

DarkNet-53

  darknet-53是yolo-v3特征提取的主干网络,权重是在ImageNet训练得到,下载地址darknet53.conv.74。Darknet-53 的主体框架如下图所示,它主要由 Convolutional 和 Residual 结构所组成。需要特别注意的是,最后三层 Avgpool、Connected 和 softmax layer 是用于在 Imagenet 数据集上作分类训练用的。当我们用 Darknet-53 层对图片提取特征时,是不会用到这三层的。
DarkNet-53
Darknet-53 有多牛逼?看看下面这张图,作者进行了比较,Darknet-53 在精度上可以与最先进的分类器媲美,同时它的浮点运算更少,计算速度也最快。和 ReseNet-101 相比,Darknet-53 网络的速度是前者的1.5倍;虽然 ReseNet-152 和它性能相似,但是用时却是它的2倍以上。
在这里插入图片描述

YOLO-V3部分

    def __build_network(self, input_data):
        # input_data:32倍输出
        # route_1:8倍输出
        # route_2:16倍输出
        route_1, route_2, input_data = backbone.darknet53(input_data, self.trainable)

        # DBL*5
        input_data = common.convolutional(input_data, (1, 1, 1024, 512), self.trainable, 'conv52')
        input_data = common.convolutional(input_data, (3, 3, 512, 1024), self.trainable, 'conv53')
        input_data = common.convolutional(input_data, (1, 1, 1024, 512), self.trainable, 'conv54')
        input_data = common.convolutional(input_data, (3, 3, 512, 1024), self.trainable, 'conv55')
        input_data = common.convolutional(input_data, (1, 1, 1024, 512), self.trainable, 'conv56')

        # 网络输出1:13x13x255,针对大尺寸目标
        conv_lobj_branch = common.convolutional(input_data, (3, 3, 512, 1024), self.trainable, name='conv_lobj_branch')
        conv_lbbox = common.convolutional(conv_lobj_branch, (1, 1, 1024, 3 * (self.num_class + 5)),
                                          trainable=self.trainable, name='conv_lbbox', activate=False, bn=False)

        # 上采样与route_2级联,采用最近邻差值,不需要学习额外的参数
        input_data = common.convolutional(input_data, (1, 1, 512, 256), self.trainable, 'conv57')
        input_data = common.upsample(input_data, name='upsample0', method=self.upsample_method)

        with tf.variable_scope('route_1'):
            input_data = tf.concat([input_data, route_2], axis=-1)

        # DBL*5
        input_data = common.convolutional(input_data, (1, 1, 768, 256), self.trainable, 'conv58')
        input_data = common.convolutional(input_data, (3, 3, 256, 512), self.trainable, 'conv59')
        input_data = common.convolutional(input_data, (1, 1, 512, 256), self.trainable, 'conv60')
        input_data = common.convolutional(input_data, (3, 3, 256, 512), self.trainable, 'conv61')
        input_data = common.convolutional(input_data, (1, 1, 512, 256), self.trainable, 'conv62')

        # 网络输出2:26x26x255,针对中等尺寸目标
        conv_mobj_branch = common.convolutional(input_data, (3, 3, 256, 512), self.trainable, name='conv_mobj_branch')
        conv_mbbox = common.convolutional(conv_mobj_branch, (1, 1, 512, 3 * (self.num_class + 5)),
                                          trainable=self.trainable, name='conv_mbbox', activate=False, bn=False)

        # 上采样与route_1级联
        input_data = common.convolutional(input_data, (1, 1, 256, 128), self.trainable, 'conv63')
        input_data = common.upsample(input_data, name='upsample1', method=self.upsample_method)

        with tf.variable_scope('route_2'):
            input_data = tf.concat([input_data, route_1], axis=-1)

        input_data = common.convolutional(input_data, (1, 1, 384, 128), self.trainable, 'conv64')
        input_data = common.convolutional(input_data, (3, 3, 128, 256), self.trainable, 'conv65')
        input_data = common.convolutional(input_data, (1, 1, 256, 128), self.trainable, 'conv66')
        input_data = common.convolutional(input_data, (3, 3, 128, 256), self.trainable, 'conv67')
        input_data = common.convolutional(input_data, (1, 1, 256, 128), self.trainable, 'conv68')

        # 网络输出3:52x52x255,针对小尺寸目标
        conv_sobj_branch = common.convolutional(input_data, (3, 3, 128, 256), self.trainable, name='conv_sobj_branch')
        conv_sbbox = common.convolutional(conv_sobj_branch,
                                          (1, 1, 256, 3 * (self.num_class + 5)),
                                          trainable=self.trainable,
                                          name='conv_sbbox', activate=False, bn=False)

        return conv_lbbox, conv_mbbox, conv_sbbox

多尺度检测
YOLOv3 对输入图片进行了粗、中和细网格划分,以便分别实现对大、中和小物体的预测。假如输入图片的尺寸为 416X416, 那么得到粗、中和细网格尺寸分别为 13X13、26X26 和 52X52。这样一算,那就是在长宽尺寸上分别缩放了 32、16 和 8 倍。
在这里插入图片描述
参考资源:
https://yunyang1994.github.io/posts/YOLOv3/#more

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
yolo-v5系列算法是一种基于深度学习的目标检测算法,其通过将输入图像划分为一系列网格单元,并对每个单元预测出目标的类别和边界框,从而实现对图像中目标的检测和定位。 模型移植是指将训练好的yolo-v5模型从一个平台或框架移植到另一个平台或框架的过程。在实际应用中,由于硬件设备或软件平台的限制,往往需要将模型移植到适用于特定平台的框架上,以便进行推理和应用。 模型移植的主要步骤包括模型导出、模型转换和模型部署。首先,需要将yolo-v5模型导出为通用的模型文件,例如ONNX或TensorFlow格式。然后,利用模型转换工具将导出的模型文件转换为目标平台所支持的模型格式,如Tensorflow Lite或Caffe等。最后,将转换后的模型部署到目标平台上,以便进行推理和应用。 模型移植的关键问题是确保模型在移植过程中的准确性和效率。为了保持模型的准确性,需要注意模型转换过程中参数的正确性和一致性。同时,还需要针对目标平台的硬件设备和软件框架进行优化,以提高模型在目标平台上的推理速度和性能。 总而言之,yolo-v5系列算法的模型移植是将训练好的模型从一个平台移植到另一个平台的过程。通过合理的模型导出、转换和部署步骤,可以将yolo-v5模型应用于不同的硬件设备和软件平台,以实现目标检测和定位的应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值