darkNet训练自己的YOLO模型

作者: 1037号森林里一段干木头 | 来源:发表于2020-10-26 11:21 被阅读0次

    简介:Darknet项目是github上的一个开源深度学习框架,用c语言编写,布置C/C++环境比较方便。

    1.图片数据标注

    labelme标注工具标注的文件是json格式的文件,在yolo检测的框架下需要txt格式的标注,但是没有关系,转换也很简单。
    没有labelme的话直接,pip install labelme即可。


    image.png

    (注:labelme默认是保存图片数据的,一般来说用不到,菜单-Save With Image Data取消即可)
    这里我标注了4类数据,分别用0 1 2 3表示,由于图片数据涉及到其他公司秘密不方便展示,所以随便找了个图片做标注示范。

    2. annotation格式转换

    json格式标签内容如下

    {
      "version": "4.5.6",
      "flags": {},
      "shapes": [
        {
          "label": "0",
          "points": [
            [
              1966.75,
              1436.375
            ],
            [
              2088.625,
              1567.625
            ]
          ],
          "group_id": null,
          "shape_type": "rectangle",
          "flags": {}
        },
        {
          "label": "1",
          "points": [
            [
              666.75,
              895.75
            ],
            [
              935.5,
              1186.375
            ]
          ],
          "group_id": null,
          "shape_type": "rectangle",
          "flags": {}
        },
      ],
      "imagePath": "..\\FOV_0000.bmp",
      "imageData": null,
      "imageHeight": 2984,
      "imageWidth": 4080
    }
    

    yolo的txt标签格式
    <class> <x_center> <y_center> <width> <height>
    由于图片可能有尺度缩放所以YOLO里边的位置用的是图片的百分比坐标
    python转换代码如下

    import json
    import os
    import cv2
    img_folder_path=r'F:\imagedata\FOV\FOV'
    folder_path=r"F:\imagedata\FOV\FOV\annotation"#标注数据的文件地址
    txt_folder_path = r"F:\imagedata\FOV\FOV\txt"
    
    
    def create_txt(img_name,json_d,img_path):
        src_img=cv2.imread(img_path)
        h,w = src_img.shape[:2]
        #txt文件名和图片名保持一致
        txt_name = img_name.split(".")[0]+".txt"
        txt_path = os.path.join(txt_folder_path,txt_name)
        print(txt_path)
        with open(txt_path,'a+') as f:
            for item in json_d["shapes"]:
                print(item['points'])
                print(item['label'])
                point=item['points']
                x_center = (point[0][0]+point[1][0])/2
                y_center = (point[0][1]+point[1][1])/2
                width = point[1][0]-point[0][0]
                hight = point[1][1]-point[0][1]
                print(x_center)
                f.write(" {} ".format(item['label']))
                f.write(" {} ".format(x_center/w))
                f.write(" {} ".format(y_center/h))
                f.write(" {} ".format(width/w))
                f.write(" {} ".format(hight/h))
                f.write(" \n")
                
    
    
    for jsonfile in os.listdir(folder_path):
        temp_path=os.path.join(folder_path,jsonfile)
        #如果是一个子目录就继续
        if os.path.isdir(temp_path):
            continue
        print("json_path:\t",temp_path)
        jsonfile_path=temp_path
    
        with open(jsonfile_path, "r", encoding='utf-8') as f:
            json_d = json.load(f)
            #读取图片名
            img_name=json_d['imagePath'].split("\\")[1]
            img_path=os.path.join(img_folder_path,img_name)
            print("img_path:\t",img_path)
            create_txt(img_name,json_d,img_path)
           
    

    生成的txt标签文件

     0  0.4969822303921569  0.5033512064343163  0.029871323529411766  0.043984584450402146  
     1  0.19635416666666666  0.3488815348525469  0.06587009803921569  0.09739443699731903  
     1  0.2717984068627451  0.3488815348525469  0.07123161764705882  0.09739443699731903  
     1  0.19673713235294119  0.24677446380697052  0.0666360294117647  0.09425268096514745  
     1  0.2714154411764706  0.2483453418230563  0.0628063725490196  0.09111092493297587  
    
    

    最后把图片和标签数据放到darknet\build\darknet\x64\data\obj目录下,标签和图片在同一个目录下,且标签名和图片名一样,如图


    image.png

    3. darknet cfg文件设置

    在darknet\build\darknet\x64\cfg目录下修改yolov4-tiny-obj.cfg文件(记得备份原文件),修改bath,width,height,max_batches(下面的steps= max_batches0.8,max_batches0.9),官网的要求width height需要能被32整除,max_batches=classes*2000.

    # Training
    batch=4
    subdivisions=4
    width=2048
    height=1024
    ............
    
    learning_rate=0.00261
    burn_in=1000
    max_batches = 8000
    policy=steps
    steps=6400,7200
    scales=.1,.1
    

    修改classes为你训练数据的种类数,有两处,另外一个很重要的参数每一个[yolo]层前面的filters=(种类数+5)3,有两处,例如如果有4类,则filters=(4+5)3=27,5类:filters=(5+5)*3=30

    [convolutional]
    size=1
    stride=1
    pad=1
    filters=27
    activation=linear
    
    [yolo]
    mask = 3,4,5
    anchors = 10,14,  23,27,  37,58,  81,82,  135,169,  344,319
    classes=4
    num=6
    ...........
    [convolutional]
    size=1
    stride=1
    pad=1
    filters=27
    activation=linear
    
    [yolo]
    mask = 0,1,2
    anchors = 10,14,  23,27,  37,58,  81,82,  135,169,  344,319
    classes=4
    num=6
    ............
    

    4.创建.data .name 文件

    在darknet\build\darknet\x64\data目录下创建FOV_obj.data文件(文件名随便取),写入内容

    classes= 4
    train  = data/train.txt
    valid  = data/test.txt
    names = data/FOV_obj.names
    backup = backup/
    

    创建FOV_obj.name文件写入以下内容

    0
    1
    2
    3
    
    

    创建train.txt文件写入你想要训练的图片

    data/obj/FOV_0000.jpg
    data/obj/FOV_0001.jpg
    data/obj/FOV_0002.jpg
    data/obj/FOV_0003.jpg
    data/obj/FOV_0004.jpg
    ..............
    

    创建test.txt文件写入

    data/obj/FOV_0065.jpg
    data/obj/FOV_0066.jpg
    data/obj/FOV_0067.jpg
    data/obj/FOV_0068.jpg
    .............
    
    

    python代码

    #train.txt
    txt_ = r"D:\mydoc\ML\yolo\darknet\build\darknet\x64\data\train.txt"
    with open(txt_,'a+') as f:
        for i in range(60):
            item = "data/obj/"+"FOV_{}.jpg".format(str(i).zfill(4))
            f.write(item)
            f.write("\n")
    
    #test.txt
    txt_ = r"D:\mydoc\ML\yolo\darknet\build\darknet\x64\data\test.txt"
    with open(txt_,'a+') as f:
        for i in range(60,69):
            item = "data/obj/"+"FOV_{}.jpg".format(str(i).zfill(4))
            f.write(item)
            f.write("\n")
    

    最后的文件如下


    image.png

    5. 下载yolo预训练模型

    https://github.com/AlexeyAB/darknet/releases/download/darknet_yolo_v4_pre/yolov4-tiny.conv.29
    放入darknet\build\darknet\x64目录下

    6.train

    打开cmd进入darknet.exe所在目录
    输入

    darknet.exe detector train data/FOV_obj.data cfg/yolov4-tiny-obj.cfg yolov4-tiny.conv.29 29
    
    image.png

    可以看到训练损失开始很大,在训练200-300个batch时下降到3点几,并在此处震荡,另外每训练1000个batch会保存一次模型。模型权值保存在darknet\build\darknet\x64\backup目录下,某次训练中断了,想要接着上一次的训练过程继续的话也很方便,输入:

    darknet.exe detector train data/FOV_obj.data cfg/yolov4-tiny-obj.cfg backup\yolov4-tiny-obj_last.weights
    
    image.png

    7.demo test

    使用刚刚训练的模型权重做测试

    darknet.exe detector test data/FOV_obj.data cfg/yolov4-tiny-obj.cfg backup\yolov4-tiny-obj_1000.weights
    
    image.png

    在Enter Image path:处填入图片路径(eg:data/test.jpg)

    data
    OK,至此基本训练流程走完,剩下的就是提升网络性能了。

    训练过程的一点总结

    • 在yolov4-tiny-obj.cfg配置中图片的高度和宽度应该能被32整除,用其他高宽也能训练,但是会出现比较大的震荡,test测试的时候找不到目标,或者是有一层的输入不匹配(图像输入0x0x0)。
    • 训练yolov4完整框架,用yolov4.conv.137预训练权重,图像尺寸大一点常常会导致GPU out of memory,解决方法是在.cfg文件中提高subdivisions=4(或者8、16、32、64),另外就是改输入的尺寸width height。参考https://www.ccoderun.ca/programming/2020-09-25_Darknet_FAQ/#cuda_out_of_memory
    • 网络会把尺寸*1.4,例如在.cfg文件中设置width=1024,height=768, image.png
    • yolov4完整版的配置和yolov4-tiny版配置差不多,就是改width,height,classes,yolo层前面卷积层的filters(classes,filters有三处需要改,因为它有三个yolo层)

    相关文章

      网友评论

        本文标题:darkNet训练自己的YOLO模型

        本文链接:https://www.haomeiwen.com/subject/vfzomktx.html