• 照片宽 "W": "0.564815",

  • 照片高 "H": "0.587961",

  • 归一化后的x,y值"Point(x,y)": "0.587963,0.522375", *注意:这里是双引号

  • 标签 "Label": "0",

这里的宽和高WH指的是经过 归一化处理 的值,所以无需进行归一化处理,直接遍历所有文件的值去保存就可以啦。(大部分文件宽和高为照片原本的宽和高)

上图是 json文件的属性,在下面提取中 会用到这些属性。

下面直接对代码讲解:

因为由于工作需要我只使用到了图片json文件的点坐标和label,因此只提取了points和label属性,大家根据需要可以对相应内容进行添加。

dir_json和dir_tx就是你json文件所在的路径和txt文件生成的路径。

在最后的for循环中就是遍历生成txt以及txt中的具体内容。

实现 代码

import json
import os
from pathlib import Path # 递归方式
def json2txt(path_json, path_txt):
    with open(path_json, 'r', encoding='gb18030') as path_json:
        jsonx = json.load(path_json)
        filename = path_txt.split(os.sep)[-1]
        with open(path_txt, 'w+') as ftxt:
            for shape in jsonx:
                xy = shape["Point(x,y)"]
                label = shape["Label"]
                w = shape["W"]
                h = shape["H"]
                strxy = ' '
                ftxt.writelines(str(label) + strxy + str(xy) + strxy + str(w) + strxy + str(h) + "\n")
# dir_json = r'E:\Acryl\datapro\jsonfileall\**\**.json'
jpath = Path('/workspace/yolo/data/dataset/f001json/')
dir_txt = '/workspace/yolo/data/dataset/f5/txtfile/'
if not os.path.exists(dir_txt):
    os.makedirs(dir_txt)
# list_json = os.listdir(str('jsonfileall'))
# print(type(list_json))
# for cnt, json_name in enumerate(list_json):
#     print(cnt, json_name)
# 这个方法的作用是将Path对象下的符合pattern(正则表达式、通配符)的所有文件获取到,返回一个生成器,可以通过for遍历或者next去获取详细的文件位置
for p in jpath.rglob("*.json"):
 # print('%s :/ "%s"' % (("file" if os.path.isfile(str(p)) else "dir "), str(p)))
#print(p)
# # 这里p不迭代
# # 找到所有带有路径的json文件
# list_json = os.listdir(str(p))
 # # with open(list_json, 'r', encoding='utf-8') as path_json:
# #     jsonx = json.load(list_json)
# for cnt, json_name in enumerate(list_json):
#     print('cnt=%d,name=%s' % (cnt, json_name))
#     # path_json = dir_json+json_name
#     path_json = jpath + json_name
#     path_txt = dir_txt + json_name.replace('.json', '.txt')
#     print(path_json, path_txt)
#     json2txt(path_json, path_txt)
    path_txt = dir_txt + os.sep + str(p).split(os.sep)[-1].replace('.json', '.txt')
# print(p, path_txt)
    json2txt(p, path_txt)

数据预处理扩展

1.使用pandas库读取文件单一json文件代码(可选择)
#将JSON文件读取为Pandas类型
import pandas as pd
#单一json文件测试
df = pd.read_json('E:\datapro\d1.json')
2.测试单个json文件提取所需要的信息,并写入txt文件(可选择)
import json
person_dict = {}
final_dict = "E:\Acryl\datapro\labels\"
#import json file and load the content in person_dict as a dictionary
with open('E:\Acryl\datapro\d1.json') as f:
    person_dict=json.load(f)
    #get the first list from the json(person_dict)
    for data in person_dict:
            final_dict = final_dict + ("Label: " + data[str('Label')] + "\n")
            final_dict = final_dict + ("Point(x,y):" + data[str('Point(x,y)')] + "\n")
            final_dict = final_dict + ("W: " + data[str('W')] + "\n")
            final_dict = final_dict + ("H: " + data[str('H')] + "\n")
        except:
text_file = open("json_list.txt", "w") # write output as a txt
n = text_file.write(final_dict)
text_file.close()
#import json file and load the content in person_dict as a dictionary with open('E:\Acryl\datapro\d1.json') as f: person_dict=json.load(f) #get the first list from the json(person_dict) for data in person_dict: final_dict =data[str('Label')] +' '+ data[str('Point(x,y)')] +' '+ data[str('W')]+' '+data[str('H')] except: text_file = open("json_list.txt", "w") # write output as a txt n = text_file.write(final_dict) text_file.close() for json_id in fileList: print(json_id) with open('E:/Acryl/datapro/jsonfile/' + json_id, "r", encoding="utf-8") as f: # 打开文件 data = f.read() # 读取文件 #print(data)测试打印所有数据 """首先根据传入的主目录路径,得到里面的子文件夹路径,其中每个子文件夹里面分别保存着若干jpg图片和一个json文件""" def get_dirs(main_dir): list_dirs = [] for root, dirs, files in os.walk(main_dir): for dir in dirs: list_dirs.append(os.path.join(root, dir)) return list_dirs """每个文件夹下面包含若干张jpg图片和一个json文件,根据传入的文件夹路径,得到该文件夹下的所有的jpg文件和json文件。(包含路径)""" def get_file(dir_path): list_jpgs = [] for root, dirs, files in os.walk(dir_path): for file in files: if file.endswith(".jpg"): #过滤得到jpg文件, #print(os.path.join(root, file)) list_jpgs.append(os.path.join(root, file)) if file.endswith(".json"): #过滤得到json文件 json_path = os.path.join(root, file) #json文件只有一个,就不用列表了 return list_jpgs, json_path #得到所有的jpg文件和json文件的列表(包含路径) 从json文件中获取到坐标信息,打开并加载完json文件之后,开始解析json内容, json中的object对应着python中的字典, json中的array对应着python中的列表, 然后无非就是他们的嵌套,一个一个挨着解析就好了。 def get_coordinate(json_path): coordinates = [] with open(json_path, 'rb') as file_json: datas = json.load(file_json) #print(datas['shapes']) #datas的shapes元素是一个列表 for list in datas['shapes']:#逐个遍历datas['shapes']列表中的每个元素,其中每个元素又是一个字典 #print(list['points']) #list字典中的points对应的values值就是坐标信息,而该坐标信息又是两个列表, coordinates.append(list['points']) return coordinates """根据文件夹下面的json文件里面的坐标信息,从文件夹下面的jpg图片截取子图""" if __name__ == '__main__': main_dir = r"F:\tubiao" i = 0 dirs = get_dirs(main_dir)#这一步是得到文件夹下的所有文件夹路径,其中每个文件夹下面又包含若干照片和一个json文件。 for dir in dirs:#针对每个子文件夹里面的图片和json分别进行处理 print(dir) j = 0 #每个文件夹里面的截取的子图保存时从0开始。 list_jpgs, json_path = get_file(dir)#这一步是得到每个子文件夹里面的jpg图片路径名字和json路径名字 coordinates = get_coordinate(json_path)#这一步是根据json文件路径得到接送里面保存的坐标信息, for list_jpg in list_jpgs:#对每个图片进行截图, for coordinate in coordinates:#根据坐标信息截图,有几个坐标信息就截几个图片 #image = cv2.imread(list_jpg) #不能读取中文路径,用imdecode代替 #print(list_jpg) image = cv2.imdecode(np.fromfile(list_jpg, dtype=np.uint8), cv2.IMREAD_COLOR) #image = cv2.cvtColor(image_temp, cv2.COLOR_RGB2BGR) 这个不能加,加上之后截出来的子图保存后颜色都变了。 x1 = int(coordinate[0][0]) #左上角的顶点X y1 = int(coordinate[0][1]) #左上角的顶点Y x2 = int(coordinate[1][0]) #右下角的顶点X y2 = int(coordinate[1][1]) #右下角的顶点Y cropImg = image[y1:y2, x1:x2] #坐标顺序是Y1:Y2, X1:X2,Y在前,X在后。 save_name = str(i) + "_cut" + str(j) + ".jpg" #因为是截子图,所以加了个cut save_path = os.path.join(dir,save_name) j = j + 1 #print(save_path) # cv2.imwrite(save_path, frame) #保存路径中包含中文,不能用imwrite保存,要用下一行的imencode的方法。 ret = cv2.imencode('.jpg', cropImg)[1].tofile(save_path) # [1]表示imencode的第二个返回值,也就是这张图片对应的内存数据 i = i + 1#保证每个文件夹里面截取子图的时候命名不重复
7.python遍历目录下的所有目录和文件, python读取json文件信息, 生成一个list.txt(可选择)
import json import os def readjson(): path = 'E:/Acryl/datapro/jsonfileall/jsonfile/' # 包含所有json文件夹位置 files = os.listdir(path) label_txt = open('E:/Acryl/datapro/jsonfileall/label_txt.txt', mode='w') for file in files: f = open(path + '\\' + file, mode='r', encoding='utf-8') temp = json.loads(f.read()) for temp in temp: json_str = temp[str('Label')] + ' ' + temp[str('Point(x,y)')] + ' ' + temp[str('W')] + ' ' + temp[str('H')] except: json_str = temp["Label"] + ' ' + temp[str("Point(x,y)")]+' '+ temp[str('W')]+' '+temp[str('H')] # 写入txt文件 label_txt.writelines(json_str + '\n') print(json_str) # 打印提取的数据 label_txt.close() if __name__ == '__main__': readjson()

测试数据为三个json文件,json文件同上

if os.path.exists(filename): # 计算 yolo 数据格式所需要的中心点的 相对 x, y 坐标, w,h 的值 x = (t['bbox'][0] + t['bbox'][2]) / 2 / t['image_width'] y = (t['bbox'][1] + t['bbox'][3]) / 2 / t['image_height'] w = (t['bbox'][2] - t['bbox'][0]) / t['image_width'] h = (t['bbox'][3] - t['bbox'][1]) / t['image_height'] fp = open(filename, mode="r+", encoding="utf-8") file_str = str(t['category']) + ' ' + str(round(x, 6)) + ' ' + str(round(y, 6)) + ' ' + str(round(w, 6)) + \ ' ' + str(round(h, 6)) line_data = fp.readlines() if len(line_data) != 0: fp.write('\n' + file_str) else: fp.write(file_str) fp.close() # 不存在则创建文件 else: fp = open(filename, mode="w", encoding="utf-8") fp.close() if __name__ == '__main__': main()
9.自己数据集的批量读取json文件,读取必要信息转为对应的txt文件(YOLO需要的格式)
import os
import numpy as np
import json
def json2txt(path_json, path_txt):
    with open(path_json, 'r', encoding='gb18030') as path_json:
        jsonx = json.load(path_json)
        with open(path_txt, 'w+') as ftxt:
            for shape in jsonx:
                xy = shape["Point(x,y)"]
                label = shape["Label"]
                w = shape["W"]
                h = shape["H"]
                strxy = ' '
                ftxt.writelines(str(label)+ strxy + str(xy) + strxy + str(w)+ strxy + str(h)+"\n")
dir_json = 'E:/Acryl/datapro/jsonfileall/jsonfile/'
dir_txt = 'E:/Acryl/datapro/labels/'
if not os.path.exists(dir_txt):
    os.makedirs(dir_txt)
list_json = os.listdir(dir_json)
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')
    print(path_json, path_txt)
    json2txt(path_json, path_txt)
def file_name(file_dir): for root, dirs, files in os.walk(file_dir): file = open('labellist.txt', 'w+') for f in files: # print(os.path.join(path1,f)) i = (os.path.join(path1, f)) file.write( i + '\n') file.close() if __name__ == '__main__': file_name('/workspace/yolo/data/dataset/f001json')

labellist.txt

12.批量修改处理txt文件内容

批量修改txt文件,在做YOLO项目时,会需要将文本文件中的某部分内容进行批量替换和修改,所以编写了python程序批量替换所有文本文件中特定部分的内容。

import re
import os
# 38 labels  
def reset():
  path='/workspace/yolo/data/dataset/test/'
  #path = "/workspace/yolo/data/dataset/labels0208/"
  filelist = os.listdir(path)  # 该文件夹下所有文件(包括文件夹)
  for files in filelist: # 遍历所有文件
    i = i + 1
    Olddir = os.path.join(path,files); # 原来的文件路径
    if os.path.isdir(Olddir):
      continue;
    filename = os.path.splitext(files)[0];
    filetype = os.path.splitext(files)[1];
    filePath = path+filename+filetype
    #这里会把所有0->1 
    alter(filePath,"0","1")
def alter(file,old_str,new_str):
  with open(file,"r",encoding="utf-8") as f1,open("%s.bak"% file,"w",encoding="utf-8") as f2:
    for line in f1:
      if old_str in line:
        line = line.replace(old_str,new_str)
      f2.write(line)
  os.remove(file)
  os.rename("%s.bak" % file,file)
reset()
Created on 2023.02 @author: Elena # coding=utf-8 import os path = path='/workspace/yolo/data/dataset/test' def listfiles(dirpath): filelist = [] for root, dirs, files in os.walk(dirpath): for fileObj in files: filelist.append(os.path.join(root, fileObj)) return filelist def txt_modify(files): for file in files: label_path = os.path.join(path, file) with open(label_path, 'r+') as f: lines = f.readlines() for line in lines: # e.g.'Bus' is the new one, Truck is the old one f.seek(0) f.truncate() f.write(line.replace('Truck', 'Bus')) # f.write(line.replace('dog', 'cat').replace('man', 'boy')) # 多个内容的替换 f.close() def main(): filelist = listfiles(path) for fileobj in filelist: f = open(fileobj, 'r+') lines = f.readlines() f.seek(0) f.truncate() for line in lines: f.write(line.replace('2 ', '3 ')) f.close() if __name__ == main(): main()

方法3:处理yolo已经转换好的标签数修改

import os
import re
#path = '/workspace/yolo/data/dataset/testjson2txt/1/' 
path='/workspace/yolo/data/dataset/labels0208/'
files = []
for file in os.listdir(path):
    if file.endswith(".txt"):
        files.append(path+file)
for file in files:
    with open(file, 'r') as f:
        new_data = re.sub('^12', '1', f.read(), flags=re.MULTILINE)    # 将列中的12替换为1
        print("Down")
    with open(file, 'w') as f:
        f.write(new_data)

第四篇—json标签(labelme)转txt标签(YOLOv5专题) - 哔哩哔哩 (bilibili.com)

YOLOV5——将 json 格式的标注数据转化为 YOLO 需要的 txt 格式 - yx啦啦啦 - 博客园 (cnblogs.com)

1、 YOLO 动物目标检测 数据集 ,真实场景的高质量图片数据,数据场景丰富,图片格式为jpg,共16100张图片,分为训练集和验证集。 2、使用lableimg标注软件标注,标注框质量高,标签格式为 json 格式,可以直接用于 YOLO 系列的目标检测。 3、 数据集 详情展示和更多 数据集 下载:https://blog.csdn.net/m0_64879847/article/details/132301975 1) 文件 夹目录下有 json 格式数据和jpg数据,读取 json 数据时会报错 解决方法:增加 json 文件 后缀判断 for json _name in json _names: if json _name[-4:]==' json ': 2)pandas数据用append增加行无效 解决方法:需要重新对pd进行赋值更新 label=label.append(new_label,ignore_index=True) 3) json 数据坐标存在缺失,本应有四个值
在参加许多目标检测比赛时,为了能够获得合理的评价结果,官方往往是将已经打好标签的 数据集 事先划分好训练集与测试集,将训练集和测试集的标签分别存放在 json 文件 。以百度飞桨平台第17届全国大学生智能汽车竞赛百度创意组 数据集 为例,我们将学习如何将 json 格式的 数据集 标签 化为有效的 txt 文件 。 分析 json 格式标签 了解 json 文件 格式,详细请参考这篇博客: Json
好的,您想将大量的 JSON 文件 换成 TXT 格式,以便于使用 YOLO 目标检测算法进行训练和测试。我可以提供以下几种方法: 1. 使用Python编写脚本,将 JSON 文件 中的数据解析出来,并 换为 YOLO 所需 TXT 格式。您可以使用Python的 json 库读取 JSON 文件 ,然后将其 换为 YOLO 格式的 TXT 文件 。 2. 使用在线 换工具,将 JSON 文件 上传到该工具中,然后选择将其 换为 YOLO 格式的 TXT 文件 。您可以搜索“ JSON to YOLO txt converter”来寻找在线 换工具。 3. 使用专业的 数据处理 软件,如LabelImg或LabelBox,将 JSON 文件 打开,然后将其 换为 YOLO 格式的 TXT 文件 。这些软件都提供了将 JSON 文件 换为 TXT 文件 的功能。 请注意, JSON 文件 TXT 格式时,需要保证数据格式的正确性和完整性,以避免在训练和测试时出现错误和偏差。