当前位置:   article > 正文

目标检测——0.4 构建自己的数据集(YOLO)_目标检测制作数据集包含哪些步骤

目标检测制作数据集包含哪些步骤

目录

1. 前置工作

2. 准备工作

2.1 数据集目录

2.1 数据集划分(split_train_val.py)

3. VOC格式转YOLO格式(xml_to_yolo.py)

4. YOLO格式转VOC格式

4.1 txt标注文件批量转换成xml标注文件

4.2 将所有训练集、测试集数据名称(去掉后缀)分别写入到train.txt、test.txt

4.3 复制图片

4.4 上述程序合并到一起


1. 前置工作

2. 准备工作

2.1 数据集目录

  • 准备VOCdevkit文件夹及子文件夹
  1. 各个子文件夹——见下1
  2. VOCdevkit-VOC2012-Annotations——存放标注后的xml文件
  3. VOCdevkit-VOC2012-JEPGImages——存放标注后的图像文件
  • 准备data文件夹及子文件
  1. data-pascal_voc_classes.json——
    json文件中的内容为想要识别的各个种类
    具体文件夹目录见下1、具体内容见下2
  1. ├── data
  2. │ ├── pascal_voc_classes.json # 用以保存识别类别信息
  3. │ │
  4. ├── VOCdevkit
  5. │ ├── VOC2012
  6. │ │ ├── Annotations # 用以存放所有xml标签文件
  7. │ │ ├── JPEGImages # 用以存放所有标注好的图片
  8. │ │ ├── ImageSets
  9. │ │ │ ├── Main # 用以存放所有txt文件(注意此时该文件夹是空的)
  1. {
  2. "dec_1_pass": 1,
  3. "dec_1_fail": 2,
  4. "dec_2_pass": 3,
  5. "dec_2_fail": 4
  6. }

2.1 数据集划分(split_train_val.py)

  • 根据2.1准备好的数据集,制作train.txt与val.txt
  • 生成的train.txt与val.txt和当前python文件在同一目录下,之后要挪到2.1中VOCdevkit-VOC2012-ImageSets-Main
  • 要设置的参数有两个
  1. files_path——指定xml标签文件路径
  2. val_rate——指定验证集占数据集的比例
  1. """
  2. 1.针对xml文件(即pascal vocannotations里的文件)运行后生成train.txt与val.txt
  3. 2.生成的train.txt与val.txt存放当前目录下,之后要转存到指定文件夹(VOCdevkit-VOC2012-ImageSets-Main)
  4. 3.使用设置——
  5. 该文件要设定的地方有两处
  6. (1)files_path——指定xml文件路径;如 files_path = "./VOCdevkit/VOC2012/Annotations"
  7. (2)val_rate——指定验证集比例,如 val_rate = 0.3 为30%为验证集
  8. """
  9. import os
  10. import random
  11. def main():
  12. random.seed(0) # 1.设置随机种子,保证随机结果可复现
  13. files_path = "./VOCdevkit/VOC2012/Annotations" # 2.给定文件路径
  14. assert os.path.exists(files_path), "path: '{}' does not exist.".format(files_path)
  15. val_rate = 0.3 # 3.给定验证集比例,为30%
  16. files_name = sorted([file.split(".")[0] for file in os.listdir(files_path)]) # 通过os.listdir()遍历files_path,遍历后得到所有文件的名称
  17. files_num = len(files_name)
  18. val_index = random.sample(range(0, files_num), k=int(files_num*val_rate)) # random.sample——随机采样,range为范围,k为采样个数
  19. train_files = []
  20. val_files = []
  21. for index, file_name in enumerate(files_name):
  22. if index in val_index:
  23. val_files.append(file_name)
  24. else:
  25. train_files.append(file_name)
  26. try:
  27. train_f = open("train.txt", "x")
  28. eval_f = open("val.txt", "x")
  29. train_f.write("\n".join(train_files))
  30. eval_f.write("\n".join(val_files))
  31. except FileExistsError as e:
  32. print(e)
  33. exit(1)
  34. if __name__ == '__main__':
  35. main()

3. VOC格式转YOLO格式(xml_to_yolo.py

  • 注意——文件路径
  • 运行结果
  1. 运行后生成文件如下1
  2. 运行后总文件目录如下2
  3. 生成的my_data_label.names文件内容如下3
  1. ├── my_yolo_dataset 自定义数据集根目录
  2. │ ├── train 训练集目录
  3. │ │ ├── images 训练集图像目录
  4. │ │ └── labels 训练集标签目录
  5. │ └── val 验证集目录
  6. │ ├── images 验证集图像目录
  7. │ └── labels 验证集标签目录
  8. ├── data
  9. │ ├── my_data_label.names
  1. ├── data
  2. │ ├── pascal_voc_classes.json # 用以保存识别类别信息
  3. │ ├── my_data_label.names
  4. ├── VOCdevkit
  5. │ ├── VOC2012
  6. │ │ ├── Annotations # 用以存放所有xml标签文件
  7. │ │ ├── JPEGImages # 用以存放所有标注好的图片
  8. │ │ ├── ImageSets
  9. │ │ │ ├── Main # 用以存放所有txt文件
  10. ├── my_yolo_dataset #自定义数据集根目录
  11. │ ├── train #训练集目录
  12. │ │ ├── images #训练集图像目录
  13. │ │ └── labels #训练集标签目录
  14. │ └── val #验证集目录
  15. │ ├── images #验证集图像目录
  16. │ └── labels #验证集标签目录
  1. dec_1_pass
  2. dec_1_fail
  3. dec_2_pass
  4. dec_2_fail
  1. """
  2. 本脚本有两个功能:
  3. 1.将voc数据集标注信息(.xml)转为yolo标注格式(.txt),并将图像文件复制到相应文件夹
  4. 2.根据json标签文件,生成对应names标签(my_data_label.names),该文件在data-my_data_label.names
  5. """
  6. import os
  7. from tqdm import tqdm
  8. from lxml import etree
  9. import json
  10. import shutil
  11. # voc数据集根目录以及版本
  12. voc_root = r"E:\Code Collection\make my dataset2\VOCdevkit"
  13. voc_version = "VOC2012"
  14. # 转换的训练集以及验证集对应txt文件
  15. train_txt = "train.txt"
  16. val_txt = "val.txt"
  17. # 转换后的文件保存目录
  18. save_file_root = "./my_yolo_dataset"
  19. # label标签对应json文件
  20. label_json_path = r'E:\Code Collection\make my dataset2\data\pascal_voc_classes.json'
  21. # 拼接出voc的images目录,xml目录,txt目录
  22. voc_images_path = os.path.join(voc_root, voc_version, "JPEGImages")
  23. voc_xml_path = os.path.join(voc_root, voc_version, "Annotations")
  24. train_txt_path = os.path.join(voc_root, voc_version, "ImageSets", "Main", train_txt)
  25. val_txt_path = os.path.join(voc_root, voc_version, "ImageSets", "Main", val_txt)
  26. """剩下的不用看,够用就行"""
  27. # 检查文件/文件夹都是否存在
  28. assert os.path.exists(voc_images_path), "VOC images path not exist..."
  29. assert os.path.exists(voc_xml_path), "VOC xml path not exist..."
  30. assert os.path.exists(train_txt_path), "VOC train txt file not exist..."
  31. assert os.path.exists(val_txt_path), "VOC val txt file not exist..."
  32. assert os.path.exists(label_json_path), "label_json_path does not exist..."
  33. if os.path.exists(save_file_root) is False:
  34. os.makedirs(save_file_root)
  35. def parse_xml_to_dict(xml):
  36. """
  37. 将xml文件解析成字典形式,参考tensorflow的recursive_parse_xml_to_dict
  38. Args:
  39. xml: xml tree obtained by parsing XML file contents using lxml.etree
  40. Returns:
  41. Python dictionary holding XML contents.
  42. """
  43. if len(xml) == 0: # 遍历到底层,直接返回tag对应的信息
  44. return {xml.tag: xml.text}
  45. result = {}
  46. for child in xml:
  47. child_result = parse_xml_to_dict(child) # 递归遍历标签信息
  48. if child.tag != 'object':
  49. result[child.tag] = child_result[child.tag]
  50. else:
  51. if child.tag not in result: # 因为object可能有多个,所以需要放入列表里
  52. result[child.tag] = []
  53. result[child.tag].append(child_result[child.tag])
  54. return {xml.tag: result}
  55. def translate_info(file_names: list, save_root: str, class_dict: dict, train_val='train'):
  56. """
  57. 将对应xml文件信息转为yolo中使用的txt文件信息
  58. :param file_names:
  59. :param save_root:
  60. :param class_dict:
  61. :param train_val:
  62. :return:
  63. """
  64. save_txt_path = os.path.join(save_root, train_val, "labels")
  65. if os.path.exists(save_txt_path) is False:
  66. os.makedirs(save_txt_path)
  67. save_images_path = os.path.join(save_root, train_val, "images")
  68. if os.path.exists(save_images_path) is False:
  69. os.makedirs(save_images_path)
  70. for file in tqdm(file_names, desc="translate {} file...".format(train_val)):
  71. # 检查下图像文件是否存在
  72. img_path = os.path.join(voc_images_path, file + ".jpg")
  73. assert os.path.exists(img_path), "file:{} not exist...".format(img_path)
  74. # 检查xml文件是否存在
  75. xml_path = os.path.join(voc_xml_path, file + ".xml")
  76. assert os.path.exists(xml_path), "file:{} not exist...".format(xml_path)
  77. # read xml
  78. with open(xml_path, encoding='utf-8') as fid:
  79. xml_str = fid.read()
  80. xml = etree.fromstring(xml_str)
  81. data = parse_xml_to_dict(xml)["annotation"]
  82. img_height = int(data["size"]["height"])
  83. img_width = int(data["size"]["width"])
  84. # write object info into txt
  85. assert "object" in data.keys(), "file: '{}' lack of object key.".format(xml_path)
  86. if len(data["object"]) == 0:
  87. # 如果xml文件中没有目标就直接忽略该样本
  88. print("Warning: in '{}' xml, there are no objects.".format(xml_path))
  89. continue
  90. with open(os.path.join(save_txt_path, file + ".txt"), "w", encoding='utf-8') as f:
  91. for index, obj in enumerate(data["object"]):
  92. # 获取每个object的box信息
  93. xmin = float(obj["bndbox"]["xmin"])
  94. xmax = float(obj["bndbox"]["xmax"])
  95. ymin = float(obj["bndbox"]["ymin"])
  96. ymax = float(obj["bndbox"]["ymax"])
  97. class_name = obj["name"]
  98. class_index = class_dict[class_name] - 1 # 目标id从0开始
  99. # 进一步检查数据,有的标注信息中可能有w或h为0的情况,这样的数据会导致计算回归loss为nan
  100. if xmax <= xmin or ymax <= ymin:
  101. print("Warning: in '{}' xml, there are some bbox w/h <=0".format(xml_path))
  102. continue
  103. # 将box信息转换到yolo格式
  104. xcenter = xmin + (xmax - xmin) / 2
  105. ycenter = ymin + (ymax - ymin) / 2
  106. w = xmax - xmin
  107. h = ymax - ymin
  108. # 绝对坐标转相对坐标,保存6位小数
  109. xcenter = round(xcenter / img_width, 6)
  110. ycenter = round(ycenter / img_height, 6)
  111. w = round(w / img_width, 6)
  112. h = round(h / img_height, 6)
  113. info = [str(i) for i in [class_index, xcenter, ycenter, w, h]]
  114. if index == 0:
  115. f.write(" ".join(info))
  116. else:
  117. f.write("\n" + " ".join(info))
  118. # copy image into save_images_path
  119. path_copy_to = os.path.join(save_images_path, img_path.split(os.sep)[-1])
  120. if os.path.exists(path_copy_to) is False:
  121. shutil.copyfile(img_path, path_copy_to)
  122. def create_class_names(class_dict: dict):
  123. keys = class_dict.keys()
  124. with open("./data/my_data_label.names", "w", encoding='utf-8') as w:
  125. for index, k in enumerate(keys):
  126. if index + 1 == len(keys):
  127. w.write(k)
  128. else:
  129. w.write(k + "\n")
  130. def main():
  131. # read class_indict
  132. json_file = open(label_json_path, 'r')
  133. class_dict = json.load(json_file)
  134. # 读取train.txt中的所有行信息,删除空行
  135. with open(train_txt_path, "r") as r:
  136. train_file_names = [i for i in r.read().splitlines() if len(i.strip()) > 0]
  137. # voc信息转yolo,并将图像文件复制到相应文件夹
  138. translate_info(train_file_names, save_file_root, class_dict, "train")
  139. # 读取val.txt中的所有行信息,删除空行
  140. with open(val_txt_path, "r") as r:
  141. val_file_names = [i for i in r.read().splitlines() if len(i.strip()) > 0]
  142. # voc信息转yolo,并将图像文件复制到相应文件夹
  143. translate_info(val_file_names, save_file_root, class_dict, "val")
  144. # 创建my_data_label.names文件
  145. create_class_names(class_dict)
  146. if __name__ == "__main__":
  147. main()

4. 准备yaml文件(my_yaml.yaml)

  • 制作一个my_yaml.yaml文件,放在data文件夹中
  • my_yaml.yaml文件内容见下1
  • 文件夹总目录见下2
  1. # Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
  2. path: E:\Code Collection\yolov5-6.1\my_yolo_dataset
  3. train: # train images (relative to 'path') 16551 images
  4. - train/images
  5. val: # val images (relative to 'path') 4952 images
  6. - val/images
  7. # Classes
  8. nc: 4 # number of classes
  9. names: ['dec_1_pass', 'dec_1_fail', "dec_2_pass", "dec_2_fail"] # class names
  1. ├── data
  2. │ ├── pascal_voc_classes.json # 用以保存识别类别信息
  3. │ ├── my_data_label.names # 用以保存识别类别信息
  4. │ ├── my_yaml.yaml # 用以存放路径信息与类别信息
  5. ├── VOCdevkit
  6. │ ├── VOC2012
  7. │ │ ├── Annotations # 用以存放所有xml标签文件
  8. │ │ ├── JPEGImages # 用以存放所有标注好的图片
  9. │ │ ├── ImageSets
  10. │ │ │ ├── Main # 用以存放所有txt文件
  11. ├── my_yolo_dataset # 自定义数据集根目录
  12. │ ├── train # 训练集目录
  13. │ │ ├── images # 训练集图像目录
  14. │ │ └── labels # 训练集标签目录
  15. │ └── val # 验证集目录
  16. │ ├── images # 验证集图像目录
  17. │ └── labels # 验证集标签目录

5. 扩展——YOLO格式转VOC格式

5.1 txt标注文件批量转换成xml标注文件

  1. # -*- coding:UTF-8 -*-
  2. """
  3. @Time :2023/5/17 10:32
  4. @Author :zjy
  5. @File :zjy1.py
  6. @Aim :
  7. """
  8. import xml.dom.minidom
  9. import glob
  10. from PIL import Image
  11. from math import ceil
  12. import shutil
  13. import os
  14. yolo_file = r'E:\资料备份\小论文相关文件\数据集\YOLO格式数据集——18000+200\18000+200数据集\train\labels' # yolo格式下的存放txt标注文件的文件夹
  15. turn_xml_file = r'E:\资料备份\小论文相关文件\数据集\VOC格式数据集——18000+200\train\xml' # 转换后储存xml的文件夹地址
  16. img_file = r'E:\资料备份\小论文相关文件\数据集\YOLO格式数据集——18000+200\18000+200数据集\train\images' # 存放图片的文件夹
  17. labels = ["aeroplane",
  18. "bicycle",
  19. "bird",
  20. "boat",
  21. "bottle",
  22. "bus",
  23. "car",
  24. "cat",
  25. "chair",
  26. "cow",
  27. "diningtable",
  28. "dog",
  29. "horse",
  30. "motorbike",
  31. "person",
  32. "pottedplant",
  33. "sheep",
  34. "sofa",
  35. "train",
  36. "tvmonitor"]
  37. src_img_dir = img_file
  38. src_txt_dir = yolo_file
  39. src_xml_dir = turn_xml_file # 转换后储存xml的文件夹地址
  40. img_Lists = glob.glob(src_img_dir + '/*.jpg')
  41. img_basenames = []
  42. for item in img_Lists:
  43. img_basenames.append(os.path.basename(item)) # os.path.basename返回path最后的文件名
  44. img_names = []
  45. for item in img_basenames:
  46. temp1, temp2 = os.path.splitext(item) # os.path.splitext(“文件路径”) 分离文件名与扩展名
  47. img_names.append(temp1)
  48. total_num = len(img_names) # 统计当前总共要转换的图片标注数量
  49. count = 0 # 技术变量
  50. for img in img_names: # 这里的img是不加后缀的图片名称,如:'GF3_SAY_FSI_002732_E122.3_N29.9_20170215_L1A_HH_L10002188179__1__4320___10368'
  51. count += 1
  52. if count % 1000 == 0:
  53. print("当前转换进度{}/{}".format(count, total_num))
  54. im = Image.open((src_img_dir + '/' + img + '.jpg'))
  55. width, height = im.size
  56. # 打开yolo格式下的txt文件
  57. gt = open(src_txt_dir + '/' + img + '.txt').read().splitlines()
  58. if gt:
  59. # 将主干部分写入xml文件中
  60. xml_file = open((src_xml_dir + '/' + img + '.xml'), 'w')
  61. xml_file.write('<annotation>\n')
  62. xml_file.write(' <folder>VOC2007</folder>\n')
  63. xml_file.write(' <filename>' + str(img) + '.jpg' + '</filename>\n')
  64. xml_file.write(' <size>\n')
  65. xml_file.write(' <width>' + str(width) + '</width>\n')
  66. xml_file.write(' <height>' + str(height) + '</height>\n')
  67. xml_file.write(' <depth>3</depth>\n')
  68. xml_file.write(' </size>\n')
  69. # write the region of image on xml file
  70. for img_each_label in gt:
  71. spt = img_each_label.split(' ') # 这里如果txt里面是以逗号‘,’隔开的,那么就改为spt = img_each_label.split(',')。
  72. xml_file.write(' <object>\n')
  73. xml_file.write(' <name>' + str(labels[int(spt[0])]) + '</name>\n')
  74. xml_file.write(' <pose>Unspecified</pose>\n')
  75. xml_file.write(' <truncated>0</truncated>\n')
  76. xml_file.write(' <difficult>0</difficult>\n')
  77. xml_file.write(' <bndbox>\n')
  78. center_x = round(float(spt[1].strip()) * width)
  79. center_y = round(float(spt[2].strip()) * height)
  80. bbox_width = round(float(spt[3].strip()) * width)
  81. bbox_height = round(float(spt[4].strip()) * height)
  82. xmin = str(int(center_x - bbox_width / 2))
  83. ymin = str(int(center_y - bbox_height / 2))
  84. xmax = str(int(center_x + bbox_width / 2))
  85. ymax = str(int(center_y + bbox_height / 2))
  86. xml_file.write(' <xmin>' + xmin + '</xmin>\n')
  87. xml_file.write(' <ymin>' + ymin + '</ymin>\n')
  88. xml_file.write(' <xmax>' + xmax + '</xmax>\n')
  89. xml_file.write(' <ymax>' + ymax + '</ymax>\n')
  90. xml_file.write(' </bndbox>\n')
  91. xml_file.write(' </object>\n')
  92. xml_file.write('</annotation>')
  93. else:
  94. # 将主干部分写入xml文件中
  95. xml_file = open((src_xml_dir + '/' + img + '.xml'), 'w')
  96. xml_file.write('<annotation>\n')
  97. xml_file.write(' <folder>VOC2007</folder>\n')
  98. xml_file.write(' <filename>' + str(img) + '.jpg' + '</filename>\n')
  99. xml_file.write(' <size>\n')
  100. xml_file.write(' <width>' + str(width) + '</width>\n')
  101. xml_file.write(' <height>' + str(height) + '</height>\n')
  102. xml_file.write(' <depth>3</depth>\n')
  103. xml_file.write(' </size>\n')
  104. xml_file.write('</annotation>')

5.2 将所有训练集、测试集数据名称(去掉后缀)分别写入到train.txt、test.txt

  1. # 将转换后的xml文件按train 和test 归类到train.txt和test.txt中
  2. import glob
  3. path = r'E:\资料备份\小论文相关文件\数据集\VOC格式数据集——18000+200' # 存放生成的txt文件的路径
  4. xml_Lists = glob.glob(src_xml_dir + '/*.xml')
  5. xml_basenames = []
  6. for item in xml_Lists:
  7. xml_basenames.append(os.path.basename(item))
  8. xml_names = [] # 这里是将xml文件去掉.xml后缀储存到的列表中
  9. for item in xml_basenames:
  10. temp1, temp2 = os.path.splitext(item) # os.path.splitext(“文件路径”) 分离文件名与扩展名
  11. xml_names.append(temp1)
  12. txt_file = open((path + '/train.txt'), 'w') # 注意生成train/val的txt时,要改变这里的名字
  13. for item in xml_names:
  14. txt_file.write(str(item) + '\n')

5.3 复制图片

  1. #复制train和val下的文件到一个文件夹中
  2. base_src = r'/home/dwt/DataSets/MSAR/MSAR-1.0/val/images'#要复制的文件所在的文件夹
  3. base_dst = r'/home/dwt/MyCode/pycharm_projects/YOLOX_offical/datasets/VOCdevkit/VOC2011/JPEGImages'#将文件复制到的目标文件夹
  4. list_src = glob.glob(base_src + '/*.jpg')#复制的所有文件
  5. list_src_basenames = []
  6. for item in list_src:
  7. list_src_basenames.append(os.path.basename(item))
  8. total_num = len(list_src_basenames)
  9. c = 0
  10. for item in list_src_basenames:
  11. c += 1
  12. if c % 1000 == 0:
  13. print('当前已复制{}/{}'.format(c,total_num))
  14. shutil.copyfile(os.path.join(base_src,item),os.path.join(base_dst,item))

5.4 上述程序合并到一起

  1. # -*- coding:UTF-8 -*-
  2. """
  3. @Time :2023/5/17 10:32
  4. @Author :zjy
  5. @File :zjy1.py
  6. @Aim :
  7. """
  8. import xml.dom.minidom
  9. import glob
  10. from PIL import Image
  11. from math import ceil
  12. import shutil
  13. import os
  14. import glob
  15. yolo_file = r'E:\资料备份\小论文相关文件\数据集\YOLO格式数据集——18000+200\18000+200数据集\test\labels' # yolo格式下的存放txt标注文件的文件夹
  16. turn_xml_file = r'E:\资料备份\小论文相关文件\数据集\VOC格式数据集——18000+200\新建文件夹' # 转换后储存xml的文件夹地址
  17. img_file = r'E:\资料备份\小论文相关文件\数据集\YOLO格式数据集——18000+200\18000+200数据集\test\images' # 存放图片的文件夹
  18. path = r'E:\资料备份\小论文相关文件\数据集\VOC格式数据集——18000+200\新建文件夹' # 存放生成的txt文件的路径
  19. txt_file = open((path + '/test.txt'), 'w') # 注意生成train/val的txt时,要改变这里的名字
  20. base_src = r'E:\资料备份\小论文相关文件\数据集\YOLO格式数据集——18000+200\18000+200数据集\test\images' # 要复制的照片文件所在的文件夹
  21. base_dst = r'E:\资料备份\小论文相关文件\数据集\VOC格式数据集——18000+200\新建文件夹' # 将照片文件复制到的目标文件夹
  22. list_src = glob.glob(base_src + '/*.jpg') # 复制所有照片文件
  23. labels = ["aeroplane", # 标签名
  24. "bicycle",
  25. "bird",
  26. "boat",
  27. "bottle",
  28. "bus",
  29. "car",
  30. "cat",
  31. "chair",
  32. "cow",
  33. "diningtable",
  34. "dog",
  35. "horse",
  36. "motorbike",
  37. "person",
  38. "pottedplant",
  39. "sheep",
  40. "sofa",
  41. "train",
  42. "tvmonitor"]
  43. src_img_dir = img_file
  44. src_txt_dir = yolo_file
  45. src_xml_dir = turn_xml_file # 转换后储存xml的文件夹地址
  46. img_Lists = glob.glob(src_img_dir + '/*.jpg')
  47. img_basenames = []
  48. for item in img_Lists:
  49. img_basenames.append(os.path.basename(item)) # os.path.basename返回path最后的文件名
  50. img_names = []
  51. for item in img_basenames:
  52. temp1, temp2 = os.path.splitext(item) # os.path.splitext(“文件路径”) 分离文件名与扩展名
  53. img_names.append(temp1)
  54. total_num = len(img_names) # 统计当前总共要转换的图片标注数量
  55. count = 0 # 技术变量
  56. for img in img_names: # 这里的img是不加后缀的图片名称,如:'GF3_SAY_FSI_002732_E122.3_N29.9_20170215_L1A_HH_L10002188179__1__4320___10368'
  57. count += 1
  58. if count % 1000 == 0:
  59. print("当前转换进度{}/{}".format(count, total_num))
  60. im = Image.open((src_img_dir + '/' + img + '.jpg'))
  61. width, height = im.size
  62. # 打开yolo格式下的txt文件
  63. gt = open(src_txt_dir + '/' + img + '.txt').read().splitlines()
  64. if gt:
  65. # 将主干部分写入xml文件中
  66. xml_file = open((src_xml_dir + '/' + img + '.xml'), 'w')
  67. xml_file.write('<annotation>\n')
  68. xml_file.write(' <folder>VOC2007</folder>\n')
  69. xml_file.write(' <filename>' + str(img) + '.jpg' + '</filename>\n')
  70. xml_file.write(' <size>\n')
  71. xml_file.write(' <width>' + str(width) + '</width>\n')
  72. xml_file.write(' <height>' + str(height) + '</height>\n')
  73. xml_file.write(' <depth>3</depth>\n')
  74. xml_file.write(' </size>\n')
  75. # write the region of image on xml file
  76. for img_each_label in gt:
  77. spt = img_each_label.split(' ') # 这里如果txt里面是以逗号‘,’隔开的,那么就改为spt = img_each_label.split(',')。
  78. xml_file.write(' <object>\n')
  79. xml_file.write(' <name>' + str(labels[int(spt[0])]) + '</name>\n')
  80. xml_file.write(' <pose>Unspecified</pose>\n')
  81. xml_file.write(' <truncated>0</truncated>\n')
  82. xml_file.write(' <difficult>0</difficult>\n')
  83. xml_file.write(' <bndbox>\n')
  84. center_x = round(float(spt[1].strip()) * width)
  85. center_y = round(float(spt[2].strip()) * height)
  86. bbox_width = round(float(spt[3].strip()) * width)
  87. bbox_height = round(float(spt[4].strip()) * height)
  88. xmin = str(int(center_x - bbox_width / 2))
  89. ymin = str(int(center_y - bbox_height / 2))
  90. xmax = str(int(center_x + bbox_width / 2))
  91. ymax = str(int(center_y + bbox_height / 2))
  92. xml_file.write(' <xmin>' + xmin + '</xmin>\n')
  93. xml_file.write(' <ymin>' + ymin + '</ymin>\n')
  94. xml_file.write(' <xmax>' + xmax + '</xmax>\n')
  95. xml_file.write(' <ymax>' + ymax + '</ymax>\n')
  96. xml_file.write(' </bndbox>\n')
  97. xml_file.write(' </object>\n')
  98. xml_file.write('</annotation>')
  99. else:
  100. # 将主干部分写入xml文件中
  101. xml_file = open((src_xml_dir + '/' + img + '.xml'), 'w')
  102. xml_file.write('<annotation>\n')
  103. xml_file.write(' <folder>VOC2007</folder>\n')
  104. xml_file.write(' <filename>' + str(img) + '.jpg' + '</filename>\n')
  105. xml_file.write(' <size>\n')
  106. xml_file.write(' <width>' + str(width) + '</width>\n')
  107. xml_file.write(' <height>' + str(height) + '</height>\n')
  108. xml_file.write(' <depth>3</depth>\n')
  109. xml_file.write(' </size>\n')
  110. xml_file.write('</annotation>')
  111. # 将转换后的xml文件按train 和test 归类到train.txt和test.txt中
  112. xml_Lists = glob.glob(src_xml_dir + '/*.xml')
  113. xml_basenames = []
  114. for item in xml_Lists:
  115. xml_basenames.append(os.path.basename(item))
  116. xml_names = [] # 这里是将xml文件去掉.xml后缀储存到的列表中
  117. for item in xml_basenames:
  118. temp1, temp2 = os.path.splitext(item) # os.path.splitext(“文件路径”) 分离文件名与扩展名
  119. xml_names.append(temp1)
  120. for item in xml_names:
  121. txt_file.write(str(item) + '\n')
  122. # 复制train和val下的文件到一个文件夹中
  123. list_src_basenames = []
  124. for item in list_src:
  125. list_src_basenames.append(os.path.basename(item))
  126. total_num = len(list_src_basenames)
  127. c = 0
  128. for item in list_src_basenames:
  129. c += 1
  130. if c % 1000 == 0:
  131. print('当前已复制{}/{}'.format(c, total_num))
  132. shutil.copyfile(os.path.join(base_src, item), os.path.join(base_dst, item))

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

闽ICP备14008679号