当前位置:   article > 正文

YOLOV8数据集制作,X-Anylabeling标注数据集,以及模型训练_x-anylabeling 数据转出 yolo

x-anylabeling 数据转出 yolo

1.X-Anylabeling简介与项目地址


         X-AnyLabeling 是一款全新的交互式自动标注工具,其基于AnyLabeling进行构建和二次开发,在此基础上扩展并支持了许多的模型和功能,并借助Segment AnythingYOLO等主流模型提供强大的 AI 支持。无须任何复杂配置,下载即用,支持自定义模型,极大提升用户标注效率!相较于LabelImg 和 Labelme 效率更高。

https://github.com/CVHub520/X-AnyLabeling

使用教程:https://zhuanlan.zhihu.com/p/636164570

2.X-Anylabeling所标注的数据集处理

2.1标签文件说明

标签文件的格式是json, 会存放在图片文件里。

注意:不要使用脚本直接将json文件转化成txt文件。

2.2 将json文件转xml文件

在这段代码中,需要根据实际情况更改路径。Annotations文件夹会自动创建。如果你的图像数据集不是jpg,也需要修改代码。

  1. import os
  2. import xml.dom
  3. import numpy as np
  4. import codecs
  5. import json
  6. import glob
  7. import cv2
  8. import shutil
  9. # 1.标签路径
  10. labelme_path = r"D:/SoftWareSpace/stu_py/stu_py/img/goodApple" # 原始json、bmp标注数据路径,需要更换成自己的数据集名称
  11. saved_path = r"D:/SoftWareSpace/stu_py/stu_py/img/Annotations" # 保存路径
  12. if not os.path.exists(saved_path):
  13. os.makedirs(saved_path)
  14. # 2.获取待处理文件
  15. files = glob.glob("%s/*.json" % (labelme_path))
  16. # 3.读取标注信息并写入 xml
  17. for json_filename in files:
  18. json_file = json.load(open(json_filename, "r", encoding="utf-8"))
  19. i = 0
  20. # 图像名字,若图像格式不是bmp,需要修改此处
  21. img_name = json_filename.replace(".json", ".jpg")
  22. height, width, channels = cv2.imread(img_name).shape
  23. # xml名字
  24. xmlName = os.path.join(saved_path, json_filename.split("\\")[-1].replace(".json", ".xml"))
  25. with codecs.open(xmlName, "w", "utf-8") as xml:
  26. print(2)
  27. xml.write('<annotation>\n')
  28. xml.write('\t<folder>' + 'jpg' + '</folder>\n')
  29. xml.write('\t<filename>' + img_name + '</filename>\n')
  30. # -------------------------------------------------
  31. xml.write('\t<source>\n')
  32. xml.write('\t\t<database>hulan</database>\n')
  33. # --------------------------------------------------
  34. xml.write('\t</source>\n')
  35. # -----------------------------------------------------------
  36. xml.write('\t<size>\n')
  37. xml.write('\t\t<width>' + str(width) + '</width>\n')
  38. xml.write('\t\t<height>' + str(height) + '</height>\n')
  39. xml.write('\t\t<depth>' + str(channels) + '</depth>\n')
  40. # ------------------------------------------------
  41. xml.write('\t</size>\n')
  42. xml.write('\t\t<segmented>0</segmented>\n')
  43. # 节点判断
  44. for multi in json_file["shapes"]:
  45. points = np.array(multi["points"])
  46. xmin = min(points[:, 0])
  47. xmax = max(points[:, 0])
  48. ymin = min(points[:, 1])
  49. ymax = max(points[:, 1])
  50. label = multi["label"]
  51. if xmax <= xmin:
  52. pass
  53. elif ymax <= ymin:
  54. pass
  55. else:
  56. xml.write('\t<object>\n')
  57. xml.write('\t\t<name>' + json_file["shapes"][i]["label"] + '</name>\n')
  58. xml.write('\t\t<pose>Unspecified</pose>\n')
  59. xml.write('\t\t<truncated>0</truncated>\n')
  60. xml.write('\t\t<difficult>0</difficult>\n')
  61. xml.write('\t\t<bndbox>\n')
  62. xml.write('\t\t\t<xmin>' + str(xmin) + '</xmin>\n')
  63. xml.write('\t\t\t<ymin>' + str(ymin) + '</ymin>\n')
  64. xml.write('\t\t\t<xmax>' + str(xmax) + '</xmax>\n')
  65. xml.write('\t\t\t<ymax>' + str(ymax) + '</ymax>\n')
  66. xml.write('\t\t</bndbox>\n')
  67. xml.write('\t</object>\n')
  68. print(json_filename, xmin, ymin, xmax, ymax, label)
  69. i = i + 1
  70. xml.write('</annotation>')

2.3获取xml文件中的labels

注意:路径需要根据实际路径进行更改。

  1. import xml.dom.minidom as xmldom
  2. import os
  3. # voc数据集获取所有标签的所有类别数"
  4. annotation_path = "D:/SoftWareSpace/stu_py/stu_py/img/Annotation/"#需要根据实际路径更改
  5. annotation_names = [os.path.join(annotation_path, i) for i in os.listdir(annotation_path)]
  6. labels = list()
  7. for names in annotation_names:
  8. xmlfilepath = names
  9. domobj = xmldom.parse(xmlfilepath)
  10. # 得到元素对象
  11. elementobj = domobj.documentElement
  12. # 获得子标签
  13. subElementObj = elementobj.getElementsByTagName("object")
  14. for s in subElementObj:
  15. label = s.getElementsByTagName("name")[0].firstChild.data
  16. # print(label)
  17. if label not in labels:
  18. labels.append(label)
  19. print(labels)

2.4xml文件转化为txt文件

注意:这里存放txt文件的文件夹需要自己创建,classes需要修改成2.3代码所获取的labels。

  1. import xml.etree.ElementTree as ET
  2. import os
  3. classes = ['apple'] # 类别
  4. CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
  5. def convert(size, box):
  6. dw = 1. / size[0]
  7. dh = 1. / size[1]
  8. x = (box[0] + box[1]) / 2.0 # (x_min + x_max) / 2.0
  9. y = (box[2] + box[3]) / 2.0 # (y_min + y_max) / 2.0
  10. w = box[1] - box[0] # x_max - x_min
  11. h = box[3] - box[2] # y_max - y_min
  12. x = x * dw
  13. w = w * dw
  14. y = y * dh
  15. h = h * dh
  16. return (x, y, w, h)
  17. def convert_annotation(image_id):
  18. in_file = open('D:/SoftWareSpace/stu_py/stu_py/img/Annotation\%s.xml' % (image_id), encoding='UTF-8')
  19. out_file = open('D:/SoftWareSpace/stu_py/stu_py/img/labels\%s.txt' % (image_id), 'w') # 生成txt格式文件
  20. tree = ET.parse(in_file)
  21. root = tree.getroot()
  22. size = root.find('size')
  23. w = int(size.find('width').text)
  24. h = int(size.find('height').text)
  25. for obj in root.iter('object'):
  26. cls = obj.find('name').text
  27. # print(cls)
  28. if cls not in classes:
  29. continue
  30. cls_id = classes.index(cls)
  31. xmlbox = obj.find('bndbox')
  32. b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text),
  33. float(xmlbox.find('ymax').text))
  34. bb = convert((w, h), b)
  35. out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
  36. xml_path = os.path.join(CURRENT_DIR, 'D:/SoftWareSpace/stu_py/stu_py/img/Annotation')
  37. # xml list
  38. img_xmls = os.listdir(xml_path)
  39. for img_xml in img_xmls:
  40. label_name = img_xml.split('.')[0]
  41. print(label_name)
  42. convert_annotation(label_name)

2.5分配数据集

这段代码会把数据集拆开,拆成train,val,test

  1. 新建文件夹 datasets/data/images
    然后将图片和标签全部放到这个文件夹下。

  2. 在datasets下新建一个分配数据集数据的脚本文件train.py

  1. import os
  2. import random
  3. import shutil
  4. def split_dataset(data_dir,train_val_test_dir, train_ratio, val_ratio, test_ratio):
  5. # 创建目标文件夹
  6. train_dir = os.path.join(train_val_test_dir, 'train')
  7. val_dir = os.path.join(train_val_test_dir, 'val')
  8. test_dir = os.path.join(train_val_test_dir, 'test')
  9. os.makedirs(train_dir, exist_ok=True)
  10. os.makedirs(val_dir, exist_ok=True)
  11. os.makedirs(test_dir, exist_ok=True)
  12. # 获取数据集中的所有文件
  13. files = os.listdir(data_dir)
  14. # 过滤掉非图片文件
  15. image_files = [f for f in files if f.endswith('.jpg') or f.endswith('.png')]
  16. # 随机打乱文件列表
  17. random.shuffle(image_files)
  18. # 计算切分数据集的索引
  19. num_files = len(image_files)
  20. num_train = int(num_files * train_ratio)
  21. num_val = int(num_files * val_ratio)
  22. num_test = num_files - num_train - num_val
  23. # 分离训练集
  24. train_files = image_files[:num_train]
  25. for file in train_files:
  26. src_image_path = os.path.join(data_dir, file)
  27. src_label_path = os.path.join(data_dir, file.replace('.jpg', '.txt').replace('.png', '.txt'))
  28. dst_image_path = os.path.join(train_dir, file)
  29. dst_label_path = os.path.join(train_dir, file.replace('.jpg', '.txt').replace('.png', '.txt'))
  30. shutil.copy(src_image_path, dst_image_path)
  31. shutil.copy(src_label_path, dst_label_path)
  32. # 分离验证集
  33. val_files = image_files[num_train:num_train+num_val]
  34. for file in val_files:
  35. src_image_path = os.path.join(data_dir, file)
  36. src_label_path = os.path.join(data_dir, file.replace('.jpg', '.txt').replace('.png', '.txt'))
  37. dst_image_path = os.path.join(val_dir, file)
  38. dst_label_path = os.path.join(val_dir, file.replace('.jpg', '.txt').replace('.png', '.txt'))
  39. shutil.copy(src_image_path, dst_image_path)
  40. shutil.copy(src_label_path, dst_label_path)
  41. # 分离测试集
  42. test_files = image_files[num_train+num_val:]
  43. for file in test_files:
  44. src_image_path = os.path.join(data_dir, file)
  45. src_label_path = os.path.join(data_dir, file.replace('.jpg', '.txt').replace('.png', '.txt'))
  46. dst_image_path = os.path.join(test_dir, file)
  47. dst_label_path = os.path.join(test_dir, file.replace('.jpg', '.txt').replace('.png', '.txt'))
  48. shutil.copy(src_image_path, dst_image_path)
  49. shutil.copy(src_label_path, dst_label_path)
  50. print("数据集分离完成!")
  51. print(f"训练集数量:{len(train_files)}")
  52. print(f"验证集数量:{len(val_files)}")
  53. print(f"测试集数量:{len(test_files)}")
  54. def move_files(data_dir):
  55. # 创建目标文件夹
  56. images_dir = os.path.join(data_dir, 'images')
  57. labels_dir = os.path.join(data_dir, 'labels')
  58. os.makedirs(images_dir, exist_ok=True)
  59. os.makedirs(labels_dir, exist_ok=True)
  60. # 获取数据集中的所有文件
  61. files = os.listdir(data_dir)
  62. # 移动PNG文件到images文件夹
  63. png_files = [f for f in files if f.endswith('.jpg')]
  64. for file in png_files:
  65. src_path = os.path.join(data_dir, file)
  66. dst_path = os.path.join(images_dir, file)
  67. shutil.move(src_path, dst_path)
  68. # 移动TXT文件到labels文件夹
  69. txt_files = [f for f in files if f.endswith('.txt')]
  70. for file in txt_files:
  71. src_path = os.path.join(data_dir, file)
  72. dst_path = os.path.join(labels_dir, file)
  73. shutil.move(src_path, dst_path)
  74. print(f"{data_dir}文件移动完成!")
  75. print(f"总共移动了 {len(png_files)} 个PNG文件到images文件夹")
  76. print(f"总共移动了 {len(txt_files)} 个TXT文件到labels文件夹")
  77. # 设置数据集路径和切分比例
  78. data_dir = './data/images' # 图片和标签路径
  79. train_val_test_dir= './data' # 目标文件夹
  80. train_ratio = 0.7 # 训练集比例
  81. val_ratio = 0.2 # 验证集比例
  82. test_ratio = 0.1 # 测试集比例
  83. # 调用函数分离数据集
  84. split_dataset(data_dir, train_val_test_dir,train_ratio, val_ratio, test_ratio)
  85. # 调用函数移动文件
  86. move_files(os.path.join(train_val_test_dir, 'train'))
  87. move_files(os.path.join(train_val_test_dir, 'val'))
  88. move_files(os.path.join(train_val_test_dir, 'test'))

3.在datasets同级目录下新建一个mydata.yaml文件

  1. train: ./data/train/images
  2. val: ./data/val/images
  3. test: ./data/test/images
  4. # 类别数
  5. nc: 2
  6. # 类别名称
  7. names: ["goodapple","badapple"]

3.训练数据集

3.1训练

在终端执行以下命令

yolo task=detect mode=train model=yolov8.yaml data=mydata.yaml epochs=1000 batch=16 device=0

data:需要改成mydata.yaml文件的路径,

epochs:指的是训练轮数,可以根据实际修改

device:0指的是GPU,如果没有GPU,也可以将0改成cpu

3.2测试命令

yolo detect predict model=yolov8n.pt source='badimg'  

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

闽ICP备14008679号