TT100K数据集转换成coco格式,并重新划分

TT100K数据集转换成coco格式,并重新划分

统计每个类别

import os
import json

os.makedirs('annotations',exist_ok=True)
#存放数据的父路径
parent_path = '/path/to/your/TT100K/data'

#读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=image_element['path']
    
    # 添加图像的信息到dataset中
    image_path=image_path.split('/')[-1]
    obj_list=image_element['objects']

    #遍历每张图片的标注信息
    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的类别
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, 'annotations/statistics.json')
with open(json_name, 'w',encoding="utf-8") as f:
    json.dump(result, f,ensure_ascii=False,indent=1)

转换成coco格式

我这里根据上边统计的类别的结果重新划分了数据集,根据每个类别类别的总数量按7:2:1分为了train_set,val_set,test_set。其中每个图片所属类别根据该图片包含的类别的数量决定(归属为含有类别最多的类别)

import os
import cv2
import json
import shutil

os.makedirs('dataset/annotations',exist_ok=True)
#存放数据的父路径
parent_path = '/path/to/your/TT100K/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,'annotations/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']

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]
    #在所选的类别图片中
    if image_name not in select_dict['images']:
        continue

    #处理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的引用对象,从而划分数据集
    if num_rate<0.7:
        dataset =train_dataset
    elif num_rate<0.9:
        dataset=val_dataset
    else :
        print("dataset=test_dataset")
        dataset=test_dataset
    
    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(image_path)
    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格式

按着原来的划分保存,发现221类中Train中居然好多类别没有标志信息。所以,这种并不合适。

import os
import cv2
import json

os.makedirs('annotations',exist_ok=True)
#存放数据的父路径
parent_path = '/path/to/your/TT100K/data'

#读TT100K原始数据集标注文件
with open(os.path.join(parent_path,'annotations.json')) as origin_json:
    origin_dict = json.load(origin_json)
    classes = origin_dict['types']

train_dataset = {'info':{},'licenses':[],'categories': [],'images': [] , 'annotations': []}
val_dataset = {'info':{},'licenses':[],'categories': [],'images': [] , 'annotations': []}
test_dataset = {'info':{},'licenses':[],'categories': [],'images': [] , 'annotations': []}
label={}

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

images_dic = origin_dict['imgs']

obj_id=1

#TT100K的annotation转换成coco的
for image_id in images_dic:
    image_element=images_dic[image_id]
    image_path=image_element['path']
    
    # 用opencv读取图片,得到图像的宽和高
    im = cv2.imread(image_path)
    H, W, _ = im.shape

    
    # 切换dataset的引用对象,从而划分数据集
    if 'train' in image_path:
            dataset = train_dataset
    elif 'test' in image_path:
            dataset = val_dataset
    else:
        dataset = test_dataset
    
    # 添加图像的信息到dataset中
    image_path=image_path.split('/')[-1]
    dataset['images'].append({'file_name': image_path,
                                'id': image_id,
                                'width': W,
                                'height': H})
    obj_list=image_element['objects']

    for anno_dic in obj_list:
        
        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

# 保存结果
for phase in ['train','val','test']:
    json_name = os.path.join(parent_path, '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)

TT100K中的一些标注示例

文件太大了,拿出TT100K中的一部分annotations,字典中的内容都包含全了。

{"imgs": {
    "32770": {"path": "other/32770.jpg", "objects": [], "id": 32770},
    "32773": {"path": "test/32773.jpg", 
        "objects": [
        {"category": "ph2", "bbox": {"xmin": 924.0, "ymin": 1132.0, "ymax": 1177.3333, "xmax": 966.6667}, 
        "ellipse_org": [[942.725, 1132.14], [926.19, 1144.18], [922.884, 1156.61], [931.746, 1173.02], [949.471, 1174.07], [959.921, 1169.58], [962.037, 1142.72]],
        "ellipse": [[943.6439208984375, 1154.060791015625], [41.572391510009766, 45.09551239013672], 36.37429428100586]}, 
        {"category": "p11", "bbox": {"xmin": 970.667, "ymin": 1128.0, "ymax": 1170.6667, "xmax": 1013.3333}, 
        "ellipse_org": [[997.385, 1130.51], [977.584, 1137.36], [974.222, 1161.52], [990.286, 1170.61], [1012.7, 1157.41]], 
        "ellipse": [[992.5154418945312, 1149.9034423828125], [39.68983840942383, 43.2476692199707], 66.92964172363281]}, 
        {"category": "pl5", "bbox": {"xmin": 1146.67, "ymin": 1108.0, "ymax": 1150.6667, "xmax": 1190.6733000000002}, 
        "ellipse_org": [[1170.5, 1110.58], [1151.81, 1121.04], [1155.43, 1148.58], [1176.6, 1150.32], [1190.93, 1125.4]], 
        "ellipse": [[1168.935546875, 1130.9200439453125], [40.40793991088867, 44.34447479248047], 53.05292892456055]}], "id": 32773}, 
    "8": {"path": "other/8.jpg", "objects": [], "id": 8}, 
    "65547": {"path": "other/65547.jpg", "objects": [], "id": 65547}, 
    "2": {"path": "test/2.jpg", "objects": [{"category": "pne", "bbox": {"xmin": 489.6, "ymin": 993.6, "ymax": 1010.4, "xmax": 507.20000000000005}, 
        "ellipse_org": [[498.899, 995.698], [505.703, 1004.15], [498.899, 1010.06], [492.496, 1003.3], [494.497, 1008.55], [494.1, 998.1]], 
        "ellipse": [[498.7543029785156, 1002.3943481445312], [12.916229248046875, 15.343103408813477], 20.536766052246094]}, 
        {"category": "pb", "bbox": {"xmin": 1465.6, "ymin": 775.2, "ymax": 823.2, "xmax": 1510.3999999999999}, 
        "ellipse_org": [[1486.13, 776.471], [1508.96, 800.14], [1486.83, 821.849], [1466.11, 802.661], [1486.13, 776.471]], 
        "ellipse": [[1486.7872314453125, 798.53955078125], [42.06432342529297, 45.424739837646484], 161.0270233154297]}, 
        {"category": "il60", "bbox": {"xmin": 1296.8, "ymin": 769.6, "ymax": 822.4, "xmax": 1344.0}, 
        "ellipse_org": [[1320.18, 770.724], [1344.38, 797.843], [1319.57, 820.339], [1297.07, 796.61], [1320.18, 770.724]], 
        "ellipse": [[1320.454833984375, 795.0762939453125], [46.60488510131836, 50.64521408081055], 159.8419189453125]}, 
        {"category": "pl80", "bbox": {"xmin": 1207.2, "ymin": 769.6, "ymax": 820.8000000000001, "xmax": 1259.2}, 
        "ellipse_org": [[1234.93, 771.065], [1257.8, 794.684], [1234.18, 818.901], [1209.67, 796.777], [1216.1, 810.081], [1214.45, 780.482], [1253.77, 780.035]], 
        "ellipse": [[1233.2791748046875, 794.2261352539062], [47.03112030029297, 48.21159362792969], 92.2869873046875]},
        {"category": "il70", "bbox": {"xmin": 1056.8, "ymin": 772.8, "ymax": 821.5999999999999, "xmax": 1104.8}, 
        "ellipse_org": [[1080.48, 773.219], [1104.84, 798.148], [1078.35, 821.083], [1056.7, 796.581], [1096.86, 778.776], [1063.96, 779.345]], 
        "ellipse": [[1079.98828125, 796.7401123046875], [48.33481216430664, 48.59633255004883], 32.45444107055664]}, 
        {"category": "pl100", "bbox": {"xmin": 965.6, "ymin": 771.2, "ymax": 822.4000000000001, "xmax": 1017.6}, 
        "ellipse_org": [[992.607, 773.456], [1016.23, 798.122], [990.963, 820.994], [968.839, 798.421], [971.981, 809.931], [973.323, 782.426]], 
        "ellipse": [[991.9072265625, 796.5220947265625], [46.99789047241211, 48.43968963623047], 72.09580993652344]}, 
        {"category": "il80", "bbox": {"xmin": 844.8, "ymin": 776.8, "ymax": 826.4, "xmax": 893.5999999999999}, 
        "ellipse_org": [[867.583, 777.713], [892.33, 802.605], [868.017, 826.194], [844.284, 801.447], [847.902, 816.064], [848.046, 787.843]], 
        "ellipse": [[867.6563110351562, 801.4813232421875], [48.00596237182617, 50.005287170410156], 34.71076965332031]}, 
        {"category": "pl100", "bbox": {"xmin": 757.6, "ymin": 779.2, "ymax": 831.2, "xmax": 807.2}, 
        "ellipse_org": [[781.487, 781.335], [805.918, 805.159], [781.032, 828.68], [758.725, 805.766], [766.768, 786.95], [799.545, 820.182]], 
        "ellipse": [[781.3561401367188, 804.3736572265625], [46.509883880615234, 47.53220748901367], 136.26280212402344]}], "id": 2}, 
    "98318": {"path": "test/98318.jpg", "objects": [{"category": "po", "bbox": {"xmin": 1594.67, "ymin": 985.333, "ymax": 1026.6667, "xmax": 1636.0}, 
        "ellipse_org": [[1617.31, 986.408], [1603.07, 991.424], [1597.41, 1002.75], [1603.07, 1017.8], [1616.83, 1023.79], [1634.95, 1009.71], [1630.27, 993.042], [1603.26, 1019.9]], 
        "ellipse": [[1615.67822265625, 1004.5797729492188], [36.9547119140625, 37.54513931274414], 110.10639953613281]}, 
        {"category": "w55", "bbox": {"xmin": 1278.67, "ymin": 989.333, "ymax": 1008.0, "xmax": 1301.3333}, "polygon": [[1291.49, 989.534], [1279.22, 1008.97], [1302.09, 1008.82]]}, 
        {"category": "pl40", "bbox": {"xmin": 1284.0, "ymin": 1009.33, "ymax": 1028.0, "xmax": 1302.6667}, 
        "ellipse_org": [[1292.72, 1009.42], [1285.56, 1013.15], [1285.12, 1021.55], [1292.2, 1026.02], [1297.47, 1023.82], [1300.25, 1019.58], [1297.33, 1011.4], [1291.18, 1010.99], [1299.91, 1017.82]], 
        "ellipse": [[1291.8165283203125, 1017.4920654296875], [15.608173370361328, 16.49311637878418], 4.2683329582214355]}], "id": 98318}, 
    "65551": {"path": "other/65551.jpg", "objects": [], "id": 65551}, 
    "65552": {"path": "other/65552.jpg", "objects": [], "id": 65552}, 
    "10926": {"path": "train/10926.jpg", "objects": [{"category": "pn", "bbox": {"xmin": 1126.37, "ymin": 991.542, "ymax": 1002.9851, "xmax": 1137.8084999999999}, 
        "ellipse_org": [[1136.35, 993.95], [1127.25, 995.1], [1129.05, 1002.1], [1132.6, 1002.95], [1136.95, 1000.0]], "ellipse": [[1131.77197265625, 997.223876953125], [9.32163143157959, 12.719460487365723], 68.103515625]}, 
        {"category": "pl80", "bbox": {"xmin": 1172.14, "ymin": 982.089, "ymax": 999.5020000000001, "xmax": 1190.0498},
        "ellipse_org": [[1186.12, 984.395], [1173.19, 989.232], [1177.72, 999.16], [1182.51, 1000.03], [1188.82, 992.897], [1179.15, 984.14]], 
        "ellipse": [[1180.553955078125, 991.4905395507812], [15.228023529052734, 17.70697593688965], 33.04566192626953]}], "id": 10926}},
"types": ["i1", "i10", "i11", "i12", "i13", "i14", "i15", "i2", "i3", "i4", "i5", "il100", "il110", "il50", "il60", "il70", "il80", "il90", "io", "ip", "p1", "p10", "p11", "p12", "p13", "p14", "p15", "p16", "p17", "p18", "p19", "p2", "p20", "p21", "p22", "p23", "p24", "p25", "p26", "p27", "p28", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "pa10", "pa12", "pa13", "pa14", "pa8", "pb", "pc", "pg", "ph1.5", "ph2", "ph2.1", "ph2.2", "ph2.4", "ph2.5", "ph2.8", "ph2.9", "ph3", "ph3.2", "ph3.5", "ph3.8", "ph4", "ph4.2", "ph4.3", "ph4.5", "ph4.8", "ph5", "ph5.3", "ph5.5", "pl10", "pl100", "pl110", "pl120", "pl15", "pl20", "pl25", "pl30", "pl35", "pl40", "pl5", "pl50", "pl60", "pl65", "pl70", "pl80", "pl90", "pm10", "pm13", "pm15", "pm1.5", "pm2", "pm20", "pm25", "pm30", "pm35", "pm40", "pm46", "pm5", "pm50", "pm55", "pm8", "pn", "pne", "po", "pr10", "pr100", "pr20", "pr30", "pr40", "pr45", "pr50", "pr60", "pr70", "pr80", "ps", "pw2", "pw2.5", "pw3", "pw3.2", "pw3.5", "pw4", "pw4.2", "pw4.5", "w1", "w10", "w12", "w13", "w16", "w18", "w20", "w21", "w22", "w24", "w28", "w3", "w30", "w31", "w32", "w34", "w35", "w37", "w38", "w41", "w42", "w43", "w44", "w45", "w46", "w47", "w48", "w49", "w5", "w50", "w55", "w56", "w57", "w58", "w59", "w60", "w62", "w63", "w66", "w8", "wo", "i6", "i7", "i8", "i9", "ilx", "p29", "w29", "w33", "w36", "w39", "w4", "w40", "w51", "w52", "w53", "w54", "w6", "w61", "w64", "w65", "w67", "w7", "w9", "pax", "pd", "pe", "phx", "plx", "pmx", "pnl", "prx", "pwx", "w11", "w14", "w15", "w17", "w19", "w2", "w23", "w25", "w26", "w27", "pl0", "pl4", "pl3", "pm2.5", "ph4.4", "pn40", "ph3.3", "ph2.6"]}

你可能感兴趣的:(数据集处理,python,cv,深度学习)