在使用标注软件的过程中,会考虑将已经标注好的数据,导入到当前的标注软件中,进行二次审核或标注任务。
此时,就需要对已经标注的标签文件,转化为该软件可以打开显示的格式。对于pair软件的使用,也不例外。
下面我们要做的就是对已经有单一标签的数据,生成可以被pair软件所能读取的格式,然后打开进行二次标注。
1. 标注标签转储
有使用过pair软件标注的都知道,在标注完成,保存标签时候,pair软件在某些标签情况下,会生成包含mask形式的nii.gz格式的标签文件。我们这里就是采用这个文件,往pair软件里面导入已经标注好的标签。
那么,第一步就是将我们已经标注的信息,转储成nii.gz格式,我
import glob
import numpy as np
from PIL import Image
def png2nii(image_path):
image_arr = glob.glob(str(image_path) + str("/*"))
image_arr.sort()
print(image_arr, len(image_arr))
allImg = []
allImg = np.zeros([len(image_arr), 512, 512], dtype='uint8')
for i in range(len(image_arr)):
single_image_name = image_arr[i]
img_as_img = Image.open(single_image_name).convert("L")
#img_as_img.show()
img_as_np = np.asarray(img_as_img)
allImg[i, :, :] = img_as_np
np.transpose(allImg, [2, 1, 0])
return allImg
def save_array_as_nii_volume(data, filename, reference_name=None):
"""
save a numpy array as nifty image
inputs:
data: a numpy array with shape [Depth, Height, Width]
filename: the ouput file name
reference_name: file name of the reference image of which affine and header are used
outputs: None
"""
img = sitk.GetImageFromArray(data)
if (reference_name is not None):
img_ref = sitk.ReadImage(reference_name)
img.CopyInformation(img_ref)
sitk.WriteImage(img, filename)
def oneSeriesMask2nii(image_path, dst_dir, patient):
allImg = png2nii(image_path)
save_array_as_nii_volume(allImg, os.path.join(dst_dir, patient, patient + '.nii.gz'))
print(np.shape(allImg))
上面展示了一个CT Series序列生成好的mask图,转储成nii.gz文件格式的数据,可以采用pair或ITK-SNAP标注软件进行打开。
mask图像存储如下所示:
2.pair打开遇到不对齐问题
通过阶段1,生成的包含mask
的nii.gz
文件,用pair
打开,会遇到如下的这种情况:
问题是什么呢?显示的mask图,与图像位置不太匹配。仔细琢磨后发现是由于dcm文件的像素尺寸与物理尺寸之间的差异。原因如下:
- pair显示的是mm单位,也就是像素大小space,此时显示的就不再是(512,512),而是(512xspace,512*yspace)
- 制作nii.gz文件时候的大小是(512,512),没有顾及到space转换
下面就有两种方式改变
- 制作nii.gz大小也转到
(512*xspace,512*yspace)
,发现不能导入,报错 - pair显示的图像,调整到
(512,512)
,也就是space调整等于1,发现可用,正常显示
发现pair显示的图像,调整到(512,512)
是有效的,我们下面就看下是如何调整的。直接放图
后面我们看下,修改后匹配的样子,如下图所示:
至此,pair软件导入我们自己放进去的标签,进行二次标注的情况就完成了。之后利用pair自带的提取标注mask位置的功能,就可以对mask区域进行调整,进而转储成pair生成的标签标准格式。
这里,有几个点需要注意和待验证:
- 原图是调整到512*512的,后期产生的mask和json文件,是否需要进一步转换,待验证
- space不变,改变导入nii.gz的文件大小或其他形式,是否可以打破我报的错误
3. ITK-SNAP标注查看导入的mask
ITK-SNAP也是目标医学标注中用户很多的一个软件,在这个软件里面可以直接导入nii的图像和标注文件进行显示。我们下面利用这个软件,对上面生成的标签文件进行查看。
3.1 dcm文件,转储成nii文件
首先需要将dcm文件,转储成nii文件,转储代码如下:
#coding=utf-8
import SimpleITK as sitk
def dcm2nii(dcms_path, nii_path):
# 1.构建dicom序列文件阅读器,并执行(即将dicom序列文件“打包整合”)
reader = sitk.ImageSeriesReader()
dicom_names = reader.GetGDCMSeriesFileNames(dcms_path)
reader.SetFileNames(dicom_names)
image2 = reader.Execute()
# 2.将整合后的数据转为array,并获取dicom文件基本信息
image_array = sitk.GetArrayFromImage(image2) # z, y, x
origin = image2.GetOrigin() # x, y, z
spacing = image2.GetSpacing() # x, y, z
direction = image2.GetDirection() # x, y, z
# 3.将array转为img,并保存为.nii.gz
image3 = sitk.GetImageFromArray(image_array)
image3.SetSpacing(spacing)
image3.SetDirection(direction)
image3.SetOrigin(origin)
sitk.WriteImage(image3, nii_path)
def main_dcm2nii():
data_dir = r'Z:\pneumonia\dcm_new'
save_dir = r'Z:\pneumonia\raw_nii'
patient_list = os.listdir(data_dir)
n=0
for patient in patient_list:
dcms_path = os.path.join(data_dir, patient)
nii_path = os.path.join(save_dir, patient) # 所需.nii.gz文件保存路径
if not os.path.exists(nii_path):
os.makedirs(nii_path)
dcm2nii(dcms_path, os.path.join(nii_path, 'volume-'+str(n)+'.nii'))
n+=1
至此,我们就得到了两个文件,分别是
- .nii文件,包含着医学影像
- .nii.gz,包含着标注mask
3.2 ITK-SNAP打开查看
这时,打开ITK-SNAP
标注软件,现将医学影像拖进去,再讲mask标注信息拖进去,在拖动mask的nii.gz文件时候,会弹出如下选择窗口,此时选择segmentation
这个就行。
这时,就可以看到ITK-SNAP打开后的样子,如下:
发现,ITK-SNAP是可以直接进行查看的,不存在pair中存在的这个问题。可能pair考虑的会更多吧。