赞
踩
搜了好多json改txt的文章,有的看不懂自己用需要改哪里,有的只能单张转换,下面记录一下整个文件夹的json文件改txt文件的方法吧。
labelme对jpg文件进行标注后保存为json格式,json内主要信息如下:
{
"version": "5.1.1",
"flags": {},
"shapes": [ { "label": "SmallCar",
"points": [ [ 2036.0, 548.0 ], [ 2756.0, 1126.0 ] ],
"group_id": null,
"shape_type": "rectangle",
"flags": {}
},....... ],
"imagePath": "118.jpg",
"imageHeight": 1860,
"imageWidth": 2880
}
shapes:保存着bbox的类别和坐标(左上角,右下角);
imagePath:json文件对应的原图名称;
imageHeight:原图的高度;
imageWidth:原图的宽度;
将json文件中的信息提取至txt文件内,代码实现如下:
- import os
- import json
- import numpy as np
- # 类和索引
- CLASSES = ["SmallCar", "BigCar", "NonMotorVeh", "Cyclist", "R", "RG", "RR", "RY", "LR", "Pedestrain", "LY", "G", "B", "FR", "FG"] # 改这
-
-
- def convert(size, box):
- '''
- input:
- size:(width,height);
- box:(x1,x2,y1,y2)
- output:
- (x,y,w,h)
- '''
- dw = 1. / size[0]
- dh = 1. / size[1]
- x = (box[0] + box[1]) / 2.0
- y = (box[2] + box[3]) / 2.0
- w = box[1] - box[0]
- h = box[3] - box[2]
- x = x * dw
- w = w * dw
- y = y * dh
- h = h * dh
- return (x, y, w, h)
-
-
- # json -> txt
- def json2txt(path_json, path_txt):
- with open(path_json, "r") as path_json:
- jsonx = json.load(path_json)
- width = int(jsonx["imageWidth"]) # 原图的宽
- height = int(jsonx["imageHeight"]) # 原图的高
- with open(path_txt, "w+") as ftxt:
- # 遍历每一个bbox对象
- for shape in jsonx["shapes"]:
- obj_cls = str(shape["label"]) # 获取类别
- cls_id = CLASSES.index(obj_cls) # 获取类别索引
- points = np.array(shape["points"]) # 获取(x1,y1,x2,y2)
- x1 = int(points[0][0])
- y1 = int(points[0][1])
- x2 = int(points[1][0])
- y2 = int(points[1][1])
- # (左上角,右下角) -> (中心点,宽高) 归一化
- bb = convert((width, height), (x1, x2, y1, y2))
- ftxt.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + "\n")
-
-
- if __name__ == "__main__":
- # json文件夹 不同的json文件夹记得换路径
- dir_json = "/home/lyn/Desktop/mydatasets/labels/val/"
- # txt文件夹 想让生成的txt文件放哪就改到哪个路径
- dir_txt = "/home/lyn/Desktop/mydatasets/labels/val/"
- if not os.path.exists(dir_txt):
- os.makedirs(dir_txt)
- # 得到所有json文件
- list_json = os.listdir(dir_json)
- # 遍历每一个json文件,转成txt文件
- for cnt, json_name in enumerate(list_json):
- print("cnt=%d,name=%s" % (cnt, json_name))
- path_json = dir_json + json_name
- path_txt = dir_txt + json_name.replace(".json", ".txt")
- # (x1,y1,x2,y2)->(x,y,w,h)
- json2txt(path_json, path_txt)
转换不同文件夹内的json文件只需将文件夹路径传入dir_json;
dir_txt后为生成的txt文件存放位置。
注意CLASSES=[ ]内要放置json文件对应含有的类。
小改一下,源码来自YouOnly_LiveOnce https://www.bilibili.com/read/cv18350780 出处bilibili
方法二:
- import os
- import numpy as np
- import json
- from glob import glob
- import cv2
- from sklearn.model_selection import train_test_split
- from os import getcwd
-
- classes = ["SmallCar", "BigCar", "G", "R", "RG", "Cyclist", "B", "NonMotorVeh"] # 输入json文件内含有的类
- labelme_path = "/home/lyn/Desktop/yolov5-master/datasets/" # 这个文件夹内同时放了jpg文件和json文件,生成的txt文件也会存放其中
- isUseTest = True # 是否创建test集
- # 3.获取待处理文件
- files = glob(labelme_path + "*.json")
- files = [i.replace("\\", "/").split("/")[-1].split(".json")[0] for i in files]
- print(files)
- if isUseTest:
- trainval_files, test_files = train_test_split(files, test_size=0.1, random_state=55)
- else:
- trainval_files = files
- # split
- train_files, val_files = train_test_split(trainval_files, test_size=0.1, random_state=55)
-
-
- def convert(size, box):
- dw = 1. / (size[0])
- dh = 1. / (size[1])
- x = (box[0] + box[1]) / 2.0 - 1
- y = (box[2] + box[3]) / 2.0 - 1
- w = box[1] - box[0]
- h = box[3] - box[2]
- x = x * dw
- w = w * dw
- y = y * dh
- h = h * dh
- return (x, y, w, h)
-
-
- wd = getcwd()
- print(wd)
-
-
- def ChangeToYolo5(files, txt_Name):
- if not os.path.exists('tmp/'):
- os.makedirs('tmp/')
- list_file = open('tmp/%s.txt' % (txt_Name), 'w')
- for json_file_ in files:
- json_filename = labelme_path + json_file_ + ".json"
- imagePath = labelme_path + json_file_ + ".jpg"
- list_file.write('%s/%s\n' % (wd, imagePath))
- out_file = open('%s/%s.txt' % (labelme_path, json_file_), 'w')
- json_file = json.load(open(json_filename, "r", encoding="utf-8"))
- height, width, channels = cv2.imread(labelme_path + json_file_ + ".jpg").shape
- for multi in json_file["shapes"]:
- points = np.array(multi["points"])
- xmin = min(points[:, 0]) if min(points[:, 0]) > 0 else 0
- xmax = max(points[:, 0]) if max(points[:, 0]) > 0 else 0
- ymin = min(points[:, 1]) if min(points[:, 1]) > 0 else 0
- ymax = max(points[:, 1]) if max(points[:, 1]) > 0 else 0
- label = multi["label"]
- if xmax <= xmin:
- pass
- elif ymax <= ymin:
- pass
- else:
- cls_id = classes.index(label)
- b = (float(xmin), float(xmax), float(ymin), float(ymax))
- bb = convert((width, height), b)
- out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
- print(json_filename, xmin, ymin, xmax, ymax, cls_id)
-
-
- ChangeToYolo5(train_files, "train")
- ChangeToYolo5(val_files, "val")
- ChangeToYolo5(test_files, "test")
尝试后发现两个生成的txt文件点的坐标值略微有点区别,具体用哪一个本人水平不够看不出来哪个更好,能跑哪个是哪个吧。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。