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)
我这里根据上边统计的类别的结果重新划分了数据集,根据每个类别类别的总数量按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)
按着原来的划分保存,发现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中的一部分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"]}