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

news2024/11/29 0:37:50

                                                         《临江仙》

                                                        作者:缠中说禅

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

一、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 如下是整体代码

import os
import json
from random import random
import cv2
import shutil
import json
import xml.dom.minidom
from tqdm import tqdm
import argparse


# from jinxSkills.jinx_opencv.datasets_transform.dataset_transform import DataSets_transform


class TT100K2COCO:
    def __init__(self):
        self.original_datasets = 'tt100k'
        self.to_datasets = 'coco'

    def class_statistics(self):
        # os.makedirs('annotations', exist_ok=True)
        # 存放数据的父路径
        parent_path = 'E:/WorkSpace/YOLO/data/data'
        #print(parent_path)
        # 读TT100K原始数据集标注文件
        with open(os.path.join(parent_path, 'annotations.json')) as origin_json:
            origin_dict = json.load(origin_json)
            classes = origin_dict['types']
        # 建立统计每个类别包含的图片的字典
        sta = {}
        for i in classes:
            sta[i] = []

        images_dic = origin_dict['imgs']

        # 记录所有保留的图片
        saved_images = []
        # 遍历TT100K的imgs
        for image_id in images_dic:
            image_element = images_dic[image_id]##
            image_path = 'E:/WorkSpace/YOLO/data/data/'+image_element['path']
            #print(image_path)
            # 添加图像的信息到dataset中
            image_path = image_path.split('/')[-1]
            obj_list = image_element['objects']
            #print(image_path)
            # 遍历每张图片的标注信息
            for anno_dic in obj_list:
                label_key = anno_dic['category']
                # 防止一个图片多次加入一个标签类别
                if image_path not in sta[label_key]:
                    sta[label_key].append(image_path)

        # 只保留包含图片数超过100的类别(重新划分,阈值100可根据需求修改)
        result = {k: v for k, v in sta.items() if len(v) >= 100}

        for i in result:
            #print("the type of {} includes {} images".format(i, len(result[i])))
            saved_images.extend(result[i])

        saved_images = list(set(saved_images))
        #print("total types is {}".format(len(result)))

        type_list = list(result.keys())
        result = {"type": type_list, "details": result, "images": saved_images}
        print(type_list)
        # 保存结果
        json_name = os.path.join(parent_path, 'statistics.json')
        with open(json_name, 'w', encoding="utf-8") as f:
            json.dump(result, f, ensure_ascii=False, indent=1)


    def original_datasets2object_datasets_re(self):
        '''
        重新划分数据集
        :return:
        '''
        # os.makedirs('annotations2', exist_ok=True)
        # 存放数据的父路径
        parent_path = 'E:/WorkSpace/YOLO/data/data/'
        # 读TT100K原始数据集标注文件
        with open(os.path.join(parent_path, 'annotations.json')) as origin_json:
            origin_dict = json.load(origin_json)
        with open(os.path.join(parent_path, 'statistics.json')) as select_json:
            select_dict = json.load(select_json)
            classes = select_dict['type']

        train_dataset = {'info': {}, 'licenses': [], 'categories': [], 'images': [], 'annotations': []}
        val_dataset = {'info': {}, 'licenses': [], 'categories': [], 'images': [], 'annotations': []}
        test_dataset = {'info': {}, 'licenses': [], 'categories': [], 'images': [], 'annotations': []}
        label = {}  # 记录每个标志类别的id
        count = {}  # 记录每个类别的图片数
        owntype_sum = {}
        info = {
            "year": 2021,  # 年份
            "version": '1.0',  # 版本
            "description": "TT100k_to_coco",  # 数据集描述
            "contributor": "Tecent&Tsinghua",  # 提供者
            "url": 'https://cg.cs.tsinghua.edu.cn/traffic-sign/',  # 下载地址
            "date_created": 2021 - 1 - 15
        }
        licenses = {
            "id": 1,
            "name": "null",
            "url": "null",
        }

        train_dataset['info'] = info
        val_dataset['info'] = info
        test_dataset['info'] = info
        train_dataset['licenses'] = licenses
        val_dataset['licenses'] = licenses
        test_dataset['licenses'] = licenses

        # 建立类别和id的关系
        for i, cls in enumerate(classes):
            train_dataset['categories'].append({'id': i, 'name': cls, 'supercategory': 'traffic_sign'})
            val_dataset['categories'].append({'id': i, 'name': cls, 'supercategory': 'traffic_sign'})
            test_dataset['categories'].append({'id': i, 'name': cls, 'supercategory': 'traffic_sign'})
            label[cls] = i
            count[cls] = 0
            owntype_sum[cls] = 0

        images_dic = origin_dict['imgs']#源annotations.json

        obj_id = 1

        # 计算出每个类别共‘包含’的图片数
        for image_id in images_dic:
            image_element = images_dic[image_id]
            image_path = image_element['path']
            image_name = image_path.split('/')[-1]
            #print(image_name)#32770.jpg
            # 在所选的类别图片中
            if image_name not in select_dict['images']:
                continue
            else:
                #加一个赋值图片的语句
                i=0
            # 处理TT100K中的标注信息
            obj_list = image_element['objects']
            # 记录图片中包含最多的实例所属的type
            includes_type = {}
            for anno_dic in obj_list:
                if anno_dic["category"] not in select_dict["type"]:
                    continue
                # print(anno_dic["category"])
                if anno_dic["category"] in includes_type:
                    includes_type[anno_dic["category"]] += 1
                else:
                    includes_type[anno_dic["category"]] = 1
            # print(includes_type)
            own_type = max(includes_type, key=includes_type.get)
            owntype_sum[own_type] += 1

        # TT100K的annotation转换成coco的
        for image_id in images_dic:
            image_element = images_dic[image_id]
            image_path = image_element['path']
            image_name = image_path.split('/')[-1]
            # 在所选的类别图片中
            if image_name not in select_dict['images']:
                continue
            ##print("dealing with {} image".format(image_path))
            # shutil.copy(os.path.join(parent_path,image_path),os.path.join(parent_path,"dataset/JPEGImages"))

            # 处理TT100K中的标注信息
            obj_list = image_element['objects']
            # 记录图片中包含最多的实例所属的type
            includes_type = {}
            for anno_dic in obj_list:
                if anno_dic["category"] not in select_dict["type"]:
                    continue
                # print(anno_dic["category"])
                if anno_dic["category"] in includes_type:
                    includes_type[anno_dic["category"]] += 1
                else:
                    includes_type[anno_dic["category"]] = 1
            # print(includes_type)
            own_type = max(includes_type, key=includes_type.get)
            count[own_type] += 1
            num_rate = count[own_type] / owntype_sum[own_type]

            # 切换dataset的引用对象,从而划分数据集根据每个类别类别的总数量按7:2:1分为了train_set,val_set,test_set。
            # 其中每个图片所属类别根据该图片包含的类别的数量决定(归属为含有类别最多的类别)
           target = 'E:/WorkSpace/YOLO/data/'

            if num_rate < 0.7:
                dataset = train_dataset
                #print(image_path)
                shutil.copyfile(parent_path + image_path, target + '/train/' + image_path.split("/")[1])
            elif num_rate < 0.9:
                dataset = val_dataset
                shutil.copyfile(parent_path + image_path, target + '/val/' + image_path.split("/")[1])
                #print(image_path)
            else:
                #print("dataset=test_dataset")
                dataset = test_dataset
                #print(image_path)
                shutil.copyfile(parent_path + image_path, target + '/test/' + image_path.split("/")[1])

            for anno_dic in obj_list:
                if anno_dic["category"] not in select_dict["type"]:
                    continue
                x = anno_dic['bbox']['xmin']
                y = anno_dic['bbox']['ymin']
                width = anno_dic['bbox']['xmax'] - anno_dic['bbox']['xmin']
                height = anno_dic['bbox']['ymax'] - anno_dic['bbox']['ymin']
                label_key = anno_dic['category']

                dataset['annotations'].append({
                    'area': width * height,
                    'bbox': [x, y, width, height],
                    'category_id': label[label_key],
                    'id': obj_id,
                    'image_id': image_id,
                    'iscrowd': 0,
                    # mask, 矩形是从左上角点按顺时针的四个顶点
                    'segmentation': [[x, y, x + width, y, x + width, y + height, x, y + height]]
                })
                # 每个标注的对象id唯一
                obj_id += 1

            # 用opencv读取图片,得到图像的宽和高
            im = cv2.imread(os.path.join(parent_path, image_path))
            #####---------------------------------------------
            ##print(image_path)  #test  other train
            prefix = image_path.split("/")[0]


            H,W,_ = im.shape
            # 添加图像的信息到dataset中
            dataset['images'].append({'file_name': image_name,
                                      'id': image_id,
                                      'width': W,
                                      'height': H})

        # 保存结果
        for phase in ['train', 'val', 'test']:
            json_name = os.path.join(parent_path, 'dataset/annotations/{}.json'.format(phase))
            with open(json_name, 'w', encoding="utf-8") as f:
                if phase == 'train':
                    shutil.copyfile(parent_path + image_path, target + '/train/' + image_path.split("/")[1])
                    json.dump(train_dataset, f, ensure_ascii=False, indent=1)
                if phase == 'val':
                    json.dump(val_dataset, f, ensure_ascii=False, indent=1)
                if phase == 'test':
                    json.dump(test_dataset, f, ensure_ascii=False, indent=1)

    def coco_json2yolo_txt(self, class_json):
        # COCO 格式的数据集转化为 YOLO 格式的数据集
        # --json_path 输入的json文件路径
        # --save_path 保存的文件夹名字,默认为当前目录下的labels。

        def convert(size, box):
            dw = 1. / (size[0])
            dh = 1. / (size[1])
            x = box[0] + box[2] / 2.0
            y = box[1] + box[3] / 2.0
            w = box[2]
            h = box[3]
            # round函数确定(xmin, ymin, xmax, ymax)的小数位数
            x = round(x * dw, 6)
            w = round(w * dw, 6)
            y = round(y * dh, 6)
            h = round(h * dh, 6)
            return (x, y, w, h)

        # class_json = 'train'
        json_file = os.path.join(
            'E:/WorkSpace/YOLO/data/data/dataset/annotations/%s.json' % class_json)  # COCO Object Instance 类型的标注
        #E:/WorkSpace/YOLO/data/data/dataset/annotations/val.json
        #print(json_file)
        # ana_txt_save_path = 'D:/jinxData/TT100K/data/dataset/annotations/train'  # 保存的路径
        ana_txt_save_path = os.path.join('E:/WorkSpace/YOLO/data/data/dataset/annotations/', class_json)  # 保存的路径
        #print(class_json)#val
        #print(ana_txt_save_path)#E:/WorkSpace/YOLO/data/data/dataset/annotations\val
        data = json.load(open(json_file, 'r'))
        if not os.path.exists(ana_txt_save_path):
            os.makedirs(ana_txt_save_path)

        id_map = {}  # coco数据集的id不连续!重新映射一下再输出!
        with open(os.path.join(ana_txt_save_path, 'classes.txt'), 'w') as f:
            # 写入classes.txt
            for i, category in enumerate(data['categories']):
                f.write(f"{category['name']}\n")
                id_map[category['id']] = i
        # print(id_map)
        # 这里需要根据自己的需要,更改写入图像相对路径的文件位置。
        list_file = open(os.path.join(ana_txt_save_path, '%s.txt' % class_json.format()), 'w')

        for img in tqdm(data['images']):
            filename = img["file_name"]
            img_width = img["width"]
            img_height = img["height"]
            img_id = img["id"]
            head, tail = os.path.splitext(filename)
            ana_txt_name = head + ".txt"  # 对应的txt名字,与jpg一致
            f_txt = open(os.path.join(ana_txt_save_path, ana_txt_name), 'w')
            for ann in data['annotations']:
                if ann['image_id'] == img_id:
                    box = convert((img_width, img_height), ann["bbox"])
                    f_txt.write("%s %s %s %s %s\n" % (id_map[ann["category_id"]], box[0], box[1], box[2], box[3]))
            f_txt.close()
            #将图片的相对路径写入train2017或val2017的路径  'E:/WorkSpace/YOLO/yolov7-main/yolov7-main/dataset/TT100K/images/'
            #list_file.write('%s/%s/%s.jpg\n' % ('E:/WorkSpace/YOLO/data/data/',class_json.format(), head))
            list_file.write('%s/%s/%s.jpg\n' % ('E:/WorkSpace/YOLO/yolov7-main/yolov7-main/data/TT100K/images/', class_json.format(), head))
        list_file.close()

   

if __name__ == '__main__':
    tt100k = TT100K2COCO()
    #tt100k.class_statistics()
    #tt100k.original_datasets2object_datasets_re()
    tt100k.coco_json2yolo_txt('val')
    tt100k.coco_json2yolo_txt('test')
    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文件。

    def class_statistics(self):
        # os.makedirs('annotations', exist_ok=True)
        # 存放数据的父路径
        parent_path = 'E:/WorkSpace/YOLO/data/data'
        #print(parent_path)
        # 读TT100K原始数据集标注文件
        with open(os.path.join(parent_path, 'annotations.json')) as origin_json:
            origin_dict = json.load(origin_json)
            classes = origin_dict['types']
        # 建立统计每个类别包含的图片的字典
        sta = {}
        for i in classes:
            sta[i] = []

        images_dic = origin_dict['imgs']

        # 记录所有保留的图片
        saved_images = []
        # 遍历TT100K的imgs
        for image_id in images_dic:
            image_element = images_dic[image_id]##
            image_path = 'E:/WorkSpace/YOLO/data/data/'+image_element['path']
            #print(image_path)
            # 添加图像的信息到dataset中
            image_path = image_path.split('/')[-1]
            obj_list = image_element['objects']
            #print(image_path)
            # 遍历每张图片的标注信息
            for anno_dic in obj_list:
                label_key = anno_dic['category']
                # 防止一个图片多次加入一个标签类别
                if image_path not in sta[label_key]:
                    sta[label_key].append(image_path)

        # 只保留包含图片数超过100的类别(重新划分,阈值100可根据需求修改)
        result = {k: v for k, v in sta.items() if len(v) >= 100}

        for i in result:
            #print("the type of {} includes {} images".format(i, len(result[i])))
            saved_images.extend(result[i])

        saved_images = list(set(saved_images))
        #print("total types is {}".format(len(result)))

        type_list = list(result.keys())
        result = {"type": type_list, "details": result, "images": saved_images}
        print(type_list)
        # 保存结果
        json_name = os.path.join(parent_path, 'statistics.json')
        with open(json_name, 'w', encoding="utf-8") as f:
            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文件

 

    def original_datasets2object_datasets_re(self):
        '''
        重新划分数据集
        :return:
        '''
        # os.makedirs('annotations2', exist_ok=True)
        # 存放数据的父路径
        parent_path = 'E:/WorkSpace/YOLO/data/data/'
        # 读TT100K原始数据集标注文件
        with open(os.path.join(parent_path, 'annotations.json')) as origin_json:
            origin_dict = json.load(origin_json)
        with open(os.path.join(parent_path, 'statistics.json')) as select_json:
            select_dict = json.load(select_json)
            classes = select_dict['type']

        train_dataset = {'info': {}, 'licenses': [], 'categories': [], 'images': [], 'annotations': []}
        val_dataset = {'info': {}, 'licenses': [], 'categories': [], 'images': [], 'annotations': []}
        test_dataset = {'info': {}, 'licenses': [], 'categories': [], 'images': [], 'annotations': []}
        label = {}  # 记录每个标志类别的id
        count = {}  # 记录每个类别的图片数
        owntype_sum = {}
        info = {
            "year": 2021,  # 年份
            "version": '1.0',  # 版本
            "description": "TT100k_to_coco",  # 数据集描述
            "contributor": "Tecent&Tsinghua",  # 提供者
            "url": 'https://cg.cs.tsinghua.edu.cn/traffic-sign/',  # 下载地址
            "date_created": 2021 - 1 - 15
        }
        licenses = {
            "id": 1,
            "name": "null",
            "url": "null",
        }

        train_dataset['info'] = info
        val_dataset['info'] = info
        test_dataset['info'] = info
        train_dataset['licenses'] = licenses
        val_dataset['licenses'] = licenses
        test_dataset['licenses'] = licenses

        # 建立类别和id的关系
        for i, cls in enumerate(classes):
            train_dataset['categories'].append({'id': i, 'name': cls, 'supercategory': 'traffic_sign'})
            val_dataset['categories'].append({'id': i, 'name': cls, 'supercategory': 'traffic_sign'})
            test_dataset['categories'].append({'id': i, 'name': cls, 'supercategory': 'traffic_sign'})
            label[cls] = i
            count[cls] = 0
            owntype_sum[cls] = 0

        images_dic = origin_dict['imgs']#源annotations.json

        obj_id = 1

        # 计算出每个类别共‘包含’的图片数
        for image_id in images_dic:
            image_element = images_dic[image_id]
            image_path = image_element['path']
            image_name = image_path.split('/')[-1]
            #print(image_name)#32770.jpg
            # 在所选的类别图片中
            if image_name not in select_dict['images']:
                continue
            else:
                #加一个赋值图片的语句
                i=0
            # 处理TT100K中的标注信息
            obj_list = image_element['objects']
            # 记录图片中包含最多的实例所属的type
            includes_type = {}
            for anno_dic in obj_list:
                if anno_dic["category"] not in select_dict["type"]:
                    continue
                # print(anno_dic["category"])
                if anno_dic["category"] in includes_type:
                    includes_type[anno_dic["category"]] += 1
                else:
                    includes_type[anno_dic["category"]] = 1
            # print(includes_type)
            own_type = max(includes_type, key=includes_type.get)
            owntype_sum[own_type] += 1

        # TT100K的annotation转换成coco的
        for image_id in images_dic:
            image_element = images_dic[image_id]
            image_path = image_element['path']
            image_name = image_path.split('/')[-1]
            # 在所选的类别图片中
            if image_name not in select_dict['images']:
                continue
            ##print("dealing with {} image".format(image_path))
            # shutil.copy(os.path.join(parent_path,image_path),os.path.join(parent_path,"dataset/JPEGImages"))

            # 处理TT100K中的标注信息
            obj_list = image_element['objects']
            # 记录图片中包含最多的实例所属的type
            includes_type = {}
            for anno_dic in obj_list:
                if anno_dic["category"] not in select_dict["type"]:
                    continue
                # print(anno_dic["category"])
                if anno_dic["category"] in includes_type:
                    includes_type[anno_dic["category"]] += 1
                else:
                    includes_type[anno_dic["category"]] = 1
            # print(includes_type)
            own_type = max(includes_type, key=includes_type.get)
            count[own_type] += 1
            num_rate = count[own_type] / owntype_sum[own_type]

            # 切换dataset的引用对象,从而划分数据集根据每个类别类别的总数量按7:2:1分为了train_set,val_set,test_set。
            # 其中每个图片所属类别根据该图片包含的类别的数量决定(归属为含有类别最多的类别)
           target = 'E:/WorkSpace/YOLO/data/'

            if num_rate < 0.7:
                dataset = train_dataset
                #print(image_path)
                shutil.copyfile(parent_path + image_path, target + '/train/' + image_path.split("/")[1])
            elif num_rate < 0.9:
                dataset = val_dataset
                shutil.copyfile(parent_path + image_path, target + '/val/' + image_path.split("/")[1])
                #print(image_path)
            else:
                #print("dataset=test_dataset")
                dataset = test_dataset
                #print(image_path)
                shutil.copyfile(parent_path + image_path, target + '/test/' + image_path.split("/")[1])

            for anno_dic in obj_list:
                if anno_dic["category"] not in select_dict["type"]:
                    continue
                x = anno_dic['bbox']['xmin']
                y = anno_dic['bbox']['ymin']
                width = anno_dic['bbox']['xmax'] - anno_dic['bbox']['xmin']
                height = anno_dic['bbox']['ymax'] - anno_dic['bbox']['ymin']
                label_key = anno_dic['category']

                dataset['annotations'].append({
                    'area': width * height,
                    'bbox': [x, y, width, height],
                    'category_id': label[label_key],
                    'id': obj_id,
                    'image_id': image_id,
                    'iscrowd': 0,
                    # mask, 矩形是从左上角点按顺时针的四个顶点
                    'segmentation': [[x, y, x + width, y, x + width, y + height, x, y + height]]
                })
                # 每个标注的对象id唯一
                obj_id += 1

            # 用opencv读取图片,得到图像的宽和高
            im = cv2.imread(os.path.join(parent_path, image_path))
            #####---------------------------------------------
            ##print(image_path)  #test  other train
            prefix = image_path.split("/")[0]


            H,W,_ = im.shape
            # 添加图像的信息到dataset中
            dataset['images'].append({'file_name': image_name,
                                      'id': image_id,
                                      'width': W,
                                      'height': H})

        # 保存结果
        for phase in ['train', 'val', 'test']:
            json_name = os.path.join(parent_path, 'dataset/annotations/{}.json'.format(phase))
            with open(json_name, 'w', encoding="utf-8") as f:
                if phase == 'train':
                    json.dump(train_dataset, f, ensure_ascii=False, indent=1)
                if phase == 'val':
                    json.dump(val_dataset, f, ensure_ascii=False, indent=1)
                if phase == 'test':
                    json.dump(test_dataset, f, ensure_ascii=False, indent=1)

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

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

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

    def coco_json2yolo_txt(self, class_json):
        # COCO 格式的数据集转化为 YOLO 格式的数据集
        # --json_path 输入的json文件路径
        # --save_path 保存的文件夹名字,默认为当前目录下的labels。

        def convert(size, box):
            dw = 1. / (size[0])
            dh = 1. / (size[1])
            x = box[0] + box[2] / 2.0
            y = box[1] + box[3] / 2.0
            w = box[2]
            h = box[3]
            # round函数确定(xmin, ymin, xmax, ymax)的小数位数
            x = round(x * dw, 6)
            w = round(w * dw, 6)
            y = round(y * dh, 6)
            h = round(h * dh, 6)
            return (x, y, w, h)

        # class_json = 'train'
        json_file = os.path.join(
            'E:/WorkSpace/YOLO/data/data/dataset/annotations/%s.json' % class_json)  # COCO Object Instance 类型的标注
        #E:/WorkSpace/YOLO/data/data/dataset/annotations/val.json
        #print(json_file)
        # ana_txt_save_path = 'D:/jinxData/TT100K/data/dataset/annotations/train'  # 保存的路径
        ana_txt_save_path = os.path.join('E:/WorkSpace/YOLO/data/data/dataset/annotations/', class_json)  # 保存的路径
        #print(class_json)#val
        #print(ana_txt_save_path)#E:/WorkSpace/YOLO/data/data/dataset/annotations\val
        data = json.load(open(json_file, 'r'))
        if not os.path.exists(ana_txt_save_path):
            os.makedirs(ana_txt_save_path)

        id_map = {}  # coco数据集的id不连续!重新映射一下再输出!
        with open(os.path.join(ana_txt_save_path, 'classes.txt'), 'w') as f:
            # 写入classes.txt
            for i, category in enumerate(data['categories']):
                f.write(f"{category['name']}\n")
                id_map[category['id']] = i
        # print(id_map)
        # 这里需要根据自己的需要,更改写入图像相对路径的文件位置。
        list_file = open(os.path.join(ana_txt_save_path, '%s.txt' % class_json.format()), 'w')

        for img in tqdm(data['images']):
            filename = img["file_name"]
            img_width = img["width"]
            img_height = img["height"]
            img_id = img["id"]
            head, tail = os.path.splitext(filename)
            ana_txt_name = head + ".txt"  # 对应的txt名字,与jpg一致
            f_txt = open(os.path.join(ana_txt_save_path, ana_txt_name), 'w')
            for ann in data['annotations']:
                if ann['image_id'] == img_id:
                    box = convert((img_width, img_height), ann["bbox"])
                    f_txt.write("%s %s %s %s %s\n" % (id_map[ann["category_id"]], box[0], box[1], box[2], box[3]))
            f_txt.close()
            #将图片的相对路径写入train2017或val2017的路径  'E:/WorkSpace/YOLO/yolov7-main/yolov7-main/dataset/TT100K/images/'
            #list_file.write('%s/%s/%s.jpg\n' % ('E:/WorkSpace/YOLO/data/data/',class_json.format(), head))
            list_file.write('%s/%s/%s.jpg\n' % ('E:/WorkSpace/YOLO/yolov7-main/yolov7-main/data/TT100K/images/', class_json.format(), head))
        list_file.close()

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

三、开始训练

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

3.1数据集准备

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

 3.2 创建yaml文件

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

3.3 修改yolov7.yaml文件

 3.4 修改训练文件参数

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/576616.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【内网穿透】远程访问RabbitMQ服务

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 转载自cpolar内网穿透的文章&#xff1a;无公网IP&…

【C语言】刷题训练营 —— 每日一练

文章目录 前言 BC113 小乐乐定闹钟BC114 小乐乐排电梯BC115 小乐乐与欧几里得BC116 小乐乐改数字BC107 矩阵转置BC117 小乐乐走台阶BC118 小乐乐与序列BC119 小乐乐与字符串BC121 小乐乐学编程BC122 小乐乐算平均分完结 前言 大家好&#xff0c;继续更新专栏 c_牛客&#xff0…

【C++】二叉搜索树Binary Search Tree

Binary Search Tree 二叉搜索树的概念二叉搜索树的操作二叉搜索树的实现查找插入删除 二叉搜索树的应用二叉搜索树的性能分析 二叉搜索树的概念 二叉搜索树又被称为二叉排序树&#xff0c;顾名思义&#xff0c;当我们使用中序遍历时&#xff0c;会得到一个有序的序列。二叉搜索…

进程信号的保存和处理

目录 &#x1f3c6;一、信号的保存 ①信号的捕捉 ②sigset_t ③sigaction &#x1f3c6;二、不可重入函数 &#x1f3c6;三、volatile &#x1f3c6;四、SIGCHLD &#x1f3c6;一、信号的保存 在聊信号保存之前&#xff0c;我们不妨想一个问题&#xff0c;如果把所有信号…

易岸教育:高端篇!公务员面试经验总结!

根据众多应聘者的面试经验&#xff0c;总结出以下几点供应聘者参考&#xff1a; 1、注意着装。 适当提高服装档次。 衣着得体大方&#xff0c;可以提升形象&#xff0c;增强自信。 2、安心。 要以一颗平常心正确对待面试&#xff0c;就要有受挫的心理准备。 即使面试失败了一…

【Python】学习导论:Python 简介

前言&#xff1a;XMind 脑图大纲 一、Python 的发展和演变 1.1 Python 1.0&#xff08;1994年&#xff09; 版本&#xff1a;Python 的第 1 个正式版本典型里程碑&#xff1a;包含了基本的语言特性和标准库 1.2 Python 2.0&#xff08;2000年&#xff09; 版本&#xff1a;Pyt…

XDP入门--通过用户态程序自动加载与卸载eBPF程序字节码到网卡

本文目录 1、测试环境1、eBPF字节码的源代码实现3、用户态应用程度实现简介4、编译与运行5、运行状态验证 通过文章XDP入门–之hello world 我们知道&#xff0c;可以通过iproute2的ip工具向网卡去加载和卸载eBPF程序的字节码。但这个使用起来不太方便。而且在需要网卡恢复正常…

浅析Java 多线程中的锁

前言 随着互联网技术的快速发展&#xff0c;多线程编程已经成为了现今编程领域中必不可少的知识点之一。Java 是一种广泛使用的编程语言&#xff0c;也是一些底层应用程序和高并发应用程序的首选语言。而 Java 提供的多线程编程机制和相关的锁机制&#xff0c;则成为了 Java 开…

SpringBoot 上传图片-指定目录按照日期存储

SpringBoot 上传图片-指定目录按照日期存储 1. 在配置文件中指定文件保存根目录 我用的yaml,用properties也行 file-save-path: D:/upload/2. 文件上传接口 package com.admin.controller.wechat;import cn.hutool.core.lang.UUID; import com.redic.base.Result; import com…

SpringMVC 程序开发

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录 什么是 Spring MVCMVC 定义 怎么学 Spring MVCSpring MVC 创建和连接创建 Spring MVC 项目RequestMapping 注解介绍PostMappi…

二叉搜索树的实现(C语言)

目录 前言&#xff1a; 一&#xff1a;准备工作 (1)需要的头文件 (2)树节点结构体描述 (3)初始化 二&#xff1a;指针 三&#xff1a;插入新节点(建树) (1)生成一个新节点 (2)找插入位置 四&#xff1a;查找和遍历 (1)查找 (2)遍历 五&#xff1a;删除节点 六&…

mysql 主从同步

① 修改 master 配置文件② 新建同步账号③ 创建数据库④ 修改 slave 配置文件⑤ 配置主从关系⑥ 检验主从结果 角色ipmaster192.168.233.100slave1192.168.233.101slave2192.168.233.102 禁用 selinux 跟 firewal l情况下&#xff1a; ① 修改 master 配置文件 vim /etc/my…

NEFU linux实验二

在linux中&#xff0c;家目录又称“home目录”、“主目录”&#xff0c;是用户的宿主目录&#xff0c;通常用来保存用户的文件&#xff0c;可以使用“~”来表示。一个用户登录系统&#xff0c;进入后所处的位置就是“/home”&#xff0c;即家目录&#xff1b;root用户的家目录为…

路径规划算法:基于鸡群优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于鸡群优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于鸡群优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化算法鸡群…

输电线路故障诊断(利用随机森林方法实现二分类和多分类)

1.simunlike仿真系统的建立&#xff08; 运行效果 &#xff1a;输电线路故障诊断_哔哩哔哩_bilibili&#xff09; 2.在仿真系统的基础上获取数据集 分别获取单相接地故障、两相接地故障、两相间短路故障、三相接地故障、三相间短路故障和正常状态下的电流&#xff08;Ia,Ib,I…

一文带你了解MySQL之optimizer trace神器的功效

前言&#xff1a; 对于MySQL 5.6以及之前的版本来说&#xff0c;查询优化器就像是一个黑盒子一样&#xff0c;你只能通过EXPLAIN语句查看到最后优化器决定使用的执行计划&#xff0c;却无法知道它为什么做这个决策。这对于一部分喜欢刨根问底的小伙伴来说简直是灾难&#xff1…

2023年5月14日蓝桥杯c++省赛中级组

选择题讲解 1.)C++中,bool类型的变量占用字节数为 ( )。 A.1B.2 C.3 D.4 答案:A 解析:(C++ 中 bool 类型与 char 类型一样,都需要1 byte。一些其他类型的占用字节数:short:2 byte。int:4 byte。long long:8 byte。double:8 byte。) 2.)以下关于C++结构体的说…

代码随想录二刷 day04 | 链表之 24两两交换链表中的节点 19删除链表的倒数第N个节点 面试题 02.07. 链表相交 142.环形链表II

24. 两两交换链表中的节点 题目链接 解题思路&#xff1a; 先将一些可能会改变的节点保存一下&#xff0c;然后再按照三个步骤就行修改 注意 要使用改变以后节点的指针&#xff08;这个地方一刷的时候没注意到&#xff0c;稀里糊涂的过去了&#xff09; 代码如下&#xff1a;…

【八股】计算机网络-HTTP和HTTPS的区别、HTTPS加密传输原理

计算机网络-HTTP和HTTPS的区别、HTTPS加密传输原理 一、HTTP和HTTPS的基本概念二、HTTP与HTTPS的区别三、HTTPS加密传输原理1. 什么是HTTPS1.1 https诞生的原因1.2 https加密方式1.3.http和https的区别 2. https的工作流程3. 数字证书3.1 什么是数字证书3.2 如何申请数字证书3.…

亚马逊六页纸沟通法,拒绝PPT

亚马逊六页纸沟通管理法&#xff0c;拒绝PPT 使用一种简洁的「结构化备忘录」 内部管理会议沟通&#xff0c;每次不超过六页 趣讲大白话&#xff1a;让沟通更有效 【趣讲信息科技178期】 **************************** 那么“6页备忘录”到底是什么呢&#xff1f; 1. What we d…