前言
开发的时候,遇到一个标注的json文件中多边形的框的表示,一时忘记不知道如何解析,此处主要使用eval函数,故记录之。
json文件多边形框的描述
"result": [
{
"tagtype": "circle_green",
"obstructed": false,
"labelId": 1,
"data": "[[\"M\",475.7550000000001,362.453],[\"L\",476.69799999999987,383.6790000000001],[\"L\",485.18899999999985,383.2080000000001],[\"L\",484.7170000000001,361.981],[\"Z\"]]"
},
{
"tagtype": "circle_green",
"obstructed": false,
"labelId": 2,
"data": "[[\"M\",561.1320000000001,361.509],[\"L\",562.547,383.2080000000001],[\"L\",570.5659999999998,382.7360000000001],[\"L\",569.623,361.038],[\"Z\"]]"
}
]
其中,
bbox是xywh格式的;
带mlz的是由点组成的线;
是否有z代表是否是闭合图形;
有的是末尾有两个z,和一个z表示的意思一样
解析
def parse_data(data):
if isinstance(data, str):
data = eval(data)
assert isinstance(data, list)
if isinstance(data[0], list):
pts = []
for i, d in enumerate(data):
if d[0] != 'Z':
pts.append(d[1:]) # remove 'M'
if len(pts) == 1:
return pts[0], 'point'
if data[-1][0] == 'Z':
return pts, 'area'
return pts, 'line'
else:
if len(data) == 4:
return data, 'bbox' #xywh
else:
warnings.warn('3d bbox not supported yet')
具体地
>>> a=eval("[[\"M\",560.9090000000001,361.818],[\"L\",569.6970000000001,361.818],[\"L\",569.6970000000001,383.3330000000001],[\"L\",561.5149999999999,383.9390000000001],[\"Z\"]]")
>>> a[0]
['M', 560.9090000000001, 361.818]
>>> len(a)
5
>>> a[4]
['Z']
>>> b=[]
>>> b.append(a[0][1:])
>>> b.append(a[1][1:])
>>> b
[[560.9090000000001, 361.818], [569.6970000000001, 361.818]]
>>> b.append(a[3][1:])
>>> b.append(a[2][1:])
>>> b
[[560.9090000000001, 361.818], [569.6970000000001, 361.818], [561.5149999999999, 383.9390000000001], [569.6970000000001, 383.3330000000001]]
View Code
code: json2label.py
import argparse
import json
import os
import os.path as osp
json_dir = "./"
imgw = 1280
imgh = 720
imgsz = imgw, imgh
tfl_label = {'circle_green':0, 'circle_red':1, 'circle_yellow':2, 'left_green':3, 'left_red':4, 'left_yellow':5, 'nomotor_green':6, 'nomotor_red':7, 'nomotor_yellow':8, 'off':9}
def get_bbox(size, box):
# Convert xyxy box to YOLOv5 xywh box
dw = 1. / size[0]
dh = 1. / size[1]
xc = (box[0] + box[2])*0.5*dw
yc = (box[1] + box[3])*0.5*dh
w = (box[2]-box[0])*dw
h = (box[3]-box[1])*dh
return xc, yc, w, h
def get_minrect(points, size):
len_pts = len(points)
x_min = size[0] # image width
y_min = size[1] # image height
x_max = 0
y_max = 0
for i in range(len_pts):
# print("points: ", points)
if points[i][0] < x_min:
x_min = points[i][0]
if points[i][1] < y_min:
y_min = points[i][1]
if points[i][0] > x_max:
x_max = points[i][0]
if points[i][1] > y_max:
y_max = points[i][1]
return x_min, y_min, x_max, y_max
def parse_data(data):
if isinstance(data, str):
data = eval(data)
assert isinstance(data, list)
if isinstance(data[0], list):
pts = []
for i, d in enumerate(data):
if d[0] != 'Z':
pts.append(d[1:]) # remove 'M'
if len(pts) == 1:
return pts[0], 'point'
if data[-1][0] == 'Z':
return pts, 'area'
return pts, 'line'
else:
if len(data) == 4:
return data, 'bbox'
else:
warnings.warn('3d bbox not supported yet')
def parse_json(filename, dataset):
labeldir = filename.split("_")[0]
# print("labeldir: ", labeldir)
if not osp.exists(osp.join(json_dir, labeldir)):
os.mkdir(labeldir)
k=0
for data in dataset:
# k+=1
# if k==2:
# break
# data = dataset[i]
count = data['label_count']
imagename = data['file_obj']
name = osp.split(imagename)[-1].replace('png', 'txt')
labelname = osp.join(labeldir, name)
# print('labelname: ', labelname)
labelfile = open(labelname, 'w+')
for res in data['result']:
tagtype = res['tagtype']
points = parse_data(res['data'])[0]
# print('points: ', points)
if len(points)<4:
print('labelname: ', labelname)
continue
classid = tfl_label[tagtype]
rect = get_minrect(points, imgsz)
bbox = get_bbox(imgsz, rect)
if bbox[2]*imgsz[0] < 5:
print('this image tfl width less than 5:{}\t{}\t{}\n'.format(name, bbox[2]*imgsz[0], bbox[3]*imgsz[1]))
if bbox[3]*imgsz[1] < 12:
print('this image tfl height less than 10:{}\t{}\t{}\n'.format(name, bbox[2]*imgsz[0], bbox[3]*imgsz[1]))
info = f"{classid} {' '.join(f'{x:.6f}' for x in bbox)}\n"
labelfile.write(info)
labelfile.close()
def main():
jsonfiles = os.listdir(json_dir)
for i in range(0, len(jsonfiles)):
path = os.path.join(json_dir, jsonfiles[i])
# print("path: ", jsonfiles[i])
if os.path.isfile(path) and path.endswith('json'):
dataset = json.load(open(path))
num = len(dataset)
# print("dataset number: ", num)
parse_json(jsonfiles[i], dataset)
if __name__ == '__main__':
main()
View Code
参考
1. Python:eval函数 - 概念、用法、注意事项;
完