RT struct 文件 保存为nii文件及解析
最近在做放療劑量預(yù)測相關(guān)工作,需要將TPS系統(tǒng)中的RTdose、RTstruct文件等進(jìn)行解析。開個帖子記錄一下,僅供參考。
本帖記錄RT struct文件解析
目的:
將TPS導(dǎo)出的病人文件相關(guān)文件轉(zhuǎn)換.nii 或者 .npy
病例文件結(jié)構(gòu):
導(dǎo)出的數(shù)據(jù)應(yīng)該包括病人的dcm原始CT圖像以及RTstruct文件,結(jié)構(gòu)目錄如下:
處理流程:
參考開源的 dcmrtstruct2nii 工具包,pip 安裝后,修改部分源代碼 。以解決dcm文件不能讀取以及是否保存文件到磁盤的問題。
1、安裝dcmrtstruct2nii 包
pip install dcmrtstruct2nii2、簡單的使用
from dcmrtstruct2nii import dcmrtstruct2nii, list_rt_structs path = './StrctrSets.dcm' print(list_rt_structs(path)) dcmrtstruct2nii(path, './test', './outputa') #分別對應(yīng)rtstruct.dcm,病人圖像文件夾,輸出文件夾通過以上代碼可以直接將RTstruct文件 提取出來并保存為nii?,如果報錯不能加載dcm文件,請參考第三節(jié)。
dcmrtstruct2nii具體參數(shù)請自行參考源碼:
?3、修改dcmrtstruct2nii源碼,使得可以讀入自己的數(shù)據(jù)。在讀入過程報錯:
File is missing DICOM File Meta Information header or the 'DICM' prefix is missing from the header. Use force=True to force reading.如下圖請點擊報錯的地方,?然后在讀入文件的那句話加入?yún)?shù)force=true。修改后如圖 一般是在rtstructinputadapter.py中
?修改完后,即可以讀入圖像。這個一般是因為TPS導(dǎo)出的dcm,pydicom無法識別。加一個force便可以對其進(jìn)行讀取。
4、為了方便調(diào)試,重寫dcmrtstruct2nii函數(shù),添加返回值:結(jié)構(gòu)體名字,結(jié)構(gòu)體的Sitk.Image 數(shù)據(jù)
并根據(jù)output是否為空決定是否保存圖像到磁盤。修改后的源碼如下:
def dcmrtstruct2nii(rtstruct_file, dicom_file, output_path='', structures=None, gzip=True,mask_background_value=0, mask_foreground_value=255,convert_original_dicom=True):"""Converts A DICOM and DICOM RT Struct file to nii:param rtstruct_file: Path to the rtstruct file:param dicom_file: Path to the dicom file:param output_path: Output path where the masks are written to:param structures: Optional, list of structures to convert:param gzip: Optional, output .nii.gz if set to True, default: True:param save:Optional, whether to save nii file default:True:raise InvalidFileFormatException: Raised when an invalid file format is given.:raise PathDoesNotExistException: Raised when the given path does not exist.:raise UnsupportedTypeException: Raised when conversion is not supported.:raise ValueError: Raised when mask_background_value or mask_foreground_value is invalid."""output_path = os.path.join(output_path, '') # make sure trailing slash is thereif not os.path.exists(rtstruct_file):raise PathDoesNotExistException(f'rtstruct path does not exist: {rtstruct_file}')if not os.path.exists(dicom_file):raise PathDoesNotExistException(f'DICOM path does not exists: {dicom_file}')if mask_background_value < 0 or mask_background_value > 255:raise ValueError(f'Invalid value for mask_background_value: {mask_background_value}, must be between 0 and 255')if mask_foreground_value < 0 or mask_foreground_value > 255:raise ValueError(f'Invalid value for mask_foreground_value: {mask_foreground_value}, must be between 0 and 255')if structures is None:structures = []#### 如果輸出路徑為空,不進(jìn)行文件保存if output_path != '':os.makedirs(output_path, exist_ok=True)filename_converter = FilenameConverter()rtreader = RtStructInputAdapter()rtstructs = rtreader.ingest(rtstruct_file)dicom_image = DcmInputAdapter().ingest(dicom_file)dcm_patient_coords_to_mask = DcmPatientCoords2Mask()nii_output_adapter = NiiOutputAdapter()mask_name = [] ##定義保存結(jié)構(gòu)體名字的列表mask_Image = [] ##定義保存Image的列表for rtstruct in rtstructs:if len(structures) == 0 or rtstruct['name'] in structures:if not 'sequence' in rtstruct:logging.info('Skipping mask {} no shape/polygon found'.format(rtstruct['name']))continuelogging.info('Working on mask {}'.format(rtstruct['name']))try:mask = dcm_patient_coords_to_mask.convert(rtstruct['sequence'], dicom_image, mask_background_value, mask_foreground_value)except ContourOutOfBoundsException:logging.warning(f'Structure {rtstruct["name"]} is out of bounds, ignoring contour!')continuemask.CopyInformation(dicom_image)mask_filename = filename_converter.convert(f'mask_{rtstruct["name"]}')mask_name.append(mask_filename)mask_Image.append((mask))if output_path != '':#### 如果輸出路徑為空,不進(jìn)行文件保存nii_output_adapter.write(mask, f'{output_path}{mask_filename}', gzip)return mask_name,mask_Image ##返回對應(yīng)的兩個列表if convert_original_dicom:logging.info('Converting original DICOM to nii')nii_output_adapter.write(dicom_image, f'{output_path}image', gzip)logging.info('Success!')在修改代碼后,便可以通過以下的代碼對函數(shù)進(jìn)行調(diào)用
from dcmrtstruct2nii import dcmrtstruct2nii, list_rt_structs path = './RTDICOM/20220356_StrctrSets.dcm' print(list_rt_structs(path)) name, image = dcmrtstruct2nii(path, './RTDICOM/patient') #參數(shù)分別為struct文件、病人圖像文件夾,輸出文件夾img = sitk.GetArrayFromImage(image[0]) import matplotlib.pyplot as plt plt.imshow(img[60]) plt.show()可以print name和image[0]的類型進(jìn)行查看,并進(jìn)行后續(xù)工作。
5、關(guān)于RTdose的解析,請見后續(xù)。
總結(jié)
以上是生活随笔為你收集整理的RT struct 文件 保存为nii文件及解析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpringMVC原理
- 下一篇: MATLAB 产生线性调频信号