json是一种轻量级的数据交换格式,如图为在线解析之后的json图。
解读数据结构:JSON数据就是一段字符串,只不过有不同意义的分隔符将其分割开来而已,我们看上面的符号,里面有[] ,{}等符号,其中
1 []中括号代表的是一个数组;
2 {}大括号代表的是一个对象
3 双引号“”表示的是属性值
4 冒号:代表的是前后之间的关系,冒号前面是属性的名称,后面是属性的值,这个值可以是基本数据类型,也可以是引用数据类型。
Python3 中可以使用 json 模块来对 JSON 数据进行编解码,主要包含了下面4个操作函数,如图。
在json的编解码过程中,python 的原始类型与JSON类型会相互转换,如图
实例
import json # 调用json模块data = { 'name': 'yzzzhhh', 'age': 23, 'address': {'province': 'yunnan', 'city': 'yuxi'}}# 将 Python 字典类型转换为 JSON 对象json_str = json.dumps(data)# 将 JSON 对象类型转换为 Python 字典user_dic = json.loads(json_str)# 将 Python 字典直接输出到json文件with open('yzh.json', 'w', encoding='utf-8') as f: json.dump(user_dic, f, ensure_ascii=False, indent=4)# 将类文件对象中的JSON字符串直接转换成 Python 字典with open('yzh.json', 'r', encoding='utf-8') as f: ret_dic = json.load(f) print(type(ret_dic)) # 结果 <class 'dict'> print(ret_dic['name']) # 结果yzzzhhh
xml解析
XML是可扩展标记语言(Extensible Markup Language)的缩写。其是一种结构化、层级化的数据格式,最适合体现XML的数据结构就是树。您可以创建内容,然后使用限定标记标记它,从而使每个单词、短语或块成为可识别、可分类的信息。其是各种应用程序之间进行数据传输的最常用的工具。
解析XML有很多的Python包,SAX,DOM,ElementTree等等。这里介绍目前最好用也是最快速的方法最流行的方法xml.etree.ElementTree(以下简称ET),其是一个用于处理树结构的 Python 包,它可以用于处理任何树结构的数据
ET有两种实现。一个是纯Python实现的xml.etree.ElementTree,另一个是速度更快的C语言实现xml.etree.cElementTree。请记住始终使用C语言实现,因为它的速度要快很多,而且内存消耗也要少很多。一般python3版本以上都有,但是如果Python版本中没有cElementTree所需的加速模块,你可以这样导入模块:
try: import xml.etree.cElementTree as ETexcept ImportError: import xml.etree.ElementTree as ET
ET提供了两个对象:ElementTree调用parse将整个XML文档转化为树,Element则代表着树上的单个节点。
下面基于如下xml数据进行演示使用方法并做聚类:
主要的方法:
glob.glob("{}/*xml".format(path)) 遍历xml文件
ET.parse(xml_file)解析文件为树。
tree.findtext("./size/height")查找元素的值
tree.iter("object")遍历一个xml里的所有object
obj.findtext("bndbox/xmin")查找每一个object里元素的值
其他一些方法:
当要获取属性时,用attrib方法
当要获取节点值时,用text方法
当要获取节点名称时,用tag方法
# root = tree.getroot()
# print(root) # 根节点
# print(root.get('?')) # 根节点的属性
import globimport xml.tree.cElenmentTree as ETdef load_dataset(path): # 准备(H, W)进行聚类# H = Ymax - Ymin, W = Xmax - Xmin dataset = [] # glob遍历文件夹中的所有xml文件 for xml_file in glob.glob("{}/*xml".format(path)): tree = ET.parse(xml_file) height = int(tree.findtext("./size/height")) # 图片的尺寸 width = int(tree.findtext("./size/width")) for obj in tree.iter("object"): # 目标对象的坐标点 xmin = np.float64(int(obj.findtext("bndbox/xmin")) / width) # 归一化 ymin = np.float64(int(obj.findtext("bndbox/ymin")) / height) xmax = np.float64(int(obj.findtext("bndbox/xmax")) / width) ymax = np.float64(int(obj.findtext("bndbox/ymax")) / height) if xmax == xmin or ymax == ymin: # 没框 print(xml_file) continue h = ymax - ymin w = xmax - xmin dataset.append([h, w]) # 归一化加速聚类效率 print("dataset", dataset) # print("len(dataset)", len(dataset)) return np.array(dataset)if __name__ == '__main__': load_dataset(出入文件所在路径)
xml、json的解析基本方法已经介绍完,这里也为下一步的聚类9个框做了数据准备。
计算anchors框和boxes实际框之间面积的iou和avg_iou,用于衡量聚类的得分,如果分数过低比如低于60%的时候,说明此时的anchors不能拿来使用,因为得到的框不能很好地反应数据集的期望,效果会极差,只有得分在67%左右,才会得到好的效果。
iou和avg_iou代码
import numpy as npdef iou(boxes, anchors): w = np.minimum(anchors[:, 0], boxes[0]) h = np.minimum(anchors[:, 1], boxes[1]) if np.count_nonzero(w==0) > 0 or np.count_nonzero(h==0): raise ValueError('box has no area') intersection = w * h boxes_area = boxes[0] * boxes[1] anchors_area = anchors[:, 0] * anchors[:, 1] iou_ = intersection / (boxes_area + anchors_area - intersection) return iou_def avg_iou(boxes, anchors): return np.mean([np.max(iou(boxes[i], anchors)) for i in range(boxes.shape[0])])
聚类算法代码
def clustering_algorithm_k_means(boxes, k, dist=np.median): rows = boxes.shape[0] distance = np.empty((rows, k)) # [15662, 9] last_clusters = np.zeros((rows, )) # 1dim->[15662] # print(last_clusters.shape) # np.random.seed(0) # 随机种子,每次更新之前的随机框都相同 clusters = boxes[np.random.choice(rows, k, replace=False)] while True: for w_ in range(rows): distance[w_] = 1 - iou(boxes[w_], clusters) nearest_clusters = np.argmin(distance, axis=1) if (last_clusters == nearest_clusters).all(): break for cluster in range(k): clusters[cluster] = dist(boxes[nearest_clusters == cluster], axis=0) last_clusters = nearest_clusters return clusters