当前位置:   article > 正文

yolov5训练自己的数据集并实现自定义目标检测、及遇到的问题(详解)2022.3.10_yolov5目标检测需要解决的关键问题

yolov5目标检测需要解决的关键问题


一、yolov5包下载、以及环境配置

  1. YOLOv5的github下载连接:点击下载yolov5——解压到本地桌面或其他不包含中文的目录下,文件结构如下:在这里插入图片描述

  2. 然后是环境配置,这里需要安装有Anaconda,进入Anaconda Prompt,为yolov5创建一个虚拟环境并激活(防止环境污染),当然不建也可以:创建名为yolo5-master且python版本3.7的虚拟环境:conda create -n yolo5-master python=3.7
    激活虚拟环境

  3. 最后就可在虚拟环境下安装依赖包了,根据yolov5项目中的requirements.txt文件,其中罗列出了项目所需要的各种依赖包及版本,进入requirement.txt所在的目录,直接输入pip install -r requirements.txt安装即可:>由于我已经装过了所以显示:Requirement already satisfied

    由于我已经装过了所以显示:Requirement already satisfied

4.安装好了,也可以输入: pip list 命令查看安装结果


二、数据集的准备

1 用标注工具打标签

  1. 首先,在yolov5目录中的yolov5-master/data路径下创建medData(自定义)文件夹,用来存放自己的图片数据及标签,即medData文件夹下创建2个文件夹分别为:在这里插入图片描述

    images:用来存放你的图片数据( .jpg)
    xml: 用来存放图片对应的标签数据( .xml)

  2. 打开images中的图片,可用 labelme、labelImg、roLabelImg等工具对其打标签并存于上述xml文件夹中,三者都可以打标签,但又有些区别:labelme生成的标签是 .json格式的,后续还要转化为.xml格式;lebelImg是 .xml格式的(推荐用这个);而roLabelImg在打标签时矩形框可以旋转,具体可以自个儿查查。现在,用labelImg打完标签后的数据如下:
    原图像如下
    在这里插入图片描述
    对应的标签如下在这里插入图片描述

  3. 为了便于训练,把上述数据进行划分为三个部分:train.txt集、test.txt集、val.txt集,都存放于data/medData/dataSets/Main路径下;当然不是手动划分,通过创建如下makeTxt.py,自动划分:
    makeTxt.py如下

    import os
    import random
    
    trainval_percent = 0.1
    train_percent = 0.9
    xmlfilepath = 'data/medData/xml'
    txtsavepath = 'data/medData/dataSets/Main'
    total_xml = os.listdir(xmlfilepath)
    
    num = len(total_xml)
    list = range(num)
    tv = int(num * trainval_percent)
    tr = int(tv * train_percent)
    trainval = random.sample(list, tv)
    train = random.sample(trainval, tr)
    
    ftrainval = open('data/medData/dataSets/Main/trainval.txt', 'w')
    ftest = open('data/medData/dataSets/Main/test.txt', 'w')
    ftrain = open('data/medData/dataSets/Main/train.txt', 'w')
    fval = open('data/medData/dataSets/Main/val.txt', 'w')
    
    for i in list:
        name = total_xml[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()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    三个.txt文本文件如下所示:在这里插入图片描述
    三个.txt文本文件内容都形如下所示:(trainval.txt不知道干嘛用的)在这里插入图片描述
    实际上就是将图片分为三个部分,并分别把图片名字保存于文件中。
    至此,标注工作已完成,但这里得到的标签数据集是voc_2007格式的(.xml),还需要转换为coco格式的才能用于yolov5上

2. 数据集格式转换

  1. 首先,制作yolov5的标签labels:由于上面lebelImg制作的xml标签是voc的标签格式,yolo不能直接利用,所以需要创建脚本文件 voc_label.py, 把上述部分的数据转换成yolov5能够利用的数据格式,同时,将图片的路径导入三个txt文件中:
    voc_label.py:
    import xml.etree.ElementTree as ET
    import os
    from os import getcwd
    
    sets = ['train', 'val', 'test']
    classes = ["target"]  # 改成自己的类别
    abs_path = os.getcwd()
    # abs_path = abs_path.replace("\\", "/")
    print(abs_path)
    
    
    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(image_id):
        in_file = open('data/medData/xml/%s.xml' % (image_id), encoding='UTF-8')
        out_file = open('data/medData/labels/%s.txt' % (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
            # 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))
            b1, b2, b3, b4 = b
            # 标注越界修正
            if b2 > w:
                b2 = w
            if b4 > h:
                b4 = h
            b = (b1, b2, b3, b4)
            bb = convert((w, h), b)
            out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
    
    
    wd = getcwd()
    for image_set in sets:
        if not os.path.exists('data/medData/labels/'):
            os.makedirs('data/medData/labels/')
        image_ids = open('data/medData/dataSets/Main/%s.txt' % (image_set)).read().strip().split()
        list_file = open('data/medData/%s.txt' % (image_set), 'w')
        for image_id in image_ids:
            list_file.write(abs_path + '\data\medData\images\%s.jpg\n' % (image_id))
            convert_annotation(image_id)
        list_file.close()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    运行该脚本文件后,会生成如下 labels文件夹、和三个包含数据集的txt文件:
    在这里插入图片描述
    labels文件夹内容:
    在这里插入图片描述
    其中的每一个txt文件对应一张图像的标签,txt中每一行对应图像中的一个目标信息(class, x_center, y_center, width, height),txt中的内容为:
    在这里插入图片描述
    而相应的train,txt,test.txt,val.txt 都大致为:(相比之前voc_2007的加了图像路径和后缀)
    在这里插入图片描述

    注意确保这里的路径正确,否则在训练时可能会报错

3. 小结

总结:做了这么多步骤,其实最终有用的文件就只有:images、labels文件、以及三个数据集的划分文件txt;其他的文件都没啥用(voc_2007的那些),或者说都是为了生成这几个的中间产物;
在这里插入图片描述
数据集准备的整个流程图如下所示,最终得到的目标文件:图像images、对应yolo的标签labels、以及三个划分集:
在这里插入图片描述


三、yolov5的参数配置

1.数据集文件配置

在yolov5里面数据集是通过.yaml文件访问的,因此在yolov5/medData新建 target.yaml文件,里面写入信息:上述最终得到的tain.txt,test.txt,val.txt、目标的类别数 nc 、以及类别名字 names,(类别数及名字根据需求自己改),具体如下:在这里插入图片描述

2.yolov5模型文件配置

在models路径下找到yolov5s.yaml文件,复制一份并重命名为yolo5s-target.yaml,把里面的类别数 nc 改为与上面对应,我这里为1:
在这里插入图片描述

3.预训练模型下载

1.预训练模型去这个页面下载:进入下载yolov5s.pt; 下载好后放入 yolov5-master/weights/ 下即可
可选择的模型从小到大分别有:n—s—m—l—x,根据任务规模选择就行,一般小任务s就足够了
在这里插入图片描述
好了,所有的准备工作都做好了,下面即可开始训练。


四、开始训练

1.终端输入

python train.py --img 416 --batch 16 --epoch 100 --data data/medData/target.yaml --cfg models/yolov5s-target.yaml --weights weights/yolov5s.pt

  • 1
  • 2

在这里插入图片描述
训练100个epoch后共花费0.633 hours,得到的结果如下:在这里插入图片描述
得到的模型文件best.pt,保存在runs/train/exp9/wights/目录下,以后的检测就可以直接利用该模型进行操作。


2.训练时遇到的各种问题

原本想输入上述命令即可开始愉快的训练了,但期间还是遇到了花式的错误!!!
问题1
**找不到指定模块**
根据上述出错的路径可以看出是torchvision包出了问题,准备卸载了重新安装torchvision,甚至把torch也重装了,后来各种查找资料得出是torch, torchvision版本不对应,然后重新装版本对应的torch和torchvision,这和问题2类似。

问题2
在这里插入图片描述
错误显示:无效的CUDA;猜想多半是GPU的使用问题,所以先检测Cuda是否可用,发现果然返回False。参考连接在这里插入图片描述
所以去安装对应版本的 torch+cuda+torchvision ,这里一定要对应,不然可能会报问题1的错误,具体操作,可以把原来的torch,torchvision卸载了,输入如下所示命令安装即可:

pip install torch===1.7.0+cu110 torchvision===0.8.1+cu110 torchaudio===0.7.0 -f https://download.pytorch.org/whl/torch_stable.html
  • 1

在这里插入图片描述
安装完成后,再次检验cuda是否可用在这里插入图片描述
问题3
在这里插入图片描述
错误显示:BrokenPipeError: [Errno 32] Broken pipe,百度说是windows下的dataloader多线程问题,只需打开utils/dataset.py,然后 ctrl+f 搜索 dataloader 并将 num_workers = 0 即可。
在这里插入图片描述


五、验证并实现检测

首先选择数据集以外的新的图像进行检测验证,图片放于yolov5/data/images目录下,然后输入如下命令进行检测:

python detect.py --weights weights/best.pt --img-size 416
  • 1

虽然训练时只用了150+图像、epoch也只有100,但这里效果还可以:
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/338013
推荐阅读
相关标签
  

闽ICP备14008679号