• YOLOV7训练TT100K交通标识符数据集


                                                             《临江仙》

                                                            作者:缠中说禅

                    浊水倾波三万里,愀然独坐孤峰。龙潜狮睡候飙风。无情皆竖子,有泪亦英雄。
                    长剑倚天星斗烂,古今过眼成空。乾坤俯仰任穷通。半轮沧海上,一苇大江东。

    一、yolov7环境搭建

    参见我的其他博客文章,还有个下载文档,免费的

    二、TT100K数据集处理

    2.1 数据集下载19多个G

    https://bj.bcebos.com/ai-studio-online/11d4aa5b64674c399ae4a092dd2c99a1be48927a53ba41f09659040497f7ad23?authorization=bce-auth-v1%2F5cfe9a5e1454405eb2a975c43eace6ec%2F2022-09-04T15%3A26%3A20Z%2F-1%2F%2Fb6ad292a7a8dea9aaaa342f6c29ddf7f238f17f4b0de359440ad2ecffd88196d&responseContentDisposition=attachment%3B%20filename%3Dtt100k_2021.zip

    解压后的目录:

    2.2 代码用法说明

    我是在如下文章指导下进行的数据处理,把他的代码做了一些改动,参考时候请注意。

    参考链接:

    win下YOLOv7训练自己的数据集(交通标志TT100K识别)_tt100k数据集_我宿孤栈的博客-CSDN博客

    tt100k.class_statistics()#对TT100K中的数据集进行预处理,代码中是只保留包含图片数超过100的类别;

    tt100k.original_datasets2object_datasets_re()#对TT100K数据集的训练集、验证集和测试集进行比例划分;7:2:1=train:val:test.然后我加了一些代码,顺便把分类好的数据图片进行了转移,也就是把保留包含图片数超过100的类别的图片换了个地方保存。

    tt100k.coco_json2yolo_txt('val')#将CoCo格式的标签json文件(3个json文件)转换为YOLO格式的txt(注意此处需要分别调用三次,train、val和test,对应生成其3个.txt文件);

    2.3 代码

    2.3.1 如下是整体代码

    1. import os
    2. import json
    3. from random import random
    4. import cv2
    5. import shutil
    6. import json
    7. import xml.dom.minidom
    8. from tqdm import tqdm
    9. import argparse
    10. # from jinxSkills.jinx_opencv.datasets_transform.dataset_transform import DataSets_transform
    11. class TT100K2COCO:
    12. def __init__(self):
    13. self.original_datasets = 'tt100k'
    14. self.to_datasets = 'coco'
    15. def class_statistics(self):
    16. # os.makedirs('annotations', exist_ok=True)
    17. # 存放数据的父路径
    18. parent_path = 'E:/WorkSpace/YOLO/data/data'
    19. #print(parent_path)
    20. # 读TT100K原始数据集标注文件
    21. with open(os.path.join(parent_path, 'annotations.json')) as origin_json:
    22. origin_dict = json.load(origin_json)
    23. classes = origin_dict['types']
    24. # 建立统计每个类别包含的图片的字典
    25. sta = {}
    26. for i in classes:
    27. sta[i] = []
    28. images_dic = origin_dict['imgs']
    29. # 记录所有保留的图片
    30. saved_images = []
    31. # 遍历TT100K的imgs
    32. for image_id in images_dic:
    33. image_element = images_dic[image_id]##
    34. image_path = 'E:/WorkSpace/YOLO/data/data/'+image_element['path']
    35. #print(image_path)
    36. # 添加图像的信息到dataset中
    37. image_path = image_path.split('/')[-1]
    38. obj_list = image_element['objects']
    39. #print(image_path)
    40. # 遍历每张图片的标注信息
    41. for anno_dic in obj_list:
    42. label_key = anno_dic['category']
    43. # 防止一个图片多次加入一个标签类别
    44. if image_path not in sta[label_key]:
    45. sta[label_key].append(image_path)
    46. # 只保留包含图片数超过100的类别(重新划分,阈值100可根据需求修改)
    47. result = {k: v for k, v in sta.items() if len(v) >= 100}
    48. for i in result:
    49. #print("the type of {} includes {} images".format(i, len(result[i])))
    50. saved_images.extend(result[i])
    51. saved_images = list(set(saved_images))
    52. #print("total types is {}".format(len(result)))
    53. type_list = list(result.keys())
    54. result = {"type": type_list, "details": result, "images": saved_images}
    55. print(type_list)
    56. # 保存结果
    57. json_name = os.path.join(parent_path, 'statistics.json')
    58. with open(json_name, 'w', encoding="utf-8") as f:
    59. json.dump(result, f, ensure_ascii=False, indent=1)
    60. def original_datasets2object_datasets_re(self):
    61. '''
    62. 重新划分数据集
    63. :return:
    64. '''
    65. # os.makedirs('annotations2', exist_ok=True)
    66. # 存放数据的父路径
    67. parent_path = 'E:/WorkSpace/YOLO/data/data/'
    68. # 读TT100K原始数据集标注文件
    69. with open(os.path.join(parent_path, 'annotations.json')) as origin_json:
    70. origin_dict = json.load(origin_json)
    71. with open(os.path.join(parent_path, 'statistics.json')) as select_json:
    72. select_dict = json.load(select_json)
    73. classes = select_dict['type']
    74. train_dataset = {'info': {}, 'licenses': [], 'categories': [], 'images': [], 'annotations': []}
    75. val_dataset = {'info': {}, 'licenses': [], 'categories': [], 'images': [], 'annotations': []}
    76. test_dataset = {'info': {}, 'licenses': [], 'categories': [], 'images': [], 'annotations': []}
    77. label = {} # 记录每个标志类别的id
    78. count = {} # 记录每个类别的图片数
    79. owntype_sum = {}
    80. info = {
    81. "year": 2021, # 年份
    82. "version": '1.0', # 版本
    83. "description": "TT100k_to_coco", # 数据集描述
    84. "contributor": "Tecent&Tsinghua", # 提供者
    85. "url": 'https://cg.cs.tsinghua.edu.cn/traffic-sign/', # 下载地址
    86. "date_created": 2021 - 1 - 15
    87. }
    88. licenses = {
    89. "id": 1,
    90. "name": "null",
    91. "url": "null",
    92. }
    93. train_dataset['info'] = info
    94. val_dataset['info'] = info
    95. test_dataset['info'] = info
    96. train_dataset['licenses'] = licenses
    97. val_dataset['licenses'] = licenses
    98. test_dataset['licenses'] = licenses
    99. # 建立类别和id的关系
    100. for i, cls in enumerate(classes):
    101. train_dataset['categories'].append({'id': i, 'name': cls, 'supercategory': 'traffic_sign'})
    102. val_dataset['categories'].append({'id': i, 'name': cls, 'supercategory': 'traffic_sign'})
    103. test_dataset['categories'].append({'id': i, 'name': cls, 'supercategory': 'traffic_sign'})
    104. label[cls] = i
    105. count[cls] = 0
    106. owntype_sum[cls] = 0
    107. images_dic = origin_dict['imgs']#源annotations.json
    108. obj_id = 1
    109. # 计算出每个类别共‘包含’的图片数
    110. for image_id in images_dic:
    111. image_element = images_dic[image_id]
    112. image_path = image_element['path']
    113. image_name = image_path.split('/')[-1]
    114. #print(image_name)#32770.jpg
    115. # 在所选的类别图片中
    116. if image_name not in select_dict['images']:
    117. continue
    118. else:
    119. #加一个赋值图片的语句
    120. i=0
    121. # 处理TT100K中的标注信息
    122. obj_list = image_element['objects']
    123. # 记录图片中包含最多的实例所属的type
    124. includes_type = {}
    125. for anno_dic in obj_list:
    126. if anno_dic["category"] not in select_dict["type"]:
    127. continue
    128. # print(anno_dic["category"])
    129. if anno_dic["category"] in includes_type:
    130. includes_type[anno_dic["category"]] += 1
    131. else:
    132. includes_type[anno_dic["category"]] = 1
    133. # print(includes_type)
    134. own_type = max(includes_type, key=includes_type.get)
    135. owntype_sum[own_type] += 1
    136. # TT100K的annotation转换成coco的
    137. for image_id in images_dic:
    138. image_element = images_dic[image_id]
    139. image_path = image_element['path']
    140. image_name = image_path.split('/')[-1]
    141. # 在所选的类别图片中
    142. if image_name not in select_dict['images']:
    143. continue
    144. ##print("dealing with {} image".format(image_path))
    145. # shutil.copy(os.path.join(parent_path,image_path),os.path.join(parent_path,"dataset/JPEGImages"))
    146. # 处理TT100K中的标注信息
    147. obj_list = image_element['objects']
    148. # 记录图片中包含最多的实例所属的type
    149. includes_type = {}
    150. for anno_dic in obj_list:
    151. if anno_dic["category"] not in select_dict["type"]:
    152. continue
    153. # print(anno_dic["category"])
    154. if anno_dic["category"] in includes_type:
    155. includes_type[anno_dic["category"]] += 1
    156. else:
    157. includes_type[anno_dic["category"]] = 1
    158. # print(includes_type)
    159. own_type = max(includes_type, key=includes_type.get)
    160. count[own_type] += 1
    161. num_rate = count[own_type] / owntype_sum[own_type]
    162. # 切换dataset的引用对象,从而划分数据集根据每个类别类别的总数量按721分为了train_set,val_set,test_set
    163. # 其中每个图片所属类别根据该图片包含的类别的数量决定(归属为含有类别最多的类别)
    164. target = 'E:/WorkSpace/YOLO/data/'
    165. if num_rate < 0.7:
    166. dataset = train_dataset
    167. #print(image_path)
    168. shutil.copyfile(parent_path + image_path, target + '/train/' + image_path.split("/")[1])
    169. elif num_rate < 0.9:
    170. dataset = val_dataset
    171. shutil.copyfile(parent_path + image_path, target + '/val/' + image_path.split("/")[1])
    172. #print(image_path)
    173. else:
    174. #print("dataset=test_dataset")
    175. dataset = test_dataset
    176. #print(image_path)
    177. shutil.copyfile(parent_path + image_path, target + '/test/' + image_path.split("/")[1])
    178. for anno_dic in obj_list:
    179. if anno_dic["category"] not in select_dict["type"]:
    180. continue
    181. x = anno_dic['bbox']['xmin']
    182. y = anno_dic['bbox']['ymin']
    183. width = anno_dic['bbox']['xmax'] - anno_dic['bbox']['xmin']
    184. height = anno_dic['bbox']['ymax'] - anno_dic['bbox']['ymin']
    185. label_key = anno_dic['category']
    186. dataset['annotations'].append({
    187. 'area': width * height,
    188. 'bbox': [x, y, width, height],
    189. 'category_id': label[label_key],
    190. 'id': obj_id,
    191. 'image_id': image_id,
    192. 'iscrowd': 0,
    193. # mask, 矩形是从左上角点按顺时针的四个顶点
    194. 'segmentation': [[x, y, x + width, y, x + width, y + height, x, y + height]]
    195. })
    196. # 每个标注的对象id唯一
    197. obj_id += 1
    198. # 用opencv读取图片,得到图像的宽和高
    199. im = cv2.imread(os.path.join(parent_path, image_path))
    200. #####---------------------------------------------
    201. ##print(image_path) #test other train
    202. prefix = image_path.split("/")[0]
    203. H,W,_ = im.shape
    204. # 添加图像的信息到dataset中
    205. dataset['images'].append({'file_name': image_name,
    206. 'id': image_id,
    207. 'width': W,
    208. 'height': H})
    209. # 保存结果
    210. for phase in ['train', 'val', 'test']:
    211. json_name = os.path.join(parent_path, 'dataset/annotations/{}.json'.format(phase))
    212. with open(json_name, 'w', encoding="utf-8") as f:
    213. if phase == 'train':
    214. shutil.copyfile(parent_path + image_path, target + '/train/' + image_path.split("/")[1])
    215. json.dump(train_dataset, f, ensure_ascii=False, indent=1)
    216. if phase == 'val':
    217. json.dump(val_dataset, f, ensure_ascii=False, indent=1)
    218. if phase == 'test':
    219. json.dump(test_dataset, f, ensure_ascii=False, indent=1)
    220. def coco_json2yolo_txt(self, class_json):
    221. # COCO 格式的数据集转化为 YOLO 格式的数据集
    222. # --json_path 输入的json文件路径
    223. # --save_path 保存的文件夹名字,默认为当前目录下的labels。
    224. def convert(size, box):
    225. dw = 1. / (size[0])
    226. dh = 1. / (size[1])
    227. x = box[0] + box[2] / 2.0
    228. y = box[1] + box[3] / 2.0
    229. w = box[2]
    230. h = box[3]
    231. # round函数确定(xmin, ymin, xmax, ymax)的小数位数
    232. x = round(x * dw, 6)
    233. w = round(w * dw, 6)
    234. y = round(y * dh, 6)
    235. h = round(h * dh, 6)
    236. return (x, y, w, h)
    237. # class_json = 'train'
    238. json_file = os.path.join(
    239. 'E:/WorkSpace/YOLO/data/data/dataset/annotations/%s.json' % class_json) # COCO Object Instance 类型的标注
    240. #E:/WorkSpace/YOLO/data/data/dataset/annotations/val.json
    241. #print(json_file)
    242. # ana_txt_save_path = 'D:/jinxData/TT100K/data/dataset/annotations/train' # 保存的路径
    243. ana_txt_save_path = os.path.join('E:/WorkSpace/YOLO/data/data/dataset/annotations/', class_json) # 保存的路径
    244. #print(class_json)#val
    245. #print(ana_txt_save_path)#E:/WorkSpace/YOLO/data/data/dataset/annotations\val
    246. data = json.load(open(json_file, 'r'))
    247. if not os.path.exists(ana_txt_save_path):
    248. os.makedirs(ana_txt_save_path)
    249. id_map = {} # coco数据集的id不连续!重新映射一下再输出!
    250. with open(os.path.join(ana_txt_save_path, 'classes.txt'), 'w') as f:
    251. # 写入classes.txt
    252. for i, category in enumerate(data['categories']):
    253. f.write(f"{category['name']}\n")
    254. id_map[category['id']] = i
    255. # print(id_map)
    256. # 这里需要根据自己的需要,更改写入图像相对路径的文件位置。
    257. list_file = open(os.path.join(ana_txt_save_path, '%s.txt' % class_json.format()), 'w')
    258. for img in tqdm(data['images']):
    259. filename = img["file_name"]
    260. img_width = img["width"]
    261. img_height = img["height"]
    262. img_id = img["id"]
    263. head, tail = os.path.splitext(filename)
    264. ana_txt_name = head + ".txt" # 对应的txt名字,与jpg一致
    265. f_txt = open(os.path.join(ana_txt_save_path, ana_txt_name), 'w')
    266. for ann in data['annotations']:
    267. if ann['image_id'] == img_id:
    268. box = convert((img_width, img_height), ann["bbox"])
    269. f_txt.write("%s %s %s %s %s\n" % (id_map[ann["category_id"]], box[0], box[1], box[2], box[3]))
    270. f_txt.close()
    271. #将图片的相对路径写入train2017或val2017的路径 'E:/WorkSpace/YOLO/yolov7-main/yolov7-main/dataset/TT100K/images/'
    272. #list_file.write('%s/%s/%s.jpg\n' % ('E:/WorkSpace/YOLO/data/data/',class_json.format(), head))
    273. list_file.write('%s/%s/%s.jpg\n' % ('E:/WorkSpace/YOLO/yolov7-main/yolov7-main/data/TT100K/images/', class_json.format(), head))
    274. list_file.close()
    275. if __name__ == '__main__':
    276. tt100k = TT100K2COCO()
    277. #tt100k.class_statistics()
    278. #tt100k.original_datasets2object_datasets_re()
    279. tt100k.coco_json2yolo_txt('val')
    280. tt100k.coco_json2yolo_txt('test')
    281. tt100k.coco_json2yolo_txt('train')

    2.3.2 如下是每个函数的代码以及我的注释

    class_statistics(self)函数:把data1看成data把,因为我已经有了个data文件夹,为了写教程又重新解压了一份。

    parent_path = 'E:/WorkSpace/YOLO/data/data'
    
    这一块可以不用加上'E:/WorkSpace/YOLO/data/data/'+  
    直接为image_path  = image_element['path']就可以了
    image_path = 'E:/WorkSpace/YOLO/data/data/'+image_element['path']
    

    改完上述两个部分后,运行该函数,会生成一个statistics.json文件。

    1. def class_statistics(self):
    2. # os.makedirs('annotations', exist_ok=True)
    3. # 存放数据的父路径
    4. parent_path = 'E:/WorkSpace/YOLO/data/data'
    5. #print(parent_path)
    6. # 读TT100K原始数据集标注文件
    7. with open(os.path.join(parent_path, 'annotations.json')) as origin_json:
    8. origin_dict = json.load(origin_json)
    9. classes = origin_dict['types']
    10. # 建立统计每个类别包含的图片的字典
    11. sta = {}
    12. for i in classes:
    13. sta[i] = []
    14. images_dic = origin_dict['imgs']
    15. # 记录所有保留的图片
    16. saved_images = []
    17. # 遍历TT100K的imgs
    18. for image_id in images_dic:
    19. image_element = images_dic[image_id]##
    20. image_path = 'E:/WorkSpace/YOLO/data/data/'+image_element['path']
    21. #print(image_path)
    22. # 添加图像的信息到dataset中
    23. image_path = image_path.split('/')[-1]
    24. obj_list = image_element['objects']
    25. #print(image_path)
    26. # 遍历每张图片的标注信息
    27. for anno_dic in obj_list:
    28. label_key = anno_dic['category']
    29. # 防止一个图片多次加入一个标签类别
    30. if image_path not in sta[label_key]:
    31. sta[label_key].append(image_path)
    32. # 只保留包含图片数超过100的类别(重新划分,阈值100可根据需求修改)
    33. result = {k: v for k, v in sta.items() if len(v) >= 100}
    34. for i in result:
    35. #print("the type of {} includes {} images".format(i, len(result[i])))
    36. saved_images.extend(result[i])
    37. saved_images = list(set(saved_images))
    38. #print("total types is {}".format(len(result)))
    39. type_list = list(result.keys())
    40. result = {"type": type_list, "details": result, "images": saved_images}
    41. print(type_list)
    42. # 保存结果
    43. json_name = os.path.join(parent_path, 'statistics.json')
    44. with open(json_name, 'w', encoding="utf-8") as f:
    45. json.dump(result, f, ensure_ascii=False, indent=1)
    original_datasets2object_datasets_re函数

    改动比较多注意。

    1.parent_path = 'E:/WorkSpace/YOLO/data/data/'  不用说了吧

    2.加一句target = 'E:/WorkSpace/YOLO/data/',就是一个你最后要用的test  train  val图片的目录,可以自己指定。

    3.3个复制函数,我最后生成的三个文件夹

    4.运行函数,会很慢,最后会生成3的三个文件夹,已经3个json文件,还有label文件

     

    1. def original_datasets2object_datasets_re(self):
    2. '''
    3. 重新划分数据集
    4. :return:
    5. '''
    6. # os.makedirs('annotations2', exist_ok=True)
    7. # 存放数据的父路径
    8. parent_path = 'E:/WorkSpace/YOLO/data/data/'
    9. # 读TT100K原始数据集标注文件
    10. with open(os.path.join(parent_path, 'annotations.json')) as origin_json:
    11. origin_dict = json.load(origin_json)
    12. with open(os.path.join(parent_path, 'statistics.json')) as select_json:
    13. select_dict = json.load(select_json)
    14. classes = select_dict['type']
    15. train_dataset = {'info': {}, 'licenses': [], 'categories': [], 'images': [], 'annotations': []}
    16. val_dataset = {'info': {}, 'licenses': [], 'categories': [], 'images': [], 'annotations': []}
    17. test_dataset = {'info': {}, 'licenses': [], 'categories': [], 'images': [], 'annotations': []}
    18. label = {} # 记录每个标志类别的id
    19. count = {} # 记录每个类别的图片数
    20. owntype_sum = {}
    21. info = {
    22. "year": 2021, # 年份
    23. "version": '1.0', # 版本
    24. "description": "TT100k_to_coco", # 数据集描述
    25. "contributor": "Tecent&Tsinghua", # 提供者
    26. "url": 'https://cg.cs.tsinghua.edu.cn/traffic-sign/', # 下载地址
    27. "date_created": 2021 - 1 - 15
    28. }
    29. licenses = {
    30. "id": 1,
    31. "name": "null",
    32. "url": "null",
    33. }
    34. train_dataset['info'] = info
    35. val_dataset['info'] = info
    36. test_dataset['info'] = info
    37. train_dataset['licenses'] = licenses
    38. val_dataset['licenses'] = licenses
    39. test_dataset['licenses'] = licenses
    40. # 建立类别和id的关系
    41. for i, cls in enumerate(classes):
    42. train_dataset['categories'].append({'id': i, 'name': cls, 'supercategory': 'traffic_sign'})
    43. val_dataset['categories'].append({'id': i, 'name': cls, 'supercategory': 'traffic_sign'})
    44. test_dataset['categories'].append({'id': i, 'name': cls, 'supercategory': 'traffic_sign'})
    45. label[cls] = i
    46. count[cls] = 0
    47. owntype_sum[cls] = 0
    48. images_dic = origin_dict['imgs']#源annotations.json
    49. obj_id = 1
    50. # 计算出每个类别共‘包含’的图片数
    51. for image_id in images_dic:
    52. image_element = images_dic[image_id]
    53. image_path = image_element['path']
    54. image_name = image_path.split('/')[-1]
    55. #print(image_name)#32770.jpg
    56. # 在所选的类别图片中
    57. if image_name not in select_dict['images']:
    58. continue
    59. else:
    60. #加一个赋值图片的语句
    61. i=0
    62. # 处理TT100K中的标注信息
    63. obj_list = image_element['objects']
    64. # 记录图片中包含最多的实例所属的type
    65. includes_type = {}
    66. for anno_dic in obj_list:
    67. if anno_dic["category"] not in select_dict["type"]:
    68. continue
    69. # print(anno_dic["category"])
    70. if anno_dic["category"] in includes_type:
    71. includes_type[anno_dic["category"]] += 1
    72. else:
    73. includes_type[anno_dic["category"]] = 1
    74. # print(includes_type)
    75. own_type = max(includes_type, key=includes_type.get)
    76. owntype_sum[own_type] += 1
    77. # TT100K的annotation转换成coco的
    78. for image_id in images_dic:
    79. image_element = images_dic[image_id]
    80. image_path = image_element['path']
    81. image_name = image_path.split('/')[-1]
    82. # 在所选的类别图片中
    83. if image_name not in select_dict['images']:
    84. continue
    85. ##print("dealing with {} image".format(image_path))
    86. # shutil.copy(os.path.join(parent_path,image_path),os.path.join(parent_path,"dataset/JPEGImages"))
    87. # 处理TT100K中的标注信息
    88. obj_list = image_element['objects']
    89. # 记录图片中包含最多的实例所属的type
    90. includes_type = {}
    91. for anno_dic in obj_list:
    92. if anno_dic["category"] not in select_dict["type"]:
    93. continue
    94. # print(anno_dic["category"])
    95. if anno_dic["category"] in includes_type:
    96. includes_type[anno_dic["category"]] += 1
    97. else:
    98. includes_type[anno_dic["category"]] = 1
    99. # print(includes_type)
    100. own_type = max(includes_type, key=includes_type.get)
    101. count[own_type] += 1
    102. num_rate = count[own_type] / owntype_sum[own_type]
    103. # 切换dataset的引用对象,从而划分数据集根据每个类别类别的总数量按721分为了train_set,val_set,test_set
    104. # 其中每个图片所属类别根据该图片包含的类别的数量决定(归属为含有类别最多的类别)
    105. target = 'E:/WorkSpace/YOLO/data/'
    106. if num_rate < 0.7:
    107. dataset = train_dataset
    108. #print(image_path)
    109. shutil.copyfile(parent_path + image_path, target + '/train/' + image_path.split("/")[1])
    110. elif num_rate < 0.9:
    111. dataset = val_dataset
    112. shutil.copyfile(parent_path + image_path, target + '/val/' + image_path.split("/")[1])
    113. #print(image_path)
    114. else:
    115. #print("dataset=test_dataset")
    116. dataset = test_dataset
    117. #print(image_path)
    118. shutil.copyfile(parent_path + image_path, target + '/test/' + image_path.split("/")[1])
    119. for anno_dic in obj_list:
    120. if anno_dic["category"] not in select_dict["type"]:
    121. continue
    122. x = anno_dic['bbox']['xmin']
    123. y = anno_dic['bbox']['ymin']
    124. width = anno_dic['bbox']['xmax'] - anno_dic['bbox']['xmin']
    125. height = anno_dic['bbox']['ymax'] - anno_dic['bbox']['ymin']
    126. label_key = anno_dic['category']
    127. dataset['annotations'].append({
    128. 'area': width * height,
    129. 'bbox': [x, y, width, height],
    130. 'category_id': label[label_key],
    131. 'id': obj_id,
    132. 'image_id': image_id,
    133. 'iscrowd': 0,
    134. # mask, 矩形是从左上角点按顺时针的四个顶点
    135. 'segmentation': [[x, y, x + width, y, x + width, y + height, x, y + height]]
    136. })
    137. # 每个标注的对象id唯一
    138. obj_id += 1
    139. # 用opencv读取图片,得到图像的宽和高
    140. im = cv2.imread(os.path.join(parent_path, image_path))
    141. #####---------------------------------------------
    142. ##print(image_path) #test other train
    143. prefix = image_path.split("/")[0]
    144. H,W,_ = im.shape
    145. # 添加图像的信息到dataset中
    146. dataset['images'].append({'file_name': image_name,
    147. 'id': image_id,
    148. 'width': W,
    149. 'height': H})
    150. # 保存结果
    151. for phase in ['train', 'val', 'test']:
    152. json_name = os.path.join(parent_path, 'dataset/annotations/{}.json'.format(phase))
    153. with open(json_name, 'w', encoding="utf-8") as f:
    154. if phase == 'train':
    155. json.dump(train_dataset, f, ensure_ascii=False, indent=1)
    156. if phase == 'val':
    157. json.dump(val_dataset, f, ensure_ascii=False, indent=1)
    158. if phase == 'test':
    159. json.dump(test_dataset, f, ensure_ascii=False, indent=1)

    coco_json2yolo_txt(self, class_json)函数:生成路径txt

    第一个框是你的 如下三个文件路径,第二个框是你要生成的txt文件保存路径,可以自己定

    这个地方是yolo源码文件里面的一个路径,可以先看看我后面的yolo数据集文件夹的建立了,再来确认这个路径

    1. def coco_json2yolo_txt(self, class_json):
    2. # COCO 格式的数据集转化为 YOLO 格式的数据集
    3. # --json_path 输入的json文件路径
    4. # --save_path 保存的文件夹名字,默认为当前目录下的labels。
    5. def convert(size, box):
    6. dw = 1. / (size[0])
    7. dh = 1. / (size[1])
    8. x = box[0] + box[2] / 2.0
    9. y = box[1] + box[3] / 2.0
    10. w = box[2]
    11. h = box[3]
    12. # round函数确定(xmin, ymin, xmax, ymax)的小数位数
    13. x = round(x * dw, 6)
    14. w = round(w * dw, 6)
    15. y = round(y * dh, 6)
    16. h = round(h * dh, 6)
    17. return (x, y, w, h)
    18. # class_json = 'train'
    19. json_file = os.path.join(
    20. 'E:/WorkSpace/YOLO/data/data/dataset/annotations/%s.json' % class_json) # COCO Object Instance 类型的标注
    21. #E:/WorkSpace/YOLO/data/data/dataset/annotations/val.json
    22. #print(json_file)
    23. # ana_txt_save_path = 'D:/jinxData/TT100K/data/dataset/annotations/train' # 保存的路径
    24. ana_txt_save_path = os.path.join('E:/WorkSpace/YOLO/data/data/dataset/annotations/', class_json) # 保存的路径
    25. #print(class_json)#val
    26. #print(ana_txt_save_path)#E:/WorkSpace/YOLO/data/data/dataset/annotations\val
    27. data = json.load(open(json_file, 'r'))
    28. if not os.path.exists(ana_txt_save_path):
    29. os.makedirs(ana_txt_save_path)
    30. id_map = {} # coco数据集的id不连续!重新映射一下再输出!
    31. with open(os.path.join(ana_txt_save_path, 'classes.txt'), 'w') as f:
    32. # 写入classes.txt
    33. for i, category in enumerate(data['categories']):
    34. f.write(f"{category['name']}\n")
    35. id_map[category['id']] = i
    36. # print(id_map)
    37. # 这里需要根据自己的需要,更改写入图像相对路径的文件位置。
    38. list_file = open(os.path.join(ana_txt_save_path, '%s.txt' % class_json.format()), 'w')
    39. for img in tqdm(data['images']):
    40. filename = img["file_name"]
    41. img_width = img["width"]
    42. img_height = img["height"]
    43. img_id = img["id"]
    44. head, tail = os.path.splitext(filename)
    45. ana_txt_name = head + ".txt" # 对应的txt名字,与jpg一致
    46. f_txt = open(os.path.join(ana_txt_save_path, ana_txt_name), 'w')
    47. for ann in data['annotations']:
    48. if ann['image_id'] == img_id:
    49. box = convert((img_width, img_height), ann["bbox"])
    50. f_txt.write("%s %s %s %s %s\n" % (id_map[ann["category_id"]], box[0], box[1], box[2], box[3]))
    51. f_txt.close()
    52. #将图片的相对路径写入train2017或val2017的路径 'E:/WorkSpace/YOLO/yolov7-main/yolov7-main/dataset/TT100K/images/'
    53. #list_file.write('%s/%s/%s.jpg\n' % ('E:/WorkSpace/YOLO/data/data/',class_json.format(), head))
    54. list_file.write('%s/%s/%s.jpg\n' % ('E:/WorkSpace/YOLO/yolov7-main/yolov7-main/data/TT100K/images/', class_json.format(), head))
    55. list_file.close()

    以上部分是对数据集处理部分代码的修改,每个函数可以单独运行。且我丢弃了原作者的几个函数。

    三、开始训练

    参考链接:yolov7训练自己的数据集_我把把C的博客-CSDN博客

    3.1数据集准备

    创建目录,把生成的相关文件移动到对应目录,上面说到的这个路径就知道怎么改了

     3.2 创建yaml文件

    1. train: E:/WorkSpace/YOLO/yolov7-main/yolov7-main/data/TT100K/train.txt
    2. val: E:/WorkSpace/YOLO/yolov7-main/yolov7-main/data/TT100K/val.txt
    3. test: E:/WorkSpace/YOLO/yolov7-main/yolov7-main/data/TT100K/test.txt
    4. nc: 42
    5. names: ['i2','i4','i5','il100','il60','il80','io','ip','p10','p11',
    6. 'p12','p19','p23','p26','p27','p3','p5','p6','pg','ph4',
    7. 'ph4.5','pl100','pl120','pl20','pl30','pl40','pl5','pl50','pl60','pl70',
    8. 'pl80','pm20','pm30','pm55','pn','pne','po','pr40','w13','w55',
    9. 'w57','w59'
    10. ]

    3.3 修改yolov7.yaml文件

     3.4 修改训练文件参数

     大功告成,训练中出现的问题,网上都能找到,我就不列举了

  • 相关阅读:
    2022年全球市场抹茶巧克力总体规模、主要生产商、主要地区、产品和应用细分研究报告
    【妙】IP,域名,爬虫,这三个关键词之间的微关系
    java计算机毕业设计科大学生党员之家设计源码+数据库+lw文档+系统
    js语法(es6)
    MySQL-HMA 高可用故障切换
    OC-run loop
    纵目科技冲刺科创板上市:拟募资20亿元,股东阵容强大
    鸿蒙APP开发页面组件之间的属性关系
    [多媒体] 多媒体封装格式 —— MP4 vs MKV
    Flutter组件--SizeBox、FittedBox(子组件超出父组件缩放和对齐)
  • 原文地址:https://blog.csdn.net/qq_42475191/article/details/130901963