首页 > 编程语言 >【python基础】eval的使用

【python基础】eval的使用

时间:2023-04-01 12:02:12浏览次数:62  
标签:box return python pts 基础 len points eval data

前言

开发的时候,遇到一个标注的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')

具体地

【python基础】eval的使用_json

【python基础】eval的使用_Code_02

>>> 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

【python基础】eval的使用_json

【python基础】eval的使用_Code_02

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函数 - 概念、用法、注意事项


标签:box,return,python,pts,基础,len,points,eval,data
From: https://blog.51cto.com/u_15711436/6163465

相关文章