当前位置:   article > 正文

PPYOLOE目标检测训练框架使用说明_pp-yoloe源代码

pp-yoloe源代码

数据集准备

  1. 数据集标注参考博客【使用labelimg制作数据集】:使用labelimg制作数据集-CSDN博客

  1. 标注数据注意事项,图片名称为纯数字,例如1289.jpg ;不要出现其他字符,否则下面代码转换会报错。

  1. 标注好的数据集格式为VOC格式,AI Studio 中PPYOLOE用到的数据格式为coco数据格式,需要将标注好的数据进行格式转换。执行python voc2coco.py 即可!转换代码如下:

voc2coco.py

  1. import os
  2. import random
  3. import shutil
  4. import sys
  5. import json
  6. import glob
  7. import xml.etree.ElementTree as ET
  8. """
  9. 代码来源:https://github.com/Stephenfang51/VOC_to_COCO
  10. You only need to set the following three parts
  11. 1.val_files_num : num of validation samples from your all samples
  12. 2.test_files_num = num of test samples from your all samples
  13. 3.voc_annotations : path to your VOC dataset Annotations(最好写成绝对路径)
  14. """
  15. val_files_num = 0
  16. test_files_num = 0
  17. voc_annotations = r'C:/Users/liq/Desktop/VOC/Annotations/' #remember to modify the path
  18. split = voc_annotations.split('/')
  19. coco_name = split[-3]
  20. del split[-3]
  21. del split[-2]
  22. del split[-1]
  23. del split[0]
  24. # print(split)
  25. main_path = ''
  26. for i in split:
  27. main_path += '/' + i
  28. main_path = main_path + '/'
  29. # print(main_path)
  30. coco_path = os.path.join(main_path, coco_name+'_COCO/')
  31. coco_images = os.path.join(main_path, coco_name+'_COCO/images')
  32. coco_json_annotations = os.path.join(main_path, coco_name+'_COCO/annotations/')
  33. xml_val = os.path.join(main_path, 'xml', 'xml_val/')
  34. xml_test = os.path.join(main_path, 'xml/', 'xml_test/')
  35. xml_train = os.path.join(main_path, 'xml/', 'xml_train/')
  36. voc_images = os.path.join(main_path, coco_name, 'JPEGImages/')
  37. #from https://www.php.cn/python-tutorials-424348.html
  38. def mkdir(path):
  39. path=path.strip()
  40. path=path.rstrip("\\")
  41. isExists=os.path.exists(path)
  42. if not isExists:
  43. os.makedirs(path)
  44. print(path+' ----- folder created')
  45. return True
  46. else:
  47. print(path+' ----- folder existed')
  48. return False
  49. #foler to make, please enter full path
  50. mkdir(coco_path)
  51. mkdir(coco_images)
  52. mkdir(coco_json_annotations)
  53. mkdir(xml_val)
  54. mkdir(xml_test)
  55. mkdir(xml_train)
  56. #voc images copy to coco images
  57. for i in os.listdir(voc_images):
  58. img_path = os.path.join(voc_images + i)
  59. shutil.copy(img_path, coco_images)
  60. # voc images copy to coco images
  61. for i in os.listdir(voc_annotations):
  62. img_path = os.path.join(voc_annotations + i)
  63. shutil.copy(img_path, xml_train)
  64. print("\n\n %s files copied to %s" % (val_files_num, xml_val))
  65. for i in range(val_files_num):
  66. if len(os.listdir(xml_train)) > 0:
  67. random_file = random.choice(os.listdir(xml_train))
  68. # print("%d) %s"%(i+1,random_file))
  69. source_file = "%s/%s" % (xml_train, random_file)
  70. if random_file not in os.listdir(xml_val):
  71. shutil.move(source_file, xml_val)
  72. else:
  73. random_file = random.choice(os.listdir(xml_train))
  74. source_file = "%s/%s" % (xml_train, random_file)
  75. shutil.move(source_file, xml_val)
  76. else:
  77. print('The folders are empty, please make sure there are enough %d file to move' % (val_files_num))
  78. break
  79. for i in range(test_files_num):
  80. if len(os.listdir(xml_train)) > 0:
  81. random_file = random.choice(os.listdir(xml_train))
  82. # print("%d) %s"%(i+1,random_file))
  83. source_file = "%s/%s" % (xml_train, random_file)
  84. if random_file not in os.listdir(xml_test):
  85. shutil.move(source_file, xml_test)
  86. else:
  87. random_file = random.choice(os.listdir(xml_train))
  88. source_file = "%s/%s" % (xml_train, random_file)
  89. shutil.move(source_file, xml_test)
  90. else:
  91. print('The folders are empty, please make sure there are enough %d file to move' % (val_files_num))
  92. break
  93. print("\n\n" + "*" * 27 + "[ Done ! Go check your file ]" + "*" * 28)
  94. # !/usr/bin/python
  95. # pip install lxml
  96. START_BOUNDING_BOX_ID = 1
  97. PRE_DEFINE_CATEGORIES = None
  98. # If necessary, pre-define category and its id
  99. # PRE_DEFINE_CATEGORIES = {"aeroplane": 1, "bicycle": 2, "bird": 3, "boat": 4,
  100. # "bottle":5, "bus": 6, "car": 7, "cat": 8, "chair": 9,
  101. # "cow": 10, "diningtable": 11, "dog": 12, "horse": 13,
  102. # "motorbike": 14, "person": 15, "pottedplant": 16,
  103. # "sheep": 17, "sofa": 18, "train": 19, "tvmonitor": 20}
  104. """
  105. main code below are from
  106. https://github.com/Tony607/voc2coco
  107. """
  108. def get(root, name):
  109. vars = root.findall(name)
  110. return vars
  111. def get_and_check(root, name, length):
  112. vars = root.findall(name)
  113. if len(vars) == 0:
  114. raise ValueError("Can not find %s in %s." % (name, root.tag))
  115. if length > 0 and len(vars) != length:
  116. raise ValueError(
  117. "The size of %s is supposed to be %d, but is %d."
  118. % (name, length, len(vars))
  119. )
  120. if length == 1:
  121. vars = vars[0]
  122. return vars
  123. def get_filename_as_int(filename):
  124. try:
  125. filename = filename.replace("\\", "/")
  126. filename = os.path.splitext(os.path.basename(filename))[0]
  127. return int(filename)
  128. except:
  129. raise ValueError("Filename %s is supposed to be an integer." % (filename))
  130. def get_categories(xml_files):
  131. """Generate category name to id mapping from a list of xml files.
  132. Arguments:
  133. xml_files {list} -- A list of xml file paths.
  134. Returns:
  135. dict -- category name to id mapping.
  136. """
  137. classes_names = []
  138. for xml_file in xml_files:
  139. tree = ET.parse(xml_file)
  140. root = tree.getroot()
  141. for member in root.findall("object"):
  142. classes_names.append(member[0].text)
  143. classes_names = list(set(classes_names))
  144. classes_names.sort()
  145. return {name: i for i, name in enumerate(classes_names)}
  146. def convert(xml_files, json_file):
  147. json_dict = {"images": [], "type": "instances", "annotations": [], "categories": []}
  148. if PRE_DEFINE_CATEGORIES is not None:
  149. categories = PRE_DEFINE_CATEGORIES
  150. else:
  151. categories = get_categories(xml_files)
  152. bnd_id = START_BOUNDING_BOX_ID
  153. for xml_file in xml_files:
  154. tree = ET.parse(xml_file)
  155. root = tree.getroot()
  156. path = get(root, "path")
  157. if len(path) == 1:
  158. filename = os.path.basename(path[0].text)
  159. elif len(path) == 0:
  160. filename = get_and_check(root, "filename", 1).text
  161. else:
  162. raise ValueError("%d paths found in %s" % (len(path), xml_file))
  163. ## The filename must be a number
  164. image_id = get_filename_as_int(filename)
  165. size = get_and_check(root, "size", 1)
  166. width = int(get_and_check(size, "width", 1).text)
  167. height = int(get_and_check(size, "height", 1).text)
  168. image = {
  169. "file_name": filename,
  170. "height": height,
  171. "width": width,
  172. "id": image_id,
  173. }
  174. json_dict["images"].append(image)
  175. ## Currently we do not support segmentation.
  176. # segmented = get_and_check(root, 'segmented', 1).text
  177. # assert segmented == '0'
  178. for obj in get(root, "object"):
  179. category = get_and_check(obj, "name", 1).text
  180. if category not in categories:
  181. new_id = len(categories)
  182. categories[category] = new_id
  183. category_id = categories[category]
  184. bndbox = get_and_check(obj, "bndbox", 1)
  185. xmin = int(get_and_check(bndbox, "xmin", 1).text) - 1
  186. ymin = int(get_and_check(bndbox, "ymin", 1).text) - 1
  187. xmax = int(get_and_check(bndbox, "xmax", 1).text)
  188. ymax = int(get_and_check(bndbox, "ymax", 1).text)
  189. assert xmax > xmin
  190. assert ymax > ymin
  191. o_width = abs(xmax - xmin)
  192. o_height = abs(ymax - ymin)
  193. ann = {
  194. "area": o_width * o_height,
  195. "iscrowd": 0,
  196. "image_id": image_id,
  197. "bbox": [xmin, ymin, o_width, o_height],
  198. "category_id": category_id,
  199. "id": bnd_id,
  200. "ignore": 0,
  201. "segmentation": [],
  202. }
  203. json_dict["annotations"].append(ann)
  204. bnd_id = bnd_id + 1
  205. for cate, cid in categories.items():
  206. cat = {"supercategory": "none", "id": cid, "name": cate}
  207. json_dict["categories"].append(cat)
  208. os.makedirs(os.path.dirname(json_file), exist_ok=True)
  209. json_fp = open(json_file, "w")
  210. json_str = json.dumps(json_dict)
  211. json_fp.write(json_str)
  212. json_fp.close()
  213. xml_val_files = glob.glob(os.path.join(xml_val, "*.xml"))
  214. xml_test_files = glob.glob(os.path.join(xml_test, "*.xml"))
  215. xml_train_files = glob.glob(os.path.join(xml_train, "*.xml"))
  216. convert(xml_val_files, coco_json_annotations + 'val2017.json')
  217. convert(xml_test_files, coco_json_annotations+'test2017.json')
  218. convert(xml_train_files, coco_json_annotations + 'train2017.json')

或者使用voc2coco2.py

  1. # !/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. '''
  4. @Project :always
  5. @File :voc2coco2.py
  6. @Author :Lis
  7. @Date :2023/7/28 18:23
  8. @Desc :
  9. '''
  10. import xml.etree.ElementTree as ET
  11. import os
  12. import json
  13. coco = dict()
  14. coco['images'] = []
  15. coco['type'] = 'instances'
  16. coco['annotations'] = []
  17. coco['categories'] = []
  18. category_set = dict()
  19. image_set = set()
  20. category_item_id = -1
  21. image_id = 20180000000
  22. annotation_id = 0
  23. def addCatItem(name):
  24. global category_item_id
  25. category_item = dict()
  26. category_item['supercategory'] = 'none'
  27. category_item_id += 1
  28. category_item['id'] = category_item_id
  29. category_item['name'] = name
  30. coco['categories'].append(category_item)
  31. category_set[name] = category_item_id
  32. return category_item_id
  33. def addImgItem(file_name, size):
  34. global image_id
  35. if file_name is None:
  36. raise Exception('Could not find filename tag in xml file.')
  37. if size['width'] is None:
  38. raise Exception('Could not find width tag in xml file.')
  39. if size['height'] is None:
  40. raise Exception('Could not find height tag in xml file.')
  41. image_id += 1
  42. image_item = dict()
  43. image_item['id'] = image_id
  44. image_item['file_name'] = file_name
  45. image_item['width'] = size['width']
  46. image_item['height'] = size['height']
  47. coco['images'].append(image_item)
  48. image_set.add(file_name)
  49. return image_id
  50. def addAnnoItem(object_name, image_id, category_id, bbox):
  51. global annotation_id
  52. annotation_item = dict()
  53. annotation_item['segmentation'] = []
  54. seg = []
  55. # bbox[] is x,y,w,h
  56. # left_top
  57. seg.append(bbox[0])
  58. seg.append(bbox[1])
  59. # left_bottom
  60. seg.append(bbox[0])
  61. seg.append(bbox[1] + bbox[3])
  62. # right_bottom
  63. seg.append(bbox[0] + bbox[2])
  64. seg.append(bbox[1] + bbox[3])
  65. # right_top
  66. seg.append(bbox[0] + bbox[2])
  67. seg.append(bbox[1])
  68. annotation_item['segmentation'].append(seg)
  69. annotation_item['area'] = bbox[2] * bbox[3]
  70. annotation_item['iscrowd'] = 0
  71. annotation_item['ignore'] = 0
  72. annotation_item['image_id'] = image_id
  73. annotation_item['bbox'] = bbox
  74. annotation_item['category_id'] = category_id
  75. annotation_id += 1
  76. annotation_item['id'] = annotation_id
  77. coco['annotations'].append(annotation_item)
  78. def parseXmlFiles(xml_path):
  79. for f in os.listdir(xml_path):
  80. if not f.endswith('.xml'):
  81. continue
  82. bndbox = dict()
  83. size = dict()
  84. current_image_id = None
  85. current_category_id = None
  86. file_name = None
  87. size['width'] = None
  88. size['height'] = None
  89. size['depth'] = None
  90. xml_file = os.path.join(xml_path, f)
  91. print(xml_file)
  92. tree = ET.parse(xml_file)
  93. root = tree.getroot()
  94. if root.tag != 'annotation':
  95. raise Exception('pascal voc xml root element should be annotation, rather than {}'.format(root.tag))
  96. # elem is <folder>, <filename>, <size>, <object>
  97. for elem in root:
  98. current_parent = elem.tag
  99. current_sub = None
  100. object_name = None
  101. if elem.tag == 'folder':
  102. continue
  103. if elem.tag == 'filename':
  104. file_name = elem.text
  105. if file_name in category_set:
  106. raise Exception('file_name duplicated')
  107. # add img item only after parse <size> tag
  108. elif current_image_id is None and file_name is not None and size['width'] is not None:
  109. if file_name not in image_set:
  110. current_image_id = addImgItem(file_name, size)
  111. print('add image with {} and {}'.format(file_name, size))
  112. else:
  113. raise Exception('duplicated image: {}'.format(file_name))
  114. # subelem is <width>, <height>, <depth>, <name>, <bndbox>
  115. for subelem in elem:
  116. bndbox['xmin'] = None
  117. bndbox['xmax'] = None
  118. bndbox['ymin'] = None
  119. bndbox['ymax'] = None
  120. current_sub = subelem.tag
  121. if current_parent == 'object' and subelem.tag == 'name':
  122. object_name = subelem.text
  123. if object_name not in category_set:
  124. current_category_id = addCatItem(object_name)
  125. else:
  126. current_category_id = category_set[object_name]
  127. elif current_parent == 'size':
  128. if size[subelem.tag] is not None:
  129. raise Exception('xml structure broken at size tag.')
  130. size[subelem.tag] = int(subelem.text)
  131. # option is <xmin>, <ymin>, <xmax>, <ymax>, when subelem is <bndbox>
  132. for option in subelem:
  133. if current_sub == 'bndbox':
  134. if bndbox[option.tag] is not None:
  135. raise Exception('xml structure corrupted at bndbox tag.')
  136. bndbox[option.tag] = int(option.text)
  137. # only after parse the <object> tag
  138. if bndbox['xmin'] is not None:
  139. if object_name is None:
  140. raise Exception('xml structure broken at bndbox tag')
  141. if current_image_id is None:
  142. raise Exception('xml structure broken at bndbox tag')
  143. if current_category_id is None:
  144. raise Exception('xml structure broken at bndbox tag')
  145. bbox = []
  146. # x
  147. bbox.append(bndbox['xmin'])
  148. # y
  149. bbox.append(bndbox['ymin'])
  150. # w
  151. bbox.append(bndbox['xmax'] - bndbox['xmin'])
  152. # h
  153. bbox.append(bndbox['ymax'] - bndbox['ymin'])
  154. print('add annotation with {},{},{},{}'.format(object_name, current_image_id, current_category_id,
  155. bbox))
  156. addAnnoItem(object_name, current_image_id, current_category_id, bbox)
  157. if __name__ == '__main__':
  158. # 只需要改动这两个参数就行了
  159. xml_path = r'C:\Users\Administrator\Desktop\皮革数据检测格式数据集\anno' # 这是xml文件所在的地址
  160. json_file = r'C:\Users\Administrator\Desktop\皮革数据检测格式数据集\annotations.json' # 这是你要生成的json文件
  161. parseXmlFiles(xml_path)
  162. json.dump(coco, open(json_file, 'w'))

Fork PPYOLOE项目并启动运行

PPYOLOE目标检测训练框架

PPYOLOE目标检测训练框架 - 飞桨AI Studio星河社区

按照main.ipynb流程依次执行即可!

  1. 导入所需要的第三方库

  1. 安装paddlex

  1. 创建数据集目录 将标注的图像数据上传到 MyDataset/JPEGImages 目录下;将coco格式数据标签annotations.json放到MyDataset目录下。

  1. 按比例切分数据集

  1. git PaddleDetection代码

  1. 进入PaddleDetection目录

  1. 根据需求修改配置文件,比如检测的目标类别数 进入/home/aistudio/config_file/目录下,修改visdrone_detection.yml中num_classes参数

  1. 开始训练

  1. 训练完成后评估模型

  1. 挑一张验证集的图片展示预测效果(可以到生成的目录下,打开查看)

  1. 导出模型,即可使用FastDeploy进行快速推理

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

闽ICP备14008679号