当前位置:   article > 正文

YOLOv8-Detect训练自己的数据集_yolo detect yaml

yolo detect yaml

目录

0、引言

1、环境准备

2、数据集准备

2.1、创建数据集存放的文件夹

2.2、准备用于YOLOv8-Detect训练的txt

2.2.1 COCO数据集json文件转为xml

2.2.2 将多个xml整合到一个大的txt文件

2.2.3 将大的txt分解成多个小txt,txt以图片名字命名

2.2.4 将txt中对应的路径的图片复制到images/train

3、创建配置文件

3.1、设置官方配置文件:default.yaml,可自行修改。

3.2、设置data.yaml

3.3、设置yolov8s.yaml

4、进行训练

5、验证模型

6、总结


0、引言

本文是使用YOLOv8-Detect训练自己的数据集,数据集包含COCO数据集的人猫狗数据以及自己制作的人猫狗数据集,类别为0:person、1:cat、2:dog三类,大家可根据自己的数据集类别进行调整。

1、环境准备

可以参考这篇博客:深度学习环境搭建-CSDN博客

本文环境:

  • Windows10
  • python:3.10
  • cuda:11.6
  • pytorch:1.12.0
  • torchvision:0.13.0

2、数据集准备

2.1、创建数据集存放的文件夹

  1. mydata
  2. ______images
  3. ____________train
  4. _________________001.jpg
  5. ____________val
  6. _________________002.jpg
  7. ______labels
  8. ____________train
  9. _________________001.txt
  10. ____________val
  11. _________________002.txt

本人的数据都存放在mydata文件夹中(自定义命名)

目录结构如下:images存放训练集和验证集图片,labels存放训练集和验证集txt

2.2、准备用于YOLOv8-Detect训练的txt

2.2.1 COCO数据集json文件转为xml

从官网下载CoCo数据集的json文件

  1. import argparse, json
  2. import cytoolz
  3. from lxml import etree, objectify
  4. import os, re
  5. def instance2xml_base(anno):
  6. E = objectify.ElementMaker(annotate=False)
  7. anno_tree = E.annotation(
  8. E.folder('VOC2014_instance/{}'.format(anno['category_id'])),
  9. E.filename(anno['file_name']),
  10. E.source(
  11. E.database('MS COCO 2014'),
  12. E.annotation('MS COCO 2014'),
  13. E.image('Flickr'),
  14. E.url(anno['coco_url'])
  15. ),
  16. E.size(
  17. E.width(anno['width']),
  18. E.height(anno['height']),
  19. E.depth(3)
  20. ),
  21. E.segmented(0),
  22. )
  23. return anno_tree
  24. def instance2xml_bbox(anno, bbox_type='xyxy'):
  25. """bbox_type: xyxy (xmin, ymin, xmax, ymax); xywh (xmin, ymin, width, height)"""
  26. assert bbox_type in ['xyxy', 'xywh']
  27. if bbox_type == 'xyxy':
  28. xmin, ymin, w, h = anno['bbox']
  29. xmax = xmin+w
  30. ymax = ymin+h
  31. else:
  32. xmin, ymin, xmax, ymax = anno['bbox']
  33. E = objectify.ElementMaker(annotate=False)
  34. anno_tree = E.object(
  35. E.name(anno['category_id']),
  36. E.bndbox(
  37. E.xmin(xmin),
  38. E.ymin(ymin),
  39. E.xmax(xmax),
  40. E.ymax(ymax)
  41. ),
  42. E.difficult(anno['iscrowd'])
  43. )
  44. return anno_tree
  45. def parse_instance(content, outdir):
  46. # print('11111',content)
  47. categories = {d['id']: d['name'] for d in content['categories']}
  48. # merge images and annotations: id in images vs image_id in annotations
  49. merged_info_list = list(map(cytoolz.merge, cytoolz.join('id', content['images'], 'image_id', content['annotations'])))
  50. # print('111111111111',merged_info_list)
  51. # convert category id to name
  52. for instance in merged_info_list:
  53. instance['category_id'] = categories[instance['category_id']]
  54. # group by filename to pool all bbox in same file
  55. for name, groups in cytoolz.groupby('file_name', merged_info_list).items():
  56. anno_tree = instance2xml_base(groups[0])
  57. # if one file have multiple different objects, save it in each category sub-directory
  58. filenames = []
  59. # print(groups)
  60. for group in groups:
  61. filenames.append(os.path.join(outdir, re.sub(" ", "_", group['category_id']), os.path.splitext(name)[0] + ".xml"))
  62. anno_tree.append(instance2xml_bbox(group, bbox_type='xyxy'))
  63. for filename in filenames:
  64. etree.ElementTree(anno_tree).write(filename, pretty_print=True)
  65. print("Formating instance xml file {} done!".format(name))
  66. def main(args):
  67. if not os.path.exists(args.output_dir):
  68. os.makedirs(args.output_dir)
  69. content = json.load(open(args.anno_file, 'r'))
  70. if args.type == 'instance':
  71. # make subdirectories
  72. sub_dirs = [re.sub(" ", "_", cate['name']) for cate in content['categories']]
  73. for sub_dir in sub_dirs:
  74. sub_dir = os.path.join(args.output_dir, str(sub_dir))
  75. if not os.path.exists(sub_dir):
  76. os.makedirs(sub_dir)
  77. parse_instance(content, args.output_dir)
  78. if __name__ == "__main__":
  79. parser = argparse.ArgumentParser()
  80. parser.add_argument("--anno_file", help="annotation file for object instance/keypoint", default=r'D:\CoCoData\annotations_14_17\instances_train2017.json')
  81. parser.add_argument("--type", type=str, default='instance', help="object instance or keypoint", choices=['instance', 'keypoint'])
  82. parser.add_argument("--output_dir", help="output directory for voc annotation xml file", default=r'D:\CoCoData\CoCoXml')
  83. args = parser.parse_args()
  84. main(args)

修改文件存放的路径和保存xml文件的路径。

运行后得到80个文件夹,分别为80类的xml文件:

再将需要类别的xml文件整合,得到训练集和验证集xml

2.2.2 将多个xml整合到一个大的txt文件
  1. import os
  2. import random
  3. import xml.etree.ElementTree as ET
  4. import glob
  5. classes = ['person', 'cat', 'dog']
  6. def convert(size, box):
  7. dw = 1. / size[0]
  8. dh = 1. / size[1]
  9. x = (box[0] + box[2]) / 2.0
  10. y = (box[1] + box[3]) / 2.0
  11. w = min(size[0],box[2] - box[0])
  12. h = min(size[1],box[3] - box[1])
  13. # print(x,y,w,h)
  14. x = x * dw
  15. w = w * dw
  16. y = y * dh
  17. h = h * dh
  18. return (x, y, w, h)
  19. def convert_annotation(xml, list_file):
  20. in_file = open(os.path.join(xml), encoding='utf-8')
  21. tree = ET.parse(in_file)
  22. root = tree.getroot()
  23. xmlsize = root.find('size')
  24. w = int(xmlsize.find('width').text)
  25. h = int(xmlsize.find('height').text)
  26. # print(w,h)
  27. for obj in root.iter('object'):
  28. difficult = 0
  29. if obj.find('difficult') != None:
  30. difficult = obj.find('difficult').text
  31. cls = obj.find('name').text
  32. if cls not in classes or int(difficult) == 1:
  33. print(cls, "------------------------------------\n")
  34. continue
  35. cls_id = classes.index(cls)
  36. print(cls, cls_id)
  37. xmlbox = obj.find('bndbox')
  38. x0 = float(xmlbox.find('xmin').text)
  39. y0 = float(xmlbox.find('ymin').text)
  40. x1 = float(xmlbox.find('xmax').text)
  41. y1 = float(xmlbox.find('ymax').text)
  42. xmin = min(x0, x1)
  43. ymin = min(y0, y1)
  44. xmax = max(x0, x1)
  45. ymax = max(y0, y1)
  46. # b = (int(xmin), int(ymin), int(xmax), int(ymax))
  47. b = (float(xmin), float(ymin), float(xmax), float(ymax))
  48. # print(b)
  49. bb = convert((w, h), b)
  50. # print(bb)
  51. list_file.write(" "+str(cls_id) +"," + ",".join([str(a) for a in bb]))
  52. if __name__ == "__main__":
  53. random.seed(0)
  54. # 图片路径
  55. cocoImgPath = r'D:\Yolov8\Yolov8_dataset\selfXml\err04'
  56. # Xml路径
  57. cocoXmlPath = r'D:\Yolov8\Yolov8_dataset\selfXml\err04'
  58. #txt保存路径
  59. txtsavepath = r'D:\Yolov8\ultralytics-main\datasets\mydata\selfv8txt'
  60. fileWriteTxt = txtsavepath + '\\'+ cocoImgPath.split('\\')[-1] + '_v8.txt'
  61. xmls = glob.glob(os.path.join(cocoXmlPath, '*.xml'))
  62. list_file = open(fileWriteTxt, 'w', encoding='utf-8')
  63. for xml in xmls:
  64. img = xml.replace(cocoXmlPath, cocoImgPath).replace('.xml', '.jpg')
  65. if not os.path.exists(img):
  66. print(img, ' is not exit')
  67. continue
  68. list_file.write(img)
  69. convert_annotation(xml, list_file)
  70. list_file.write('\n')
  71. list_file.close()

运行以上代码可得到txt,内容如下:图片路径,xmin,ymin,xmax,ymax,classID

2.2.3 将大的txt分解成多个小txt,txt以图片名字命名
  1. import glob
  2. import os
  3. #批量处理,txt存放文件夹
  4. txtpathdir = r'D:\Yolov8\ultralytics-main\datasets\mydata\selfv8txt\err04_v8.txt'
  5. #保存txt路径
  6. savetxtpath = r'D:\Yolov8\ultralytics-main\datasets\mydata\labels\train'
  7. file = open(txtpathdir,'r',encoding='utf-8')
  8. lines = file.readlines()
  9. for line in lines:
  10. line = line.split('\n')[0]
  11. # print(line)
  12. imgdir = line.split(' ')[0]
  13. bboxinfo = line.split(' ')[1:]
  14. # print('imgdir',imgdir)
  15. savetxtdir = os.path.join(savetxtpath,imgdir.split('\\')[-1].replace('.jpg','.txt'))
  16. file = open(savetxtdir, 'w', encoding='utf-8')
  17. # print(savetxtdir)
  18. for i in range(len(bboxinfo)):
  19. # print(bboxinfo[i])
  20. info = bboxinfo[i].split(',')
  21. # print(info)
  22. info1 = ' '.join(info)
  23. print(info1)
  24. file.write(info1+'\n')

运行以上代码,即得到需要的txt

2.2.4 将txt中对应的路径的图片复制到images/train

(根据自己需求,因为我的图片类别多,存放位置也不同,所以需要找到对应的图片用于训练)

  1. import glob
  2. import os
  3. import shutil
  4. txtpathdir = r'D:\Yolov8\ultralytics-main\datasets\mydata\cocotxt\train2017_v8.txt'
  5. saveimgpath = r'D:\Yolov8\ultralytics-main\datasets\mydata\images\train'
  6. file = open(txtpathdir,'r',encoding='utf-8')
  7. lines = file.readlines()
  8. for line in lines:
  9. line = line.split('\n')[0]
  10. imgdir = line.split(' ')[0]
  11. print('imgdir',imgdir)
  12. saveimgdir = os.path.join(saveimgpath,imgdir.split('\\')[-1])
  13. print(saveimgdir)
  14. shutil.copy(imgdir,saveimgdir)

上述步骤可根据实际情况进行调整,这样就得到了可用于训练的数据,train中存放训练数据,val存放验证集。

 

labels中txt存放的数据格式如下(与官方一致):

 分别代表:类别、框的中心点xy坐标以及框的宽高(进行了归一化处理)

3、创建配置文件

3.1、设置官方配置文件:default.yaml,可自行修改。

所有参数参见:https://docs.ultralytics.com/usage/cfg/

3.2、设置data.yaml

根据自己的数据集位置进行修改和配置。

  1. path: D:\Yolov8\ultralytics-main\datasets\mydata # dataset root dir
  2. train: images/train # train images (relative to 'path') 118287 images
  3. val: images/val # val images (relative to 'path') 5000 images
  4. #test: test-dev2017.txt # 20288 of 40670 images, submit to https://competitions.codalab.org/competitions/20794
  5. # Classes
  6. names:
  7. 0: person
  8. 1: cat
  9. 2: dog
  10. nc: 3

3.3、设置yolov8s.yaml

根据自己想使用的权重进行选择,我这里采用的是yolov8s.pt进行训练,类别为3。

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