YOLOV1代码详解

 

目标检测之yolo源码解析

关于yolo目标检测的原理请参考前面一篇文章:目标检测之YOLO算法详解

在讲解源码之前,我们需要做一些准备工作:

  1. 下载源码,本文所使用的yolo源码来源于网址:https://github.com/hizhangp/yolo_tensorflow
  2. 下载训练所使用的数据集,我们仍然使用以VOC 2012数据集为例,下载地址为:http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCtrainval_11-May-2012.tar。
  3. yolo源码所在目录下,创建一个目录data,然后在data里面创建一个pascal_voc目录,用来保存与VOC 2012数据集相关的数据,我们把下载好的数据集解压到该目录下,如下图所示,其中VOCdevkit为数据集解压得到的文件,剩余三个文件夹我们先不用理会,后面会详细介绍
  4. 下载与训练模型,即YOLO_small文件,我们把下载好之后的文件解压放在weights文件夹下面。下载链接:https://drive.google.com/file/d/0B5aC8pI-akZUNVFZMmhmcVRpbTA/view?usp=sharing,需要FQ才能下载,可以使用自-由-门FQ软件。

  5. 根据自己的需求修改配置文件yolo/config.py。

  6. 运行train.py文件,开始训练。
  7. 运行test.py文件,开始测试。

 二  yolo代码文件结构

如果你按照上面我说的步骤配置好文件之后,源代码结构就会如下图所示:

我们来粗略的介绍一下每个文件的功能:

  • data文件夹,上面已经说过了,存放数据集以及训练时生成的模型,缓存文件。
  • test文件夹,用来存放测试时用到的图片。
  • utils文件夹,包含两个文件一个是pascal_voc.py,主要用来获取训练集图片文件,以及生成对应的标签文件,为yolo网络训练做准备。另一个文件是timer.py用来计时。
  • yolo文件夹,也包含两个文件,config.py包含yolo网络的配置参数,yolo_net.py文件包含yolo网络的结构。
  • train.py文件用来训练yolo网络。
  • test.py文件用来测试yolo网络。

三 config.py文件讲解

我们先从配置文件说起,代码如下:

# -*- coding: utf-8 -*-
"""
Created on Tue Jun 12 12:08:15 2018

@author: lenovo
"""

'''
配置参数
'''

import os


#
# 数据集路径,和模型检查点文件路径
#

DATA_PATH = 'data'           #所有数据所在的根目录

PASCAL_PATH = os.path.join(DATA_PATH, 'pascal_voc')   #VOC2012数据集所在的目录

CACHE_PATH = os.path.join(PASCAL_PATH, 'cache')       #保存生成的数据集标签缓冲文件所在文件夹

OUTPUT_DIR = os.path.join(PASCAL_PATH, 'output')      #保存生成的网络模型和日志文件所在的文件夹

WEIGHTS_DIR = os.path.join(PASCAL_PATH, 'weights')    #检查点文件所在的目录

#WEIGHTS_FILE = None

WEIGHTS_FILE = os.path.join(WEIGHTS_DIR, 'YOLO_small.ckpt')

#VOC 2012数据集类别名
CLASSES = ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus',
           'car', 'cat', 'chair', 'cow', 'diningtable', 'dog', 'horse',
           'motorbike', 'person', 'pottedplant', 'sheep', 'sofa',
           'train', 'tvmonitor']
#使用水平镜像,扩大一倍数据集
FLIPPED = True

'''
网络模型参数
'''

#图片大小
IMAGE_SIZE = 448

#单元格大小S  一共有CELL_SIZExCELL_SIZE个单元格  
CELL_SIZE = 7

#每个单元格边界框的个数B
BOXES_PER_CELL = 2
#泄露修正线性激活函数 系数
ALPHA = 0.1
#控制台输出信息
DISP_CONSOLE = False

#损失函数 的权重设置
OBJECT_SCALE = 1.0   #有目标时,置信度权重
NOOBJECT_SCALE = 1.0 #没有目标时,置信度权重
CLASS_SCALE = 2.0    #类别权重
COORD_SCALE = 5.0    #边界框权重



'''
训练参数设置
'''

GPU = ''
#学习率
LEARNING_RATE = 0.0001
#退化学习率衰减步数
DECAY_STEPS = 30000
#衰减率
DECAY_RATE = 0.1
STAIRCASE = True
#批量大小
BATCH_SIZE = 45
#最大迭代次数
MAX_ITER = 15000
#日志文件保存间隔步
SUMMARY_ITER = 10
#模型保存间隔步
SAVE_ITER = 500


'''
测试时的相关参数
'''
#格子有目标的置信度阈值
THRESHOLD = 0.2
#非极大值抑制 IoU阈值
IOU_THRESHOLD = 0.5

各个参数我已经在上面注释了,下面就不在重复了。下面我们来介绍yolo网络的构建。

四 yolo.py文件讲解

yolo网络的建立是通过yolo文件夹中的yolo_net.py文件的代码实现的,yolo_net.py文件定义了YOLONet类,该类包含了网路初始化(__init__()),建立网络(build_networks)和loss函数(loss_layer())等方法。

# -*- coding: utf-8 -*-
"""
Created on Tue Jun 12 12:08:15 2018

@author: lenovo
"""

'''
定义YOLO网络模型
https://blog.youkuaiyun.com/qq_34784753/article/details/78803423
https://blog.youkuaiyun.com/qq1483661204/article/details/79681926
'''

import numpy as np
import tensorflow as tf
import yolo.config as cfg
import logging
import sys

slim = tf.contrib.slim

#配置logging
logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s',
                    level=logging.INFO,
                    stream=sys.stdout)

class YOLONet(object):

1、网络参数初始化

网络的所有初始化参数包含于__init__()方法中。

    def __init__(self, is_training=True):
        '''
        构造函数 
        利用 cfg 文件对网络参数进行初始化,同时定义网络的输入和输出 size 等信息,
        其中 offset 的作用应该是一个定长的偏移
        boundery1和boundery2 作用是在输出中确定每种信息的长度(如类别,置信度等)。
        其中 boundery1 指的是对于所有的 cell 的类别的预测的张量维度,所以是 self.cell_size * self.cell_size * self.num_class
        boundery2 指的是在类别之后每个cell 所对应的 bounding boxes 的数量的总和,所以是self.boundary1 + self.cell_size * self.cell_size * self.boxes_per_cell
        
        args:
            is_training:训练?
        '''
        #VOC 2012数据集类别名
        self.classes = cfg.CLASSES
        #类别个数C 20
        self.num_class = len(self.classes)
        #网络输入图像大小448, 448 x 448
        self.image_size = cfg.IMAGE_SIZE
        #单元格大小S=7  将图像分为SxS的格子
        self.cell_size = cfg.CELL_SIZE
        #每个网格边界框的个数B=2
        self.boxes_per_cell = cfg.BOXES_PER_CELL
        #网络输出的大小 S*S*(B*5 + C) = 1470
        self.output_size = (self.cell_size * self.cell_size) *\
            (self.num_class + self.boxes_per_cell * 5)
        #图片的缩放比例 64
        self.scale = 1.0 * self.image_size / self.cell_size        
        '''#将网络输出分离为类别和置信度以及边界框的大小,输出维度为7*7*20 + 7*7*2 + 7*7*2*4=1470'''
        #7*7*20
        self.boundary1 = self.cell_size * self.cell_size * self.num_class
        #7*7*20+7*7*2
        self.boundary2 = self.boundary1 +\
            self.cell_size * self.cell_size * self.boxes_per_cell

        #代价函数 权重
        self.object_scale = cfg.OBJECT_SCALE  #1
        self.noobject_scale = cfg.NOOBJECT_SCALE  #1
        self.class_scale = cfg.CLASS_SCALE  #2.0
        self.coord_scale = cfg.COORD_SCALE  #5.0
        
        #学习率0.0001
        self.learning_rate = cfg.LEARNING_RATE
        #批大小 45
        self.batch_size = cfg.BATCH_SIZE
        #泄露修正线性激活函数 系数0.1
        self.alpha = cfg.ALPHA

        #偏置 形状[7,7,2]
        self.offset = np.transpose(np.reshape(np.array(
            [np.arange(self.cell_size)] * self.cell_size * self.boxes_per_cell),
            (self.boxes_per_cell, self.cell_size, self.cell_size)), (1, 2, 0))

        #输入图片占位符 [NONE,image_size,image_size,3]
        self.images = tf.placeholder(
            tf.float32, [None, self.image_size, self.image_size, 3],
            name='images')
        #构建网络 获取YOLO网络的输出(不经过激活函数的输出)  形状[None,1470]
        self.logits = self.build_network(
            self.images, num_outputs=self.output_size, alpha=self.alpha,
            is_training=is_training)

        if is_training:
            #设置标签占位符 [None,S,S,5+C]  即[None,7,7,25]
            self.labels = tf.placeholder(
                tf.float32,
                [None, self.cell_size, self.cell_size, 5 + self.num_class])
            #设置损失函数
            self.loss_layer(self.logits, self.labels)
            #加入权重正则化之后的损失函数
            self.total_loss = tf.losses.get_total_loss()
            #将损失以标量形式显示,该变量命名为total_loss
            tf.summary.scalar('total_loss', self.total_loss)

2、构建网络

网络的建立是通过build_network()函数实现的,网络由卷积层,池化层和全连接层组成,网络的输入维度是[None,448,448,3],输出维度为[None,1470]。

 def build_network(self,
                      images,
                      num_outputs,
                      alpha,
                      keep_prob=0.5,
                      is_training=True,
                      scope='yolo'):
        '''
        构建YOLO网络
        
        args:
            images:输入图片占位符 [None,image_size,image_size,3]  这里是[None,448,448,3]
            num_outputs:标量,网络输出节点数 1470
            alpha:泄露修正线性激活函数 系数0.1
            keep_prob:弃权 保留率
            is_training:训练?
            scope:命名空间名
            
        return:
            返回网络最后一层,激活函数处理之前的值  形状[None,1470]
        '''
        #定义变量命名空间
        with tf.variable_scope(scope):
            #定义共享参数  使用l2正则化
            with slim.arg_scope(
                [slim.conv2d, slim.fully_connected],
                activation_fn=leaky_relu(alpha),
                weights_regularizer=slim.l2_regularizer(0.0005),
                weights_initializer=tf.truncated_normal_initializer(0.0, 0.01)
            ):
                logging.info('image shape{0}'.format(images.shape))
                #pad_1 填充 454x454x3
                net = tf.pad(
                    images, np.array([[0, 0], [3, 3], [3, 3], [0, 0]]),
                    name='pad_1')
                logging.info('Layer pad_1  {0}'.format(net.shape))
                #卷积层conv_2 s=2    (n-f+1)/s向上取整    224x224x64
                net = slim.conv2d(
                    net, 64, 7, 2, padding='VALID', scope='conv_2')         
                logging.info('Layer conv_2 {0}'.format(net.shape))
                #池化层pool_3 112x112x64
                net = slim.max_pool2d(net, 2, padding='SAME', scope='pool_3')
                logging.info('Layer pool_3 {0}'.format(net.shape))
                #卷积层conv_4、3x3x192 s=1  n/s向上取整   112x112x192
                net = slim.conv2d(net, 192, 3, scope='conv_4')
                logging.info('Layer conv_4 {0}'.format(net.shape))
                #池化层pool_5 56x56x192
                net = slim.max_pool2d(net, 2, padding='SAME', scope='pool_5')
                logging.info('Layer pool_5 {0}'.format(net.shape))
                #卷积层conv_6、1x1x128 s=1  n/s向上取整  56x56x128
                net = slim.conv2d(net, 128, 1, scope='conv_6')
                logging.info('Layer conv_6 {0}'.format(net.shape))
                #卷积层conv_7、3x3x256 s=1  n/s向上取整 56x56x256
                net = slim.conv2d(net, 256, 3, scope='conv_7')
                logging.info('Layer conv_7 {0}'.format(net.shape))
                #卷积层conv_8、1x1x256 s=1  n/s向上取整 56x56x256
                net = slim.conv2d(net, 256, 1, scope='conv_8')
                logging.info('Layer conv_8 {0}'.format(net.shape))
                #卷积层conv_9、3x3x512 s=1  n/s向上取整 56x56x512
                net = slim.conv2d(net, 512, 3, scope='conv_9')
                logging.info('Layer conv_9 {0}'.format(net.shape))
                #池化层pool_10 28x28x512
                net = slim.max_pool2d(net, 2, padding='SAME', scope='pool_10')
                logging.info('Layer pool_10 {0}'.format(net.shape))
                #卷积层conv_11、1x1x256 s=1  n/s向上取整 28x28x256
                net = slim.conv2d(net, 256, 1, scope='conv_11')
                logging.info('Layer conv_11 {0}'.format(net.shape))
                #卷积层conv_12、3x3x512 s=1  n/s向上取整 28x28x512
                net = slim.conv2d(net, 512, 3, scope='conv_12')
                logging.info('Layer conv_12 {0}'.format(net.shape))
                #卷积层conv_13、1x1x256 s=1  n/s向上取整 28x28x256
                net = slim.conv2d(net, 256, 1, scope='conv_13')
                logging.info('Layer conv_13 {0}'.format(net.shape))
                #卷积层conv_14、3x3x512 s=1  n/s向上取整 28x28x512
                net = slim.conv2d(net, 512, 3, scope='conv_14')
                logging.info('Layer conv_14 {0}'.format(net.shape))
                #卷积层conv_15、1x1x256 s=1  n/s向上取整 28x28x256
                net = slim.conv2d(net, 256, 1, scope='conv_15')
                logging.info('Layer conv_15 {0}'.format(net.shape))                
                #卷积层conv_16、3x3x512 s=1  n/s向上取整 28x28x512
                net = slim.conv2d(net, 512, 3, scope='conv_16')
                logging.info('Layer
Yolov8是一个目标检测模型,它是由深度学习框架PyTorch实现的。关于Yolov8代码详解,你可以参考引用中提供的"yolov5代码详解Yolov5代码详解.zip"文件。该文件应该包含了Yolov5的代码及其详细解释。 此外,如果你只是想使用Yolov8进行目标检测,你也可以使用引用中提供的命令方式进行安装和使用。通过该命令,你可以预测模型(yolov8n.pt)在指定的图像(source)上进行目标检测。 另外,如果你对Yolov8的分割模型感兴趣,你可以使用引用中提到的-yolov8n-seg.pt模型,该模型在COCO数据集上进行了预训练,并可以用于目标分割任务。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Yolov5代码详解.zip](https://download.youkuaiyun.com/download/liufang_imei/87555127)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [YOLOv8详解代码实战,附有效果图](https://blog.youkuaiyun.com/weixin_45277161/article/details/130200494)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [YOLOv8详解 【网络结构+代码+实操】](https://blog.youkuaiyun.com/zyw2002/article/details/128732494)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值