【相关知识】
json文件介绍:数据在名称/值对中、数据由逗号分隔、花括号保存对象、方括号保存数组; 数据的书写格式是:名称:值对; JSON 值可以是:数字(整数或浮点数)、字符串(在双引号中)、逻辑值(true 或 false)、数组(在方括号中)、对象(在花括号中)、null
方法 | 实现功能 |
json.dumps | 将python对象序列化为JSON字符串 |
json.loads | 将JSON字符串反序列化为python对象【从字符串中读取】 |
json.dump | 将python对象序列化到文件中 |
json.load | 将文件流中的JSON字符串反序列化为python对象【从文件中读取】 |
读取json的逻辑:导包 => 只读打开文件 => 读取文件
Python读取JSON文件:仔细观察其格式发现JSON其实就是Python中的字典。因此,Python对JSON的读取非常简单,一个JSON文件经过json.load()以后,就变成了Python中的字典。
python读取json文件:用open读取文件,然后进行一个循环,并在每个循环里边用json.loads()把每个json转成字典
读取方式汇总:
jason2txt:
json关键字驱动:
python目录和文件操作★:
python文件路径:
文件目录: ..\是打开上一级目录;
python获取当前目录路径和文件★:用os.getcwd()可以获取当前工作目录的路径,而使用os.path.abspath()可以获取指定路径的绝对路径。os.path.join函数可以用来拼接路径,它可以接受多个参数,每个参数都是一个路径片段,最终会将这些路径片段拼接成一个完整的路径。例如:os.path.join('/home/user', 'Documents', 'file.txt'),最终生成一个完整的路径:/home/user/Documents/file.txt
# print(path) # 打印相对路径 # print(os.path.abspath(path)) # 打印绝对路径
os.listdir函数可以用来获取指定目录下的所有文件名,并将这些文件名存储在一个列表中返回。
在建好的txt文档内进行写入
python处理txt★
读取txt文档:①指定path;②函数open返回一个表示文件的对象,对象存储在f中;其中关键字with在不需要访问文件时将其自动关闭。③读取出的内容以字符串形式保存在变量里。
逐行读取txt文档时发现行间距比读取整个文件时大了很多,因为每一行都有末尾都有一个看不见的换行符,而print语句也会加上换行符。要消除这些多余空白行,可以在print语句中使用line.rstrip()
使用系统关键字with时,open()返回的文本对象只在with代码块内使用。如果要在with代码块之外访问文件的内容,可以在with代码块中将文件各行存储在一个列表中,并在with代码块外使用该列表。
读取文本文件时,python将其中的所有文本都解读为字符串。如果读取的是数字,并要将其作为数值使用,就必须使用函数int()将其转化为整数。或使用float()将其转换为浮点数。
a=c[0:3,:] 前0,1,2行
b = c[0,2:4] 第0行的第2和第3列不包括第4列,因为列下标也是从0开始的
d = c[2:4,2:4] 取中间的2-4行的2-4列
e = c[0,:] 取第0行所有数据
f = c[:,1] 取第1列所有数据
g = c[::2,::2] 两个冒号后面表示步长为2
python中二维列表:二维列表是将其他列表当做列表的元素放在一个列表当中,也就是列表的嵌套。二维列表是一个多维数组,它由多个一维列表组成,每个一维列表可以包含任意数量的元素。而二元列表是一个一维数组,它由两个元素组成,每个元素可以是任意类型的值。
列表后跟两个中括号的含义二元列表li [i] ['key']:li[i]是访问列表li的元素,而li的元素都是字典,用字典名通过其键来访问值。 || 这是二元列表,列表里面还有其他的可以通过关键字或者索引访问的数据结构。 li_1.append(li[i]["key"]) #通过for循环将列表内嵌字典所有的value添加到li_1列表。 || li[index]中的index代表列表第几个内嵌字典,后面紧跟的li['key']代表从列表第几个内嵌字典取出与key相对应的value ||
.extend() 方法用于在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表).append() 方法用于在列表末尾添加新的对象。区别:.extend() 方法可以一次性追加另一个序列中的多个值,而 .append() 方法只能添加一个值。
写入参数:a是不断叠加;w写入,比较好
字典排序
【代码过程】
保留指定小数位:
for point in points:
# 去掉坐标中的“[ ]”符号
point = str(point).replace('[', '').replace(']', '')
# 以逗号隔开两个坐标
point_list = point.split(',')
# 将字符串转换为浮点数
point_list = [float(x) for x in point_list]
# 保留3位小数
point_list = [format(x, '.3f') for x in point_list]
# 将两个坐标拼接成字符串
point = ','.join(point_list)
f.write(point + '\n')
一行搞定:
# 以逗号隔开两个坐标,并将两个坐标都转换成float形式并保留3位小数
point = ','.join(map(lambda x: format(float(x), '.3f'), point.split(',')))
f.write(point + '\n')
在labelme标注工具中,标注circle的时候,会得到两个点,第一个点表示圆心,第二个点表示圆的半径。所以对于标定顺序确定的json文档,转成txt后我只要保留两个circle中的第一个坐标(以点检测为现在要做的第一步实验内容)【写入之前加个判断】
# 将坐标写入txt文档 【所有坐标全部写入】
with open(file_name.replace('.json', '.txt'), 'w') as f:
for point in points:
point = str(point).replace('[', '').replace(']', '') # 字符串
point = ','.join(map(lambda x: format(float(x), '.3f'), point.split(',')))
f.write(point + '\n')
# f.write(str(point) + '\n')
# 将坐标写入txt文档 【删除不需要的行】
with open(file_name.replace('.json', '.txt'), 'w') as f:
for index, point in enumerate(points):
if index == 7 or index == 9:
pass
else:
point = str(point).replace('[', '').replace(']', '') # 字符串
point = ','.join(map(lambda x: format(float(x), '.3f'), point.split(',')))
f.write(point + '\n')
结果查看 done!
但是图像标记的landmark的顺序不是固定的,所以我开始得到的10个点坐标并不是固定的,标记人员各自的顺序不同,所以需要同一txt文档中标记点的坐标位置。
一个JSON文件,它包含了一个版本号、一个空的flags字典和一个shapes列表,shapes列表中包含了多个shape字典,每个shape字典中包含了一个label、一个points列表、一个group_id、一个shape_type和一个flags字典。
从JSON文件中获取shapes键对应的值,即shapes列表,该列表包含了多个shape字典。
创建一个长度为17的空列表,用于存储从shapes列表中获取的points值。
【最终代码】
# -*- coding:utf8 -*-
import os
import json
from pprint import pprint
def json_filelist(jsonpath):
"""获取json文件路径"""
jsons_path = []
json_list = os.listdir(jsonpath)
for json in json_list:
if json.endswith('.json'): # 对文件格式进行判断
jsons_path.append(os.path.join(jsonpath, json))
return jsons_path
def load_json(jsonpath):
# 获取所有jason文件的文件名
# file_list = os.listdir(jsonpath) # 列表(文件名)
# 遍历每个jason文件
# for file_name in jsonpath:
# # 解析jason文件
with open(jsonpath, 'r') as f:
data = json.load(f)
data_save = dict()
for i in range(8):
label = data['shapes'][i]['label']
if label =='4-1' or '4-2':
data_save[label]=data['shapes'][i]['points'][0]
else:
data_save[label] = data['shapes'][i]['points']
data_save = sorted(data_save.items())
savepath= os.path.join('labelstxt',os.path.basename(jsonpath)).replace('.json','.txt')
# print(savepath)
with open(savepath,'w',encoding='utf-8') as f:
for i in range(8):
point = str(data_save[i][1]).replace('[', '').replace(']', '')
f.write(point)
f.write('\n')
if __name__ == '__main__':
jsonpath = json_filelist('labels')
# pprint(jsonpath)
for i in range(len(jsonpath)):
load_json(jsonpath[i])
用之前标定点判定没有报错,但在Lable总数检查的时候发现少了3个点;统计countPoint和countCircle的时候也都没有问题。 =>最后发现是标注里45.json中重复标记,所以一开始标签的选择还是挺重要的,影响后面的读取、标签排序。(没有采取脊柱的位置判定方法,纯标签排序)