【Pair使用笔记指南3】标注结果转储labelme读取的json文件
pair根据选择标注标签的不同,会保存生成不同的标注文件。目前我发现的就是压缩包文件,里面包含着nii.gz
文件,或者.json
文件。对于某些标注工具的选择,保存的内容可能不同,但是据我发现,.json
文件是都会存在的。
标注过程中发现,pair标注中对闭合区域的标记,有两种形式可以选择,分别是实心闭合和空心闭合,发现如下:
- 实心闭合,保存文件中包括
nii.gz
和json
文件 - 空心闭合,保存文件中只有
jso
n文件 - 两者保存的
json
文件字段和格式不一样
下面我们就对这个复杂的json文件进行转储,生成一个相对比较简单的json文件,可以用labelme
打开的文件。下面我们开始吧。
- 解压存储的标签文件 untar
- 去除一个series的标注信息,包括层号、类别、坐标等等
- 存储到json文件
- labelme打开确认下
下面我们就分空心闭合、实心闭合和混合型三个方面,进行记录。
1. 空心闭合操作
主代码如下:
import json
import commentjson
import tarfile
import os
import globdef untar(fname, output_dirs):t = tarfile.open(fname)t.extractall(path = output_dirs)def PolygonModelpoints3D2points2D(E_Points):tmp_points2d = []for e in E_Points:tmp_points2d.append([e[0], e[1]])return tmp_points2ddef save2jsonFile(list_coors, save_dir, filename):A = dict()listbigoption = []for coor in list_coors:print('coor:', coor)listobject = dict()listxy = coor[:-1]label_cls = coor[-1]listobject['points'] = listxylistobject['line_color'] = 'null'listobject['label'] = str(label_cls)listobject['fill_color'] = 'null'listbigoption.append(listobject)A['lineColor'] = [0, 255, 0, 128]A['imageData'] = 'imageData'A['fillColor'] = [255, 0, 0, 128]A['imagePath'] = filename.replace('.json', '.png')A['shapes'] = listbigoptionA['flags'] = {}with open(os.path.join(save_dir, filename), 'w') as f:json.dump(A, f, indent=2, ensure_ascii=False)def Polygon_json(json_path=None, with_comment=False):label_list = []with open(json_path, encoding='utf-8') as f:if with_comment: # 若*.json中添加了注释,则使用commentjson。若无注释则使用json库也可。Anno_Dict = commentjson.load(f)else:Anno_Dict = json.load(f)Depth, Name = str(Anno_Dict["FileInfo"]["Depth"]), Anno_Dict["FileInfo"]["Name"].split('_')[0]Results_Dict = Anno_Dict["Models"]Polygon_list = Results_Dict["PolygonModel2"]dict_sliceNum_coor = {}for E_idx, E_item in enumerate(Polygon_list):E_Label = str(E_item["Label"])E_Points = E_item["Points"]# 由于存储标签中坐标是xyz的,labelme打开一张图时候,不需要高度信息,就去除掉E_Points = PolygonModelpoints3D2points2D(E_Points)E_Points.append(E_Label)E_SliceIndex = str(E_item["SliceIndex"])print('slicenum: {}\n类别id:{}\n坐标:{}\n'.format(E_SliceIndex, E_Label, E_Points))label_list.append(E_Label)if E_SliceIndex not in dict_sliceNum_coor.keys():dict_sliceNum_coor[E_SliceIndex] = [E_Points]else:cur_coor = dict_sliceNum_coor[E_SliceIndex]cur_coor.append(E_Points)dict_sliceNum_coor[E_SliceIndex] = cur_coorfor key, value in dict_sliceNum_coor.items():save_dir = os.path.join(os.path.dirname(json_path), 'json')filename = Name + '_' + (6-len(key))*'0'+key+'_'+Depth+'.json'if not os.path.exists(save_dir):os.makedirs(save_dir)save2jsonFile(value, save_dir, filename)print(save_dir, filename)return label_listif __name__ == '__main__':data_dir = r'F:\Pair\json_data'patient_list = os.listdir(data_dir)label_list_all = []TB_PatientNum = 0for patient in patient_list:file_dir = os.path.join(data_dir, patient)tar_list = glob.glob(file_dir + r'/*.tar')json_list = glob.glob(file_dir + r'/*.json')if len(tar_list) > len(json_list):if len(tar_list) > 0:for file_path in tar_list:print('start untar ---', file_path)untar(file_path, file_dir)json_list = glob.glob(file_dir + r'/*.json')if len(json_list) > 0:for file_path in json_list:label_list = PolygonModel2_json(json_path=file_path, with_comment=True)
到这里,已经将pair标注保存的json文件,转储到了小的json文件了。但是,此时的json文件和图片文件放到一起,还不能用labelme进行查看,还需要添加base64
位的图像信息到json
文件内。
2. 添加base64到imageData json中
添加的方式如下:
import base64
from PIL import Image
import iodef base64encode_img(image_path):src_image = Image.open(image_path)output_buffer = io.BytesIO()src_image.save(output_buffer, format='JPEG')byte_data = output_buffer.getvalue()base64_str = base64.b64encode(byte_data).decode('utf-8')return base64_strA['imageData'] = base64encode_img(os.path.join(raw_dir, file_name))
上面我就没和上面的代码组合到一起了,相信你一定知道该放置到哪里。如果还有疑问,来评论区留言就可以了。
此时,再用labelme打开,你就能够直接看到标注的信息,显示在图像上面了。
3. 实心闭合操作
import json
import commentjson
import tarfile
import os
import glob"""
1.解压存储的标签文件 untar
2.去除一个series的标注信息,包括层号、类别、坐标等等
3.存储到json文件
4.labelme打开确认下
"""def untar(fname, output_dirs):t = tarfile.open(fname)t.extractall(path = output_dirs)def Polyspoints3D2points2D(E_Points):tmp_points2d = []for e in E_Points:e_p = e["Pos"]tmp_points2d.append([e_p[0], e_p[1]])return tmp_points2ddef save2jsonFile(list_coors, save_dir, filename):A = dict()listbigoption = []for coor in list_coors:# print('coor:', coor)listobject = dict()listxy = coor[:-1]label_cls = coor[-1]listobject['points'] = listxylistobject['line_color'] = 'null'listobject['label'] = str(label_cls)listobject['fill_color'] = 'null'listbigoption.append(listobject)A['lineColor'] = [0, 255, 0, 128]A['imageData'] = 'imageData'A['fillColor'] = [255, 0, 0, 128]A['imagePath'] = filename.replace('.json', '.png')A['shapes'] = listbigoptionA['flags'] = {}with open(os.path.join(save_dir, filename), 'w') as f:json.dump(A, f, indent=2, ensure_ascii=False)def Polys_json(json_path=None, with_comment=False):label_list = []with open(json_path, encoding='utf-8') as f:if with_comment: # 若*.json中添加了注释,则使用commentjson。若无注释则使用json库也可。Anno_Dict = commentjson.load(f)else:Anno_Dict = json.load(f)Depth, Name = str(Anno_Dict["FileInfo"]["Depth"]), Anno_Dict["FileInfo"]["Name"].split('_')[0]Polygon_list = Anno_Dict["Polys"]dict_sliceNum_coor = {}for E_idx, E_item in enumerate(Polygon_list):Shapes_info = E_item["Shapes"]for j_idx, j_item in enumerate(Shapes_info):E_Label = str(j_item["labelType"])E_SliceIndex = str(j_item["ImageFrame"])E_Points = j_item["Points"]# 由于存储标签中坐标是xyz的,labelme打开一张图时候,不需要高度信息,就去除掉E_Points = Polyspoints3D2points2D(E_Points)E_Points.append(E_Label)# print('slicenum: {}\n类别id:{}\n坐标:{}\n'.format(E_SliceIndex, E_Label, E_Points))label_list.append(E_Label)if E_SliceIndex not in dict_sliceNum_coor.keys():dict_sliceNum_coor[E_SliceIndex] = [E_Points]else:cur_coor = dict_sliceNum_coor[E_SliceIndex]cur_coor.append(E_Points)dict_sliceNum_coor[E_SliceIndex] = cur_coorfor key, value in dict_sliceNum_coor.items():save_dir = os.path.join(os.path.dirname(json_path), 'json')filename = Name + '_' + (6-len(key))*'0'+key+'_'+Depth+'.json'if not os.path.exists(save_dir):os.mkdir(save_dir)save2jsonFile(value, save_dir, filename)print(save_dir, filename)return label_listif __name__ == '__main__':data_dir = r'Z:\cancer1-100'patient_list = os.listdir(data_dir)label_list_all = []TB_PatientNum = 0for patient in patient_list:file_dir = os.path.join(data_dir, patient)print(file_dir)if os.path.exists(os.path.join(data_dir, patient, 'json')):continuetar_list = glob.glob(file_dir + r'/*.tar')json_list = glob.glob(file_dir + r'/*.json')if len(tar_list) > len(json_list):if len(tar_list) > 0:for file_path in tar_list:print('start untar ---', file_path)untar(file_path, file_dir)json_list = glob.glob(file_dir + r'/*.json')if len(json_list) > 0:for file_path in json_list:# Polyslabel_list = Polys_json(json_path=file_path, with_comment=True)
除去上面两种情况外,还会有混合的,则进行统一处理。
处理代码如下:
def Polygon_combine_json(json_path=None, with_comment=False):label_list = []with open(json_path, encoding='utf-8') as f:if with_comment: # 若*.json中添加了注释,则使用commentjson。若无注释则使用json库也可。Anno_Dict = commentjson.load(f)else:Anno_Dict = json.load(f)Depth, Name = str(Anno_Dict["FileInfo"]["Depth"]), Anno_Dict["FileInfo"]["Name"].split('_')[0]try:Results_Dict = Anno_Dict["Models"]Polygon_list = Results_Dict["PolygonModel2"]dict_sliceNum_coor = {}for E_idx, E_item in enumerate(Polygon_list):E_Label = str(E_item["Label"])E_Points = E_item["Points"]if len(E_Points) < 3:continue# 由于存储标签中坐标是xyz的,labelme打开一张图时候,不需要高度信息,就去除掉E_Points = PolygonModelpoints3D2points2D(E_Points)E_Points.append(E_Label)# 序号这里建议直接+1,解决从0开始的问题E_SliceIndex = str(E_item["SliceIndex"])# print('slicenum: {}\n类别id:{}\n坐标:{}\n'.format(E_SliceIndex, E_Label, E_Points))label_list.append(E_Label)if E_SliceIndex not in dict_sliceNum_coor.keys():dict_sliceNum_coor[E_SliceIndex] = [E_Points]else:cur_coor = dict_sliceNum_coor[E_SliceIndex]cur_coor.append(E_Points)dict_sliceNum_coor[E_SliceIndex] = cur_coorexcept:passtry:Polygon_list2 = Anno_Dict["Polys"]for E_idx, E_item in enumerate(Polygon_list2):Shapes_info = E_item["Shapes"]for j_idx, j_item in enumerate(Shapes_info):E_Label = str(j_item["labelType"])# 序号这里建议直接+1,解决从0开始的问题E_SliceIndex = str(j_item["ImageFrame"])E_Points = j_item["Points"]# 加上判断,避免出现单个点if len(E_Points) < 3:continue# 由于存储标签中坐标是xyz的,labelme打开一张图时候,不需要高度信息,就去除掉E_Points = Polyspoints3D2points2D(E_Points)E_Points.append(E_Label)# print('slicenum: {}\n类别id:{}\n坐标:{}\n'.format(E_SliceIndex, E_Label, E_Points))label_list.append(E_Label)if E_SliceIndex not in dict_sliceNum_coor.keys():dict_sliceNum_coor[E_SliceIndex] = [E_Points]else:cur_coor = dict_sliceNum_coor[E_SliceIndex]cur_coor.append(E_Points)dict_sliceNum_coor[E_SliceIndex] = cur_coorexcept:passfor key, value in dict_sliceNum_coor.items():save_dir = os.path.join(os.path.dirname(json_path), 'json')# filename = Name + '_' + (6-len(key))*'0'+key+'_'+Depth+'.json'filename = Name + '_' + (6 - len(key)) * '0' + key + '.json'if not os.path.exists(save_dir):os.mkdir(save_dir)save2jsonFile(value, save_dir, filename)print(save_dir, filename)return label_list
4.注意事项
注意事项1:ImageFrame从0开始
这点在对生成的json文件与图像对应时候尤为重要。我们dcm文件中都是从1开始的,而不是0。所以这点需要注意。
注意事项2:ImageFrame的排序和dcm文件的排序会不一致
生成的json标注文件内ImageFrame排序不是按照dcm文件内记录的顺序进行排布的,而是根据Z轴进行排布的,也就是我们下图的箭头方向:
注意事项3:json标注坐标,是在mm单位下的坐标,不是像素单位
如果你用labelme
打开发现标注区域不匹配,这个点需要注意。所以在转图时候,记得转化到mm单位,这里要用到PixelSpacing
- 方式一,对坐标除以pixelspace,换算到mm单位
- 方式二,对图像大小乘以pixelspace,换算到像素单位
至此,亲测有效,你就可以打开生成的json和图像放到一起,用labelme打开看看了。相信你看到的内容,还是很满意的。
【Pair使用笔记指南3】标注结果转储labelme读取的json文件相关推荐
- Three.js入门学习笔记07:外部模型导入-C4D转成json文件供网页使用-fbx导入
上一篇用的obj导入,转成json发现有些材质加载不进去,不知是什么原因. 比如blender导入obj模型的时候,只要obj和mtl材质文件在同一个文件夹内,正常情况,导入obj的同时就能直接导入同 ...
- Python深度学习入门笔记(二):使用Pandas读取批量CSV文件,文件名中有顺序变量
前言 本文主要展示如何将具有变量名称的 CSV 文件导入 Python,比如一系列连续变化的文件如: r1.csv r2.csv r3.csv - 我将使用一个简单的例子来说明这个概念,并提供完整的 ...
- Three.js入门学习笔记05:外部模型导入-C4D转成json文件供网页使用
参考学习: https://www.jianshu.com/p/906072e60197 https://blog.csdn.net/qq_30100043/article/details/79606 ...
- 根据标注精灵助手标好并导出的json文件生成txt文件(一)
最近在做自然场景的OCR检测识别算法,对于检测来说,需要对文件图片进行ground truth坐标点label的标注,刚开始使用的是标注精灵助手,标注好boundingbox后导出的是json格式的文 ...
- 【深度学习之路记录02】python代码批量修改Labelme标注的json文件(删除标签、修改标签名)
代码参考:https://blog.csdn.net/qq_44442727/article/details/112785978 创建自己的数据集时,经常需要一些调整,比如说修改某一批文件中已经标好的 ...
- Revit2016 笔记10 - Revit标注
Revit2016 笔记10 - Revit标注 一.尺寸标注 尺寸标注是项目中显示距离和尺寸的视图专有图元,其中包括两种类型: 临时尺寸标注和永久性尺寸标注.当放置构件时,Revit 会放置临时尺寸 ...
- Linux学习笔记-段错误与内存转储
在Linux下,程序中如果进行了不正确的指针操作,则程序崩溃.提示"Segment Fault": 源码如下: #include <stdio.h>void test( ...
- 好用的图像分割标注工具:Labelme
缘起:最近在找合适的读博院校,正在参与一个和人眼语义分割有关的小测验,需要从网上自己找数据,做标签,所以借此机会和大家推荐一下这款救我于火急之中的小工具Labelme. 这里有详细的安装步骤:http ...
- Python修改图片格式以及相对应labelme标注的Json文件
Python修改图片格式以及相对应labelme标注的Json文件 前言 前提条件 相关介绍 实验环境 Python修改图片格式以及相对应labelme标注的Json文件 代码实现 输出结果 前言 本 ...
最新文章
- jfreechart的使用
- MongoDB工具最新开发 源代码更新 兼 进展报告 - 集群功能开发
- VS2010 断点无效肿么办?
- 放苹果问题 POJ 1664
- Lucene教程--Analyzer分析器详解
- Spring4学习笔记
- android 布局防抖动,Android全屏返回布局抖动问题
- Jsoup获取所有链接
- OpenShift 4 Hands-on Lab (0) - 教程说明和准备环境
- 历史为什么选择C语言?事实证明:暮年的C语言,依旧宝刀未老!
- Codeforces Global Round 21 E. Placing Jinas
- 数据输入流与数据输出流
- 粒子群算法查找函数最小值
- 新自媒体账号想要开直播?大周给你几点建议
- 2004年国内十大暴利行业
- 湖北公安机关出台10条措施服务民营经济发展
- 5个实用的性能测试工具(软件测试工程师必备)
- 佳明表盘 c语言开发的吗,Garmin MonkeyC的写法和经验
- 红外接收二极管 -- 结电容和暗电流
- 噪鹃de“喔啊“悲惨的叫声
热门文章
- 清华大学计算机科学与技术系黄必胜,刘斌(清华大学计算机科学与技术系教授)_百度百科...
- SSRS 的简单使用(一)
- GIT乱码解决方案汇总及GIT用户名和邮箱修改
- 电脑上的c语言程序打不开,电脑软件无法打开怎么解决|电脑软件打不开的处理的方法...
- PyQt5界面多线程多进程爬虫(爬了600w张网页, 出现了一些问题)
- 全球各地5G频谱分配情况如何?最全无线通信频率分配表
- 你以为的5G仅仅是运行在5G的频段嘛?一文带你了解国内运营商的5G/4G/3G/2G频谱划分
- 如何只用逻辑运算实现算术加减乘除运算
- 关于开发Android应用时写从图库选择头像功能时遇到的一些问题。
- NC65后台手动创建用户并设置初始密码