darknet-自分のyolov 3モデルを訓練する

17852 ワード

Yolo v 3の使い方


参照先@zhaonan
目次
  • Yolo v 3の使い方
  • darknet
  • をインストール
  • 訓練Pascal VOCフォーマットのデータ
  • cfgファイルのvocを変更する.data
  • VOCを修正する.names
  • プリトレーニングボリューム重み
  • をダウンロード
  • cfg/yolov 3-vocを修正する.cfg

  • 自分のモデルを訓練する
  • 試験Yoloモデル
  • テスト1枚画像:
  • 一括テストピクチャ
  • 予測結果
  • を生成する.
  • サードパーティ製computeを採用mAP
  • プレミアムステップ
  • Reference


  • darknetのインストール

  • ダウンロードライブラリファイル
  • git clone https://github.com/pjreddie/darknet
    cd darknet
    
  • Makefile
  • を修正
    GPU=1  #0 1
    CUDNN=1  #0 1
    OPENCV=0  #0 1
    OPENMP=0
    DEBUG=0
    
  • コンパイル
  • make
    
  • ダウンロード事前トレーニングモデル
  • wget https://pjreddie.com/media/files/yolov3.weights
    
  • 予備訓練モデルによる簡単な試験
  • ./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg
    

    Pascal VOC形式のデータのトレーニング

  • は、darknetがxmlファイルを必要としないため、Labelsを生成する.txtファイル(フォーマット:)
  • voc_でlabel.py(./scripts)cat voc_label.py共修正四箇所
    import xml.etree.ElementTree as ET
    import pickle
    import os
    from os import listdir, getcwd
    from os.path import join
    sets=[('2007', 'train'), ('2007', 'val'), ('2007', 'test')]  #         
    classes = ["head", "eye", "nose"]     #        
    
    def convert(size, box):
        dw = 1./(size[0])
        dh = 1./(size[1])
        x = (box[0] + box[1])/2.0 - 1
        y = (box[2] + box[3])/2.0 - 1
        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(year, image_id):
        in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id))  #           
        out_file = open('VOCdevkit/VOC%s/labels/%s.txt'%(year, image_id), 'w')
        tree=ET.parse(in_file)
        root = tree.getroot()
        size = root.find('size')
        w = int(size.find('width').text)
        h = int(size.find('height').text)
        for obj in root.iter('object'):
            difficult = obj.find('difficult').text
            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]) + '
    ') wd = getcwd() for year, image_set in sets: if not os.path.exists('VOCdevkit/VOC%s/labels/'%(year)): os.makedirs('VOCdevkit/VOC%s/labels/'%(year)) image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split() list_file = open('%s_%s.txt'%(year, image_set), 'w') for image_id in image_ids: list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg
    '%(wd, year, image_id)) convert_annotation(year, image_id) list_file.close() os.system("cat 2007_train.txt 2007_val.txt > train.txt") #
    wget https://pjreddie.com/media/files/voc_label.py
    python voc_label.py
    
    VOCdevkit/VOC2007/labels/:
    learner@learner-pc:~/darknet/scripts$ ls
    2007_test.txt #0   dice_label.sh        imagenet_label.sh  VOCdevkit_original
    2007_train.txt #1  gen_tactic.sh        train.txt #3        voc_label.py
    2007_val.txt #2 get_coco_dataset.sh  VOCdevkit
    

    このときdarknetにはtxtファイルが必要で、すべての画像が含まれています.
    cat 2007_train.txt 2007_val.txt 2012_*.txt > train.txt
    

    cfgファイルのvocを変更する.data

    classes= 3    #         
    train  = /home/learner/darknet/data/voc/train.txt   #         or /home/learner/darknet/scripts/2007_test.txt
    valid  = /home/learner/darknet/data/voc/2007_test.txt   #         or /home/learner/darknet/scripts/2007_test.txt
    names = /home/learner/darknet/data/voc.names  #   voc.names
    backup = /home/learner/darknet/backup   #        ,            
    

    VOCを修正する.names

    head  #         ,    
    eye
    nose
    

    事前トレーニングボリュームウェイトのダウンロード

    wget https://pjreddie.com/media/files/darknet53.conv.74
    

    cfg/yolov 3-vocを修正する.cfg

    [net]
    # Testing
     batch=64
     subdivisions=32   #       =batch/subvisions,    GPU      ,        
    # Training
    # batch=64
    # subdivisions=16
    width=416
    height=416
    channels=3
    momentum=0.9
    decay=0.0005
    angle=0
    saturation = 1.5
    exposure = 1.5
    hue=.1
    
    learning_rate=0.001
    burn_in=1000
    max_batches = 50200  #    
    policy=steps
    steps=40000,45000  #       
    scales=.1,.1
    
    
    
    [convolutional]
    batch_normalize=1
    filters=32
    size=3
    stride=1
    pad=1
    activation=leaky
    
    .....
    
    [convolutional]
    size=1
    stride=1
    pad=1
    filters=24   #filters = 3 * ( classes + 5 )   here,filters=3*(3+5)
    activation=linear
    
    [yolo]
    mask = 6,7,8
    anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
    classes=3    #         
    num=9
    jitter=.3
    ignore_thresh = .5
    truth_thresh = 1
    random=1
    
    [route]
    layers = -4
    
    [convolutional]
    batch_normalize=1
    filters=256
    size=1
    stride=1
    pad=1
    activation=leaky
    
    [upsample]
    stride=2
    
    [route]
    layers = -1, 61
    
    
    
    [convolutional]
    batch_normalize=1
    filters=256
    size=1
    stride=1
    pad=1
    activation=leaky
    
    [convolutional]
    batch_normalize=1
    size=3
    stride=1
    pad=1
    filters=512
    activation=leaky
    
    [convolutional]
    batch_normalize=1
    filters=256
    size=1
    stride=1
    pad=1
    activation=leaky
    
    [convolutional]
    batch_normalize=1
    size=3
    stride=1
    pad=1
    filters=512
    activation=leaky
    
    [convolutional]
    batch_normalize=1
    filters=256
    size=1
    stride=1
    pad=1
    activation=leaky
    
    [convolutional]
    batch_normalize=1
    size=3
    stride=1
    pad=1
    filters=512
    activation=leaky
    
    [convolutional]
    size=1
    stride=1
    pad=1
    filters=24    #filters = 3 * ( classes + 5 )   here,filters=3*(3+5)
    activation=linear
    
    [yolo]
    mask = 3,4,5
    anchors = 10,13,  16,30,  33,23,  30,61,  62,45,  59,119,  116,90,  156,198,  373,326
    classes=3  #         
    num=9
    jitter=.3
    ignore_thresh = .5
    truth_thresh = 1
    random=1
    
    [route]
    layers = -4
    
    [convolutional]
    batch_normalize=1
    filters=128
    size=1
    stride=1
    pad=1
    activation=leaky
    
    [upsample]
    stride=2
    
    [route]
    layers = -1, 36
    
    
    
    [convolutional]
    batch_normalize=1
    filters=128
    size=1
    stride=1
    pad=1
    activation=leaky
    
    [convolutional]
    batch_normalize=1
    size=3
    stride=1
    pad=1
    filters=256
    activation=leaky
    
    [convolutional]
    batch_normalize=1
    filters=128
    size=1
    stride=1
    pad=1
    activation=leaky
    
    [convolutional]
    batch_normalize=1
    size=3
    stride=1
    pad=1
    filters=256
    activation=leaky
    
    [convolutional]
    batch_normalize=1
    filters=128
    size=1
    stride=1
    pad=1
    activation=leaky
    
    [convolutional]
    batch_normalize=1
    size=3
    stride=1
    pad=1
    filters=256
    activation=leaky
    
    [convolutional]
    size=1
    stride=1
    pad=1
    filters=24    #filters = 3 * ( classes + 5 )   here,filters=3*(3+5)
    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=3   #         
    num=9
    jitter=.3
    ignore_thresh = .5
    truth_thresh = 1
    random=1
    

    自分のモデルを訓練する


    1単GPUトレーニング:./darknet -i detector train
    ./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74
    

    2 GPUトレーニング、フォーマット0,1,2,3:./darknet detector train -gpus
    ./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74 -gpus 0,1,2,3
    

    Yoloモデルのテスト


    1枚の画像をテストします。

  • 単枚の画像をテストして、コンパイルする必要がある時OpenCVのサポートがあります:./darknet detector test # opencv
  • ファイルのbatchsubdivisionsの2つは1でなければなりません.
  • のテストでは、-threshおよび-hierのオプションで対応するパラメータを指定することもできます.
  • ./darknet detector test cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_20000.weights Eminem.jpg

  • 一括テスト画像

  • yolov3-voc.cfg(cfg )ファイルのbatchsubdivisionsの2つは1でなければなりません.
  • はdetectorにあります.cにヘッダファイルを追加する:
    #include   /* Many POSIX functions (but not all, by a large margin) */
    #include    /* open(), creat() - and fcntl() */
    

  • *GetFilename(char*p)関数
    #include "darknet.h"
    #include   //       
    #include
    #include
    #include  //       
    static int coco_ids[] = {1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23,24,25,27,28,31,32,33,34,35,36,37,38,39,40,41,42,43,44,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,67,70,72,73,74,75,76,77,78,79,80,81,82,84,85,86,87,88,89,90};
     
    char *GetFilename(char *p)
    { 
        static char name[30]={""};
        char *q = strrchr(p,'/') + 1;
        strncpy(name,q,20);
        return name;
    }
    
  • を前に追加
  • detectorを次のコードで置き換える.cファイル(exampleフォルダ下)のvoid test_detector関数(自分のパスに変更する3箇所注意)
  • void test_detector(char *datacfg, char *cfgfile, char *weightfile, char *filename, float thresh, float hier_thresh, char *outfile, int fullscreen)
    {
        list *options = read_data_cfg(datacfg);
        char *name_list = option_find_str(options, "names", "data/names.list");
        char **names = get_labels(name_list);
     
        image **alphabet = load_alphabet();
        network *net = load_network(cfgfile, weightfile, 0);
        set_batch_network(net, 1);
        srand(2222222);
        double time;
        char buff[256];
        char *input = buff;
        float nms=.45;
        int i=0;
        while(1){
            if(filename){
                strncpy(input, filename, 256);
                image im = load_image_color(input,0,0);
                image sized = letterbox_image(im, net->w, net->h);
            //image sized = resize_image(im, net->w, net->h);
            //image sized2 = resize_max(im, net->w);
            //image sized = crop_image(sized2, -((net->w - sized2.w)/2), -((net->h - sized2.h)/2), net->w, net->h);
            //resize_network(net, sized.w, sized.h);
                layer l = net->layers[net->n-1];
     
     
                float *X = sized.data;
                time=what_time_is_it_now();
                network_predict(net, X);
                printf("%s: Predicted in %f seconds.
    ", input, what_time_is_it_now()-time); int nboxes = 0; detection *dets = get_network_boxes(net, im.w, im.h, thresh, hier_thresh, 0, 1, &nboxes); //printf("%d
    ", nboxes); //if (nms) do_nms_obj(boxes, probs, l.w*l.h*l.n, l.classes, nms); if (nms) do_nms_sort(dets, nboxes, l.classes, nms); draw_detections(im, dets, nboxes, thresh, names, alphabet, l.classes); free_detections(dets, nboxes); if(outfile) { save_image(im, outfile); } else{ save_image(im, "predictions"); #ifdef OPENCV cvNamedWindow("predictions", CV_WINDOW_NORMAL); if(fullscreen){ cvSetWindowProperty("predictions", CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN); } show_image(im, "predictions",0); cvWaitKey(0); cvDestroyAllWindows(); #endif } free_image(im); free_image(sized); if (filename) break; } else { printf("Enter Image Path: "); fflush(stdout); input = fgets(input, 256, stdin); if(!input) return; strtok(input, "
    "); list *plist = get_paths(input); char **paths = (char **)list_to_array(plist); printf("Start Testing!
    "); int m = plist->size; if(access("/home/learner/darknet/data/outv3tiny_dpj",0)==-1)//"/home/learner/darknet/data" { if (mkdir("/home/learner/darknet/data/outv3tiny_dpj",0777))//"/home/learner/darknet/data" { printf("creat file bag failed!!!"); } } for(i = 0; i < m; ++i){ char *path = paths[i]; image im = load_image_color(path,0,0); image sized = letterbox_image(im, net->w, net->h); //image sized = resize_image(im, net->w, net->h); //image sized2 = resize_max(im, net->w); //image sized = crop_image(sized2, -((net->w - sized2.w)/2), -((net->h - sized2.h)/2), net->w, net->h); //resize_network(net, sized.w, sized.h); layer l = net->layers[net->n-1]; float *X = sized.data; time=what_time_is_it_now(); network_predict(net, X); printf("Try Very Hard:"); printf("%s: Predicted in %f seconds.
    ", path, what_time_is_it_now()-time); int nboxes = 0; detection *dets = get_network_boxes(net, im.w, im.h, thresh, hier_thresh, 0, 1, &nboxes); //printf("%d
    ", nboxes); //if (nms) do_nms_obj(boxes, probs, l.w*l.h*l.n, l.classes, nms); if (nms) do_nms_sort(dets, nboxes, l.classes, nms); draw_detections(im, dets, nboxes, thresh, names, alphabet, l.classes); free_detections(dets, nboxes); if(outfile){ save_image(im, outfile); } else{ char b[2048]; sprintf(b,"/home/learner/darknet/data/outv3tiny_dpj/%s",GetFilename(path));//"/home/leaner/darknet/data" save_image(im, b); printf("save %s successfully!
    ",GetFilename(path)); /* #ifdef OPENCV //cvNamedWindow("predictions", CV_WINDOW_NORMAL); if(fullscreen){ cvSetWindowProperty("predictions", CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN); } //show_image(im, "predictions"); //cvWaitKey(0); //cvDestroyAllWindows(); #endif*/ } free_image(im); free_image(sized); if (filename) break; } } } }
  • 再コンパイル
  • make clean
    make
    
  • ロットテスト
  • を開始
    ./darknet detector test cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_20000.weights
    
  • Image Pathを入力(すべてのテストファイルのパス、voc.dataのvalidの後ろのパスをコピーできます):
  • /home/learner/darknet/data/voc/2007_test.txt #     
    
  • の結果は、./data/outフォルダの下に
  • 保存されます.

    予測結果の生成


    予測結果の生成
  • ./darknet detector valid
  • yolov3-voc.cfg(cfgフォルダの下) batch subdivisionsの2つは1でなければなりません.
  • の結果、resultsで指定されたディレクトリの下にで始まるいくつかのファイルが生成され、resultsを指定していない場合、デフォルトは/resultsである.
  • 実行文は、端末が使用のみを返す場合、./results/comp4_det_test_[类名].txtにテスト結果
  • を保存
    ./darknet detector valid cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_20000.weights
    

    サードパーティ製compute_を採用mAP


    サードパーティ製ライブラリのダウンロード:
    git clone https://github.com/LianjiLi/yolo-compute-map.git
    

    以下の変更を行います.
  • darknet/examples/detectorを変更します.c中validate_detector()
    char *valid_images = option_find_str(options, "valid", "./data/2007_test.txt");//           
    
    if(!outfile) outfile = "comp4_det_test_";
            fps = calloc(classes, sizeof(FILE *));
            for(j = 0; j < classes; ++j){
                snprintf(buff, 1024, "%s/%s.txt", prefix, names[j]);//  outfile       %s
                fps[j] = fopen(buff, "w");
    
  • 再コンパイル
    make clean
    make
    
  • valid
    darknet      ./darknet detector valid cfg/voc.data cfg/yolov3-tiny.cfg backup/yolov3-tiny_164000.weights(         )
    
  • を実行
  • このフォルダの下でpython compute_mAP.py
  • を実行する.
  • 説明:compute_mAP.pyのtest.txtファイルの内容はファイル名のみ、絶対パスなし、接尾辞なし
  • 高度なステップアップ


    darknetの浅いフィーチャーの可視化は以下を参照してください.https://www.cnblogs.com/pprp/p/10146355.html
    AlexyAB大神がまとめた最適化の経験を参照してください.https://www.cnblogs.com/pprp/p/10204480.html
    Darknetの分類方法については、以下を参照してください.https://www.cnblogs.com/pprp/p/10342335.html
    Darknet lossビジュアル化ソフトウェアは以下を参照してください.https://www.cnblogs.com/pprp/p/10248436.html
    YOLOネットワーク構造の変更方法:https://pprp.github.io/2018/09/20/tricks.html
    YOLO詳細改善まとめ:https://pprp.github.io/2018/06/20/yolo.html
    ps:以上はすべて自分の科学研究の過程の中で内容を総括して、系統が足りないかもしれません、伝言の討論を歓迎します

    Reference


    YOLOv 3目標検出まとめ
    公式サイト
    構想整理自@zhaonan
    転載は作者を明記してください.問題があれば伝言を残してください.