当前位置:   article > 正文

YOLOv7——目标检测数据集划分篇_yolo划分数据集

yolo划分数据集

法一:

1.准备VOC数据集

        将所有数据集图片放入JPEGImages文件夹中,所有的图片对应的xml文件放入Annotations中,ImageSets文件夹中创建Main文件夹,暂时Main文件夹为空。

文件夹结构 

datasets
     ————Annotations  # 存放图片对应的xml文件,与JPEGImages图片一一对应
     ————ImageSets
         ————Main    # 存放train.txt和val.txt文件
     ————JPEGImages   # 存放所有图片

2.数据集划分

在 VOCdevkit 目录下创建split.py,运行之后会在 Main 文件夹下生成三个个txt文件:

 train.txt、val.txt、test.txt

  1. # -*- coding: utf-8 -*-
  2. """
  3. Author:smile
  4. Date:2022/09/11 10:00
  5. 顺序:脚本A1
  6. 简介:分训练集、验证集和测试集,按照 8:1:1 的比例来分,训练集8,验证集1,测试集1
  7. """
  8. import os
  9. import random
  10. import argparse
  11. parser = argparse.ArgumentParser()
  12. # xml文件的地址,根据自己的数据进行修改 xml一般存放在Annotations下
  13. parser.add_argument('--xml_path', default='datasets/Annotations', type=str, help='input xml label path')
  14. # 数据集的划分,地址选择自己数据下的ImageSets/Main
  15. parser.add_argument('--txt_path', default='datasets/ImageSets/Main', type=str, help='output txt label path')
  16. opt = parser.parse_args()
  17. train_percent = 0.8 # 训练集所占比例
  18. val_percent = 0.1 # 验证集所占比例
  19. test_persent = 0.1 # 测试集所占比例
  20. xmlfilepath = opt.xml_path
  21. txtsavepath = opt.txt_path
  22. total_xml = os.listdir(xmlfilepath)
  23. if not os.path.exists(txtsavepath):
  24. os.makedirs(txtsavepath)
  25. num = len(total_xml)
  26. list = list(range(num))
  27. t_train = int(num * train_percent)
  28. t_val = int(num * val_percent)
  29. train = random.sample(list, t_train)
  30. num1 = len(train)
  31. for i in range(num1):
  32. list.remove(train[i])
  33. val_test = [i for i in list if not i in train]
  34. val = random.sample(val_test, t_val)
  35. num2 = len(val)
  36. for i in range(num2):
  37. list.remove(val[i])
  38. file_train = open(txtsavepath + '/train.txt', 'w')
  39. file_val = open(txtsavepath + '/val.txt', 'w')
  40. file_test = open(txtsavepath + '/test.txt', 'w')
  41. for i in train:
  42. name = total_xml[i][:-4] + '\n'
  43. file_train.write(name)
  44. for i in val:
  45. name = total_xml[i][:-4] + '\n'
  46. file_val.write(name)
  47. for i in list:
  48. name = total_xml[i][:-4] + '\n'
  49. file_test.write(name)
  50. file_train.close()
  51. file_val.close()
  52. file_test.close()

3. VOC转YOLO格式

        第2步只是把数据集划分了比例,想训练,还要进行这一步。在datasets目录下创建voc_label.py,点击运行,会在目录下生成新的labels文件夹,把数据集路径导入txt文件,将每个xml标注信息提取转换为了txt格式,每个图像对应一个txt文件。

  1. # -*- coding: utf-8 -*-
  2. import xml.etree.ElementTree as ET
  3. import os
  4. sets = ['train', 'val', 'test'] # 如果你的Main文件夹没有test.txt,就删掉'test'
  5. # classes = ["a", "b"] # 改成自己的类别,VOC数据集有以下20类别
  6. classes = ["pig", 'eat', 'stand', 'lie'] # class names
  7. abs_path = os.getcwd()
  8. def convert(size, box):
  9. dw = 1. / (size[0])
  10. dh = 1. / (size[1])
  11. x = (box[0] + box[1]) / 2.0 - 1
  12. y = (box[2] + box[3]) / 2.0 - 1
  13. w = box[1] - box[0]
  14. h = box[3] - box[2]
  15. x = x * dw
  16. w = w * dw
  17. y = y * dh
  18. h = h * dh
  19. return x, y, w, h
  20. def convert_annotation(image_id):
  21. in_file = open(abs_path + '/datasets/Annotations/%s.xml' % (image_id), encoding='UTF-8')
  22. out_file = open(abs_path + '/datasets/labels/%s.txt' % (image_id), 'w')
  23. tree = ET.parse(in_file)
  24. root = tree.getroot()
  25. size = root.find('size')
  26. w = int(size.find('width').text)
  27. h = int(size.find('height').text)
  28. for obj in root.iter('object'):
  29. difficult = obj.find('difficult').text
  30. # difficult = obj.find('Difficult').text
  31. cls = obj.find('name').text
  32. if cls not in classes or int(difficult) == 1:
  33. continue
  34. cls_id = classes.index(cls)
  35. xmlbox = obj.find('bndbox')
  36. b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
  37. float(xmlbox.find('ymax').text))
  38. b1, b2, b3, b4 = b
  39. # 标注越界修正
  40. if b2 > w:
  41. b2 = w
  42. if b4 > h:
  43. b4 = h
  44. b = (b1, b2, b3, b4)
  45. bb = convert((w, h), b)
  46. out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
  47. for image_set in sets:
  48. if not os.path.exists(abs_path + '/datasets/labels/'):
  49. os.makedirs(abs_path + '/datasets/labels/')
  50. image_ids = open(abs_path + '/datasets/ImageSets/Main/%s.txt' % (image_set)).read().strip().split()
  51. list_file = open(abs_path + '/datasets/%s.txt' % (image_set), 'w')
  52. for image_id in image_ids:
  53. list_file.write(abs_path + '/datasets/JPEGImages/%s.jpg\n' % (image_id)) # 要么自己补全路径,只写一半可能会报错
  54. convert_annotation(image_id)
  55. list_file.close()

运行之后,会在datasets目录下生成 labels文件夹和3个新的.txt文件

 其中,新生成的3个的train.txt、val.txt、test.txt,这正是后面训练需要用的文件。每个txt文件里面存放的图片的文件名全路径

4.训练准备

1.创建自己数据集的 yaml 文件

找到文件夹 data , 在data 文件夹中创建自己数据集的 Pig.yaml 文件
train  val   test :  三个txt的路径(注意冒号后要有一个空格)
nc : 自己数据集类别个数
names数据集类别名字

2.修改训练 yolov7 的 yaml 文件

在 cfg/training 文件夹中,选择想要使用的 yaml 文件,将文件中的 nc 改为自己数据集的类别数

 3. 修改datasets.py文件

 做完以上步骤,若直接开始训练,会报错:

解决方法:
找到  utils/dataset.py 文件,搜索框搜索 Define label,将下图红色线处内容修改为’JPEGImages’。原本yolov7 代码这里是’images’,但VOC是把图片保存在JPEGImages下的,所以需要修改方能正确读取图片。 

5. 开始训练

训练的时候 train 和 val 数据集都会使用到,验证集 test 在下一步使用

weights : 预训练权重位置
cfg上一部分修改的 yolov7.yaml 文件位置
data 上一部分修改的数据集 yaml 文件位置
hyp训练所需超参数位置,可以不用修改
epochs : 想要训练的轮数
batch-size : 步距,需要显存,过大可能报错

6.使用 test.py

当训练完之后想要使用测试集(test)进行测试的时候,找到  test.py

weights : 自己训练完之后生成的权重位置
data : 同训练时使用的一样(自己数据集的 yaml)
task : 改为 test

法二:

一、准备数据

 

 

二、划分数据集

先随便新建一些文件夹和文件,如下

 

  1. # 将图片和标注数据按比例切分为 训练集和测试集
  2. import shutil
  3. import random
  4. import os
  5. # 原始路径
  6. image_original_path = "图像文件夹路径"
  7. label_original_path = "标注结果的路径" // 该路径下不要有classes.txt
  8. cur_path = os.getcwd()
  9. # 训练集路径
  10. train_image_path = os.path.join(cur_path, "images/train/")
  11. train_label_path = os.path.join(cur_path, "labels/train/")
  12. # 验证集路径
  13. val_image_path = os.path.join(cur_path, "images/val/")
  14. val_label_path = os.path.join(cur_path, "labels/val/")
  15. # 测试集路径
  16. test_image_path = os.path.join(cur_path, "images/test/")
  17. test_label_path = os.path.join(cur_path, "labels/test/")
  18. # 训练集目录
  19. list_train = os.path.join(cur_path, "train.txt")
  20. list_val = os.path.join(cur_path, "val.txt")
  21. list_test = os.path.join(cur_path, "test.txt")
  22. train_percent = 0.8
  23. val_percent = 0.1
  24. test_percent = 0.1
  25. def del_file(path):
  26. for i in os.listdir(path):
  27. file_data = path + "\\" + i
  28. os.remove(file_data)
  29. def mkdir():
  30. if not os.path.exists(train_image_path):
  31. os.makedirs(train_image_path)
  32. else:
  33. del_file(train_image_path)
  34. if not os.path.exists(train_label_path):
  35. os.makedirs(train_label_path)
  36. else:
  37. del_file(train_label_path)
  38. if not os.path.exists(val_image_path):
  39. os.makedirs(val_image_path)
  40. else:
  41. del_file(val_image_path)
  42. if not os.path.exists(val_label_path):
  43. os.makedirs(val_label_path)
  44. else:
  45. del_file(val_label_path)
  46. if not os.path.exists(test_image_path):
  47. os.makedirs(test_image_path)
  48. else:
  49. del_file(test_image_path)
  50. if not os.path.exists(test_label_path):
  51. os.makedirs(test_label_path)
  52. else:
  53. del_file(test_label_path)
  54. def clearfile():
  55. if os.path.exists(list_train):
  56. os.remove(list_train)
  57. if os.path.exists(list_val):
  58. os.remove(list_val)
  59. if os.path.exists(list_test):
  60. os.remove(list_test)
  61. def main():
  62. mkdir()
  63. clearfile()
  64. file_train = open(list_train, 'w')
  65. file_val = open(list_val, 'w')
  66. file_test = open(list_test, 'w')
  67. total_txt = os.listdir(label_original_path)
  68. num_txt = len(total_txt)
  69. list_all_txt = range(num_txt)
  70. num_train = int(num_txt * train_percent)
  71. num_val = int(num_txt * val_percent)
  72. num_test = num_txt - num_train - num_val
  73. train = random.sample(list_all_txt, num_train)
  74. # train从list_all_txt取出num_train个元素
  75. # 所以list_all_txt列表只剩下了这些元素
  76. val_test = [i for i in list_all_txt if not i in train]
  77. # 再从val_test取出num_val个元素,val_test剩下的元素就是test
  78. val = random.sample(val_test, num_val)
  79. print("训练集数目:{}, 验证集数目:{}, 测试集数目:{}".format(len(train), len(val), len(val_test) - len(val)))
  80. for i in list_all_txt:
  81. name = total_txt[i][:-4]
  82. srcImage = image_original_path + name + '.jpg'
  83. srcLabel = label_original_path + name + ".txt"
  84. if i in train:
  85. dst_train_Image = train_image_path + name + '.jpg'
  86. dst_train_Label = train_label_path + name + '.txt'
  87. shutil.copyfile(srcImage, dst_train_Image)
  88. shutil.copyfile(srcLabel, dst_train_Label)
  89. file_train.write(dst_train_Image + '\n')
  90. elif i in val:
  91. dst_val_Image = val_image_path + name + '.jpg'
  92. dst_val_Label = val_label_path + name + '.txt'
  93. shutil.copyfile(srcImage, dst_val_Image)
  94. shutil.copyfile(srcLabel, dst_val_Label)
  95. file_val.write(dst_val_Image + '\n')
  96. else:
  97. dst_test_Image = test_image_path + name + '.jpg'
  98. dst_test_Label = test_label_path + name + '.txt'
  99. shutil.copyfile(srcImage, dst_test_Image)
  100. shutil.copyfile(srcLabel, dst_test_Label)
  101. file_test.write(dst_test_Image + '\n')
  102. file_train.close()
  103. file_val.close()
  104. file_test.close()
  105. if __name__ == "__main__":
  106. main()

划分完成之后的数据集应该是这样

        images文件夹下
        有三个文件夹,每个文件夹中都有对应的图像

 

 

        labels文件夹下
        有三个文件夹,每个文件夹中都有对应的标注数据

        

         

 

        train.txt文件
        保存了训练图像的路径

 

数据集制作完成。

参考文章:

YOLOv7目标检测数据集划分_yolo数据集划分_I'mFAN的博客-CSDN博客

【Yolov7】制作自己的数据集_yolo数据集制作_不知道在干嘛每天的博客-CSDN博客

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

闽ICP备14008679号