darknet训练yolov4模型

darknet训练yolov4模型

安装darknet环境安装部署

这里以windows环境为例,其他环境看官网说明

源码下载

  1. 下载源码
git clone https://github.com/AlexeyAB/darknet.git
  1. 下载完成后用cmake 打开

在这里插入图片描述
Configure >> Generate >> Open Project
然后在vs 上编译出 darknet.exe
在这里插入图片描述
在输出文件夹中得到daeknet.exe
在这里插入图片描述

准备数据集打标签(以识别篮球为例)

这里用labelImg工具打标签

pip install labelImg
  1. 新建一个文件夹
    在这里插入图片描述
  2. 进入文件夹下在新建两个文件夹cfg和data
    用于存放配置文件已经训练数据集
    在这里插入图片描述
  3. 进入data文件夹下新建如下如下文件夹和文件
    用于存放图片 、图片索引文件 以及标签文件
    在这里插入图片描述
    打开config.data,输入以下内容
    这里只识别篮球一个种类 所以classes=1,有多少种类classes就设为多少
    在这里插入图片描述
    打开config.names,输入种类名称
    在这里插入图片描述
  4. 将图片移到前面新建的那个images文件夹中用labelImg工具打开文件夹

在这里插入图片描述
选择高级模式Advancedmode 和 自动保存 auto save mode
格式选择yolo格式 ,保存位置选择图片文件夹
在这里插入图片描述
然后对所有的图片开始打标签在这里插入图片描述

  1. 删除图片文件夹里面的classes.txt ,然后将标签文件全部拷贝到labels文件夹里面(注意这里是拷贝过去,images文件夹下存放图片和标签,labels文件夹下存放标签)

  2. 将darknet文件夹下的cfg文件夹下面的yolov4_custom.cfg文件拷贝到前面新建的cfg文件夹下并修改以下几个地方

#batch和sub是结合使用的,例如这儿的batch=64,sub=16表示训练的过程中将一次性加载64张图片进内存,然后分16次完成前向传播,
	#意思是每次4张,前向传播的循环过程中累加loss求平均,待64张图片都完成前向传播后,再一次性后传更新参数
#调参经验:sub一般设置16,不能太大或太小,且为8的倍数;
	#batch的值可以根据显存占用情况动态调整,一次性加减sub大小即可,通常情况下batch越大越好,
	#还需注意一点,在测试的时候batch和sub都设置为1,避免发生神秘错误!
batch=64
subdivisions=16

width=416		#将网络的size改为416*416 (需要是32的倍数)
height=416

max_batches = 2000  #训练次数(由于我这里图片比较少,所以先设为2000次,一般设置为classes*2000 ,不要小于训练图片数,也不要小于classes * 2000)

steps=1600,1800 (一般设置为max_batches的80%,90%)

修改所有的yolo层上面的filters=3*(classes + 5),以及yolo层的classes种类数
在这里插入图片描述

分离数据集与测试集

  1. 写个脚本Process.py将数据集和测试集分离出来并将索引记录子txt文件中(这里在网上随便找了一个,也可以自己写一个)
    在这里插入图片描述
import os
import random
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
import math

trainval_percent = 0.2  		#测试集比例
train_percent = 0.8				#训练集比例
picSuffix='.jpg'				#图片格式

sets = ['train', 'test','val']
labelfilepath = 'data/labels'
txtsavepath = 'data/ImageSets'
total_label = os.listdir(labelfilepath)
 
def StepOne():
    num = len(total_label)
    list = range(num)
    tv = int(num * trainval_percent)
    tr = int(tv * train_percent)
    #tv = int(num * trainval_percent)
    #tr = int(tv * train_percent)
    trainval = random.sample(list, tv)
    train = random.sample(trainval, tr)

    ftrainval = open('data/ImageSets/trainval.txt', 'w')
    ftest = open('data/ImageSets/test.txt', 'w')
    ftrain = open('data/ImageSets/train.txt', 'w')
    fval = open('data/ImageSets/val.txt', 'w')

    for i in list:
        name = total_label[i][:-4] + '\n'
        if i in trainval:
            ftrainval.write(name)
            if i in train:
                ftest.write(name)
            else:
                fval.write(name)
        else:
            ftrain.write(name)

    ftrainval.close()
    ftrain.close()
    fval.close()
    ftest.close()

def StepTow():
    for image_set in sets:
        if not os.path.exists('data/labels/'):
            os.makedirs('data/labels/')
        image_ids = open('data/ImageSets/%s.txt' % (image_set)).read().strip().split()
        list_file = open('data/%s.txt' % (image_set), 'w')
        for image_id in image_ids:
            list_file.write('data/images/%s%s\n' % (image_id,picSuffix))
        list_file.close()

if __name__ == "__main__":
    StepOne()
    StepTow()
    
  1. 运行脚本,在data文件夹下以及data/Imagesets文件夹下生成下面这些文件
python Process.py

在这里插入图片描述
在这里插入图片描述

下载预训练模型

data同级目录下新建weights文件夹,并下载预训练模型存放其中
下载预训练模型
在这里插入图片描述

重定anchors

anchors其实就是在训练之前人为设定的先验框,网络输出结果的框就是在anchors的基础上进行调整的。所以说先验框设定的好坏对于模型的输出效果影响还是挺大的。在yolo中一般设定一个物体的先验框的个数一般是9个

  1. 从darknet的编译目录下找darknet.exe这个可执行文件,我们这里是在Release下,将其拷贝到我们这个工程路径下(data同级路径下)

在这里插入图片描述
在这里插入图片描述

  1. 从darknet目录下拷贝pthreadVC2.dll文件到这里
    在这里插入图片描述
  2. 运行命令算出anchors
darknet.exe detector calc_anchors data/config.data -num_of_clusters 9 -width 416 -height 416

成功后会在当前路径下生成anchors.txt文件
将其中的内容拷贝下来,修改cfg/yolov4_custom.cfg文件的anchors (下面三个地方)
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  1. 新建文件夹backup(在data同级路径下)

训练模型

执行命令:

darknet.exe detector train data/config.data  cfg/yolov4-custom.cfg  weights/yolov4.conv.137 -map

如果出现memory error 则将配置文件cfg/yolov4-custom.cfg的batch调小再试

正在训练:
在这里插入图片描述
训练完成:
在这里插入图片描述

生成的文件在backup文件夹中

测试效果

写一个简单的测试程序测试一下

#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/opencv.hpp>
#include <string>
#include <vector>
#include <sys/time.h>
#include "yolo_v2_class.hpp"

double const lbk_get_time_ms(){
    
    
    double t;
    struct timeval tv;
    gettimeofday(&tv, NULL);
    t =  tv.tv_sec*1000. + tv.tv_usec/1000.;
    return t;
}


int main(){
    
    
    std::string cfg_file =      "model/yolov4-custom.cfg";
    std::string weights_file =  "model/yolov4-custom_final.weights";
    std::string filename =      "testImage/img0.jpg";
    
    Detector detector(cfg_file, weights_file);

    cv::Mat mat_img = cv::imread(filename);
    auto det_image = detector.mat_to_image_resize(mat_img);

    double t0 = lbk_get_time_ms();
    std::vector<bbox_t> result_vec = detector.detect_resized(*det_image, mat_img.size().width, mat_img.size().height);

    for (auto &i : result_vec) {
    
    
        std::cout << "obj_id = " << i.obj_id << ",  x = " << i.x << ", y = " << i.y << ", w = " << i.w << ", h = " << i.h << std::setprecision(3) << ", prob = " << i.prob << std::endl;
    }
    
    float min_prop = 0.6f; //可信度过滤
    for (auto &i : result_vec) {
    
    
        if(i.prob > min_prop){
    
    
            cv::rectangle (mat_img, cv::Rect(i.x,i.y,i.w,i.h), cv::Scalar(0, 0, 255), 2, 8, 0);
            if(i.obj_id == 0){
    
    
                cv::putText(mat_img, "basketball", cv::Point(i.x,i.y), cv::FONT_HERSHEY_COMPLEX, 2, cv::Scalar(0, 255, 255), 2, 8, 0);
            }else{
    
    
                cv::putText(mat_img, std::to_string(i.obj_id - 1), cv::Point(i.x,i.y), cv::FONT_HERSHEY_COMPLEX, 2, cv::Scalar(0, 255, 255), 2, 8, 0);
            }
            
        }
        
    }

    cv::imwrite("testImage/res.jpg",mat_img);
    std::cout << "time :" << (lbk_get_time_ms() - t0) << std::endl;
}

在这里插入图片描述
位置有点歪,不过鉴于咱们训练集只有几十张图片,这样的效果就还不错了!

猜你喜欢

转载自blog.csdn.net/liang_baikai/article/details/125934702