• Darknet的整体框架,安装,训练与测试


    目录

    一、Darknet优势

    二、Darknet的结构

    三、Darknet安装

    四、Darknet的训练

    五、Darknet的检测

    正文

    一、Darknet优势

    darknet是一个由纯C编写的深度学习框架,它有着其它深度学习框架无法相比的优势:

    1.易于安装:在makefile里面选择自己需要的附加项(cuda,cudnn,opencv等)直接make即可,几分钟完成安装;
    2.没有任何依赖项:整个框架都用C语言进行编写,可以不依赖任何库,连opencv作者都编写了可以对其进行替代的函数;
    3.结构明晰,源代码查看、修改方便:其框架的基础文件都在src文件夹,而定义的一些检测、分类函数则在example文件夹,可根据需要直接对源代码进行查看和修改;
    4.友好python接口:虽然darknet使用c语言进行编写,但是也提供了python的接口,通过python函数,能够使用python直接对训练好的.weight格式的模型进行调用;
    5.易于移植:部署到机器本地十分简单,且可以根据机器情况,使用cpu和gpu,特别是检测识别任务的本地端部署。

    二、Darknet结构

        darknet整理结构图:

     |--cfg
     |------coco.data
     |------darknet.cfg
     |------...
     |------yolov3.cfg
     |--data
     |------coco.names
     |------...
     |--examples
     |------classifier.c
     |------detector.c
     |------...
     |--include
     |------darknet.h
     |--python
     |------darknet.py
     |------...
     |--scripts
     |------get_coco_dataset.sh
     |------...
     |--src
     |------convolutional_layer.c
     |------convolutional_layer.h
     |------convolutional_kernels.cu
     |------...
     |--darknet53.conv.74
     |--LICENSE
     |--Makefile
     |--ReadMe.md
    View Code

        各文件夹功能解释:

        1.cfg文件夹内是一些模型的架构,通过该文件定义整个模型的架构

        2.data文件夹内放置了一些label文件,和一些样例图

        3.src文件夹内全是最底层的框架定义文件,所有层的定义等最基本的函数全部在该文件夹内

        4.examples文件夹是更为高层的一些函数,如检测函数,识别函数等,这些函数直接调用了底层的函数,我们经常使用的就是example中的函数;

        5.include文件夹,存放头文件的地方;

        6.python文件夹里是使用python对模型的调用方法,基本都在darknet.py中; 

        7.scripts文件夹中是一些脚本,如下载coco数据集,将voc格式的数据集转换为训练所需格式的脚本等

        8.除了license文件,剩下的就是Makefile文件

    三、Darknet安装

        1、打开Makefile文件,将需要的选项设置为1,使用GPU和CUDNN:

    在这里插入图片描述

       2、打开终端,进入到darknet文件夹根目录,输入make,开始编译

       3、编译完成后,在根目录下,会多出一些文件夹和文件:obj文件夹中存放了编译过程中的.o文件,另外,还生成了三个文件:可执行文件darknet.exe,静态链接库libdarknet.a和动态链接库libdarknet.so。本地进行模型调用可直接使用darknet.exe,而如果要移植到其它平台,就需要用到libdarknet.so这个动态链接库。不过,该动态链接库只包含了src文件夹中定义的框架基础函数,并没有包含examples中的上层函数,所以在调用过程中需要自己去定义检测函数。

    四、Darknet的训练

         1、数据准备

            将数据的groundtruth转化为darknet需要的格式,如果你的gt为voc格式的xml,可以通过如下脚本进行转换

    import xml.etree.ElementTree as ET
    import pickle
    import os
    from os import listdir, getcwd
    from os.path import join
    classes = ["car"]#类别改为自己需要检测的所有类别
    def convert(size, box):
        dw = 1./size[0]
        dh = 1./size[1]
        x = (box[0] + box[1])/2.0
        y = (box[2] + box[3])/2.0
        w = box[1] - box[0]
        h = box[3] - box[2]
        x = x*dw
        w = w*dw
        y = y*dh
        h = h*dh
        return (x,y,w,h)
    def convert_annotation(image_id):
        in_file = open(xml_path)#与图片对应的xml文件所在的地址
        out_file = open(txt_save_path,'w') #与此xml对应的转换后的txt,这个txt的保存完整路径
        tree=ET.parse(in_file)
        root = tree.getroot()
        size = root.find('size')  #访问size标签的数据
        w = int(size.find('width').text)#读取size标签中宽度的数据
        h = int(size.find('height').text)#读取size标签中高度的数据
    
        for obj in root.iter('object'):
            cls = obj.find('name').text
            if cls not in classes :#or int(difficult) == 1:
                continue
            cls_id = classes.index(cls)
            xmlbox = obj.find('bndbox')  
            b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
            bb = convert((w,h), b)
            out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '
    ')
    View Code

         需要自行设置xml_path和txt_save_path

    从上面的代码可以看到,对于object的位置x_min,x_max,y_min,y_max,先求得其中心点坐标center_x,center_y以及位置框的长宽width_rect,height_rect,再将这四个值分别除以长宽以将数据归一化。

         2、*.data文件准备

         训练的时候必须的项目有“class”,“train”,“backup”。“names”最好也设置上,方便以后调用。

         “class”表示你要检测的类别个数,如检测类别为4则class=4
         “backup”表示训练过程中的缓存和保存的模型。训练过程中,会在该路径下生成一个后缀为.backup的文件,该文件每100个step将模型更新一遍,以防止训练忽然终端而没有保存模型。并且,训练保存的模型也会存在该路径下。默认情况下,每10000step还是多少会保存一个模型,命名为yolov3_迭代次数.weights,最终训练完成还会保存一个yolov3_final.weights。这些模型都会保存在backup路径下
         “names”为保存检测object名称的路径,names=plate.names
         “train”为你训练集的list路径,如train=data/trainlist.txt,trainlist.txt中保存了所有训练集图像的路径:

        /home/jim/yolov3/data/car/image/1101.jpg

        /home/jim/yolov3/data/car/image/1104.jpg

        /home/jim/yolov3/data/car/image/1134.jpg

        可通过如下命令生成文件:

            find image_path -name *.jpg > trainlist.txt     ::image_path为你数据集的路径

        3、*.cfg文件准备

    如果要调用yolo v3,可以直接使用cfg文件夹下的yolov3.cfg,但是需要做如下几个修改:
    首先,将最上方的

    # Testing
    batch=1
    subdivisions=1
    # Training
    # batch=64
    # subdivisions=16
    修改为
    
    # Testing
    #batch=1
    #subdivisions=1
    # Training
    batch=64
    subdivisions=16
    View Code

    其中batch表示batchsize,而subdivisions是为了解决想要大batchsize而显存又不够的情况,每次代码只读取batchsize/subdivisions 个图像,如图中设置为64/16=4,但是会将16次的结果也就是64张图的结果,作为一个batch来统一处理; 

    然后,根据自己检测的类别,将每个[yolo](共有三个[yolo]) 下方的classes修改为自己需要检测的类别,如果只检测一类则classes=1
    然后将每个[yolo] 上方的第一个filters的值进行修改,计算方式为(5+classes)*3,如果classes为1,则为18,修改前后的对比:

    [convolutional]
    size=1
    stride=1
    pad=1
    filters=255
    activation=linear
    
    [yolo]
    mask = 0,1,2
    anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
    classes=80
    num=9
    jitter=.3
    ignore_thresh = .5
    truth_thresh = 1
    random=1
    
    [convolutional]
    size=1
    stride=1
    pad=1
    filters=18
    activation=linear
    
    [yolo]
    mask = 0,1,2
    anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
    classes=1
    num=9
    jitter=.3
    ignore_thresh = .5
    truth_thresh = 1
    random=1
    View Code

    其中:random表示论文中提及的resize network来增强网络的适应性,如果显存足够,最好设置为1,如果显存不够,也可以将其设置为0,即不进行network resizing

       4、weights文件准备

          如果你使用的是作者提供的cfg模型结构,如yolov3,那么可以到官网去下载预训练模型来初始化模型参数,这样可以加快收敛。

          当然,你也可以不使用预训练模型进行训练

       5、开始训练

         如果使用预训练模型则使用如下命令

         ./darknet detector train data/detect.data data/yolov3.cfg data/yolov3.weight

         否则,使用如下命令:

          ./darknet detector train data/detect.data data/yolov3.cfg

         注:分类模型使用如下命令:

          ./darknet classifier train cfg/cifar.data cfg/cifar_small.cfg (xxx.weights)

    五、Darknet的检测

         检测使用如下命令:

          ./darknet detector test data/detect.data data/yolov3.cfg data/yolov3.weight

           其中./darknet为前面编译生成的darknet.exe文件,darknet.exe首先调用example文件夹下的darknet.c,该文件中的main函数需要预定义参数,detector即为预定义参数,如下代码:

           else if (0 == strcmp(argv[1], "detector")){ run_detector(argc, argv);}

      由‘detector’转而调用run_detector,run_detector存在于example文件夹下的detector.c中,再根据预定义参数,确定是调用检测函数,训练函数还是验证函数:

    if(0==strcmp(argv[2], "test")) test_detector(datacfg, cfg, weights, filename, thresh, hier_thresh, outfile, fullscreen);
    else if(0==strcmp(argv[2], "train")) train_detector(datacfg, cfg, weights, gpus, ngpus, clear);
    else if(0==strcmp(argv[2], "valid")) validate_detector(datacfg, cfg, weights, outfile);
    else if(0==strcmp(argv[2], "valid2")) validate_detector_flip(datacfg, cfg, weights, outfile);
    else if(0==strcmp(argv[2], "recall")) validate_detector_recall(cfg, weights);
    else if(0==strcmp(argv[2], "demo"))

       其中test表示检测,train表示训练,valid表示验证,recall表示测试其召回率,demo为调用摄像头的实时检测,命令最后的三个参数表示运行需要的文件,.data文件记录了模型检测的类别,类名文件等,如下:

    classes= 1
    train = /home/jim/yolov3/data/car/train.list
    names = data/plate/car.names
    backup = /home/jim/yolov3/data/car/models

    class表示检测类别,train为训练中需要用到的训练数据的列表,valid为验证集列表,names为检测类别的名称,backup为训练中用到的存放训练模型的路径

    .cfg文件定义了模型结构,而.weight文件为调用的模型权重文件。

  • 相关阅读:
    WHERE col1=val1 AND col2=val2;index exists on col1 and col2, the appropriate rows can be fetched directly
    MySQL 交集 实现方法
    MBProgressHUD的使用
    Xcode4 使用 Organizer 分析 Crash logs(转)
    SimpleXML 使用详细例子
    PHP的XML Parser(转)
    iPhone,iPhone4,iPad程序启动画面的总结 (转)
    Pop3得到的Email 信件格式介绍
    yii总结
    隐藏Tabbar的一些方法
  • 原文地址:https://www.cnblogs.com/jimchen1218/p/11834493.html
Copyright © 2020-2023  润新知