def cylinder_mask(setting, cn=None, overwrite=False): cylinder_folder = su.address_generator(setting, 'Cylinder', cn=cn, type_im=0).rsplit('/', maxsplit=1)[0] if not os.path.isdir(cylinder_folder): os.makedirs(cylinder_folder) for type_im in range(len(setting['types'])): cylinder_mask_address = su.address_generator(setting, 'Cylinder', cn=cn, type_im=type_im) if (not os.path.isfile(cylinder_mask_address)) or overwrite: image_sitk = sitk.ReadImage( su.address_generator(setting, 'Im', cn=cn, type_im=type_im)) cylinder_mask_sitk = sitk.BinaryThreshold( image_sitk, lowerThreshold=setting['DefaultPixelValue'] - 1, upperThreshold=setting['DefaultPixelValue'] + 0.01, insideValue=0, outsideValue=1) structure = np.ones((1, 3, 3)) # erosion with ndimage is 5 times faster than SimpleITK cylinder_mask_eroded = (ndimage.binary_erosion( sitk.GetArrayFromImage(cylinder_mask_sitk), structure=structure, iterations=2)).astype(np.int8) cylinder_mask_eroded_sitk = ip.array_to_sitk(cylinder_mask_eroded, im_ref=image_sitk) sitk.WriteImage(cylinder_mask_eroded_sitk, cylinder_mask_address) logging.debug(cylinder_mask_address + ' is done')
def lung_fill_hole_erode(setting, cn=None): folder = su.address_generator(setting, 'Lung_Filled_Erode', cn=cn, type_im=0).rsplit('/', maxsplit=1)[0] if not os.path.isdir(folder): os.makedirs(folder) for type_im in range(len(setting['types'])): lung_raw_filled_sitk = sitk.ReadImage( su.address_generator(setting, 'Lung_Filled', cn=cn, type_im=type_im)) lung_raw_filled = sitk.GetArrayFromImage(lung_raw_filled_sitk) lung_raw_filled = lung_raw_filled > 0 structure = np.ones([3, 3, 3], dtype=np.bool) lung_filled_erode = (ndimage.morphology.binary_dilation( lung_raw_filled, structure=structure)).astype(np.int8) sitk.WriteImage( ip.array_to_sitk(lung_filled_erode, im_ref=lung_raw_filled_sitk), su.address_generator(setting, 'Lung_Filled_Erode', cn=cn, type_im=type_im))
def lung_fill_hole(data_folder, data, type_im, cn, ext='.mha', mha_folder_name='mha'): lung_initial_folder_name = 'Lung_Initial' lung_filled_folder_name = 'Lung_Filled' if data == 'DIR-Lab_4D': type_im_list = [ 'T00', 'T10', 'T20', 'T30', 'T40', 'T50', 'T60', 'T70', 'T80', 'T90' ] data_folder_sub = data_folder + 'DIR-Lab/4DCT/' lung_initial_folder = data_folder_sub + mha_folder_name + '/case' + str( cn) + '/' + lung_initial_folder_name + '/' lung_filled_folder = data_folder_sub + mha_folder_name + '/case' + str( cn) + '/' + lung_filled_folder_name + '/' lung_initial_address = lung_initial_folder + 'case' + str( cn ) + '_' + type_im_list[type_im] + '_' + lung_initial_folder_name + ext lung_filled_address = lung_filled_folder + 'case' + str( cn ) + '_' + type_im_list[type_im] + '_' + lung_filled_folder_name + ext elif data == 'DIR-Lab_COPD': type_im_list = ['i', 'e'] data_folder_sub = data_folder + 'DIR-Lab/COPDgene/' lung_initial_folder = data_folder_sub + mha_folder_name + '/' + lung_initial_folder_name + '/' lung_filled_folder = data_folder_sub + mha_folder_name + '/' + lung_filled_folder_name + '/' lung_initial_address = lung_initial_folder + 'copd' + str( cn) + '_' + type_im_list[type_im] + 'BHCT' + ext lung_filled_address = lung_filled_folder + 'copd' + str( cn) + '_' + type_im_list[type_im] + 'BHCT' + ext else: raise ValueError('Data=' + data + ", it should be in ['DIR-Lab_4D', 'DIR-Lab_COPD']") if not os.path.isdir(lung_filled_folder): os.makedirs(lung_filled_folder) lung_initial_sitk = sitk.ReadImage(lung_initial_address) lung_initial = sitk.GetArrayFromImage(lung_initial_sitk) lung_initial = lung_initial > 0 structure = np.ones([3, 3, 3], dtype=np.bool) lung_filled = (ndimage.morphology.binary_closing( lung_initial, structure=structure)).astype(np.int8) sitk.WriteImage(ip.array_to_sitk(lung_filled, im_ref=lung_initial_sitk), lung_filled_address)
def add_noise(setting, im_info, stage, deformed_im_previous_sitk=None, deformed_torso_sitk=None, gonna_generate_next_im=False): im_info_su = { 'data': im_info['data'], 'deform_exp': im_info['deform_exp'], 'type_im': im_info['type_im'], 'cn': im_info['cn'], 'dsmooth': im_info['dsmooth'], 'stage': stage, 'padto': im_info['padto'] } seed_number = ag_utils.seed_number_by_im_info( im_info, 'add_noise', stage=stage, gonna_generate_next_im=gonna_generate_next_im) random_state = np.random.RandomState(seed_number) if gonna_generate_next_im: sigma_noise = setting['deform_exp'][ im_info['deform_exp']]['NextIm_SigmaN'] torso_address = su.address_generator(setting, 'NextTorso', **im_info_su) else: sigma_noise = setting['deform_exp'][ im_info['deform_exp']]['Im_NoiseSigma'] torso_address = su.address_generator(setting, 'DeformedTorso', **im_info_su) if deformed_im_previous_sitk is None: deformed_im_previous_sitk = sitk.ReadImage( su.address_generator(setting, 'DeformedIm', deformed_im_ext='Clean', **im_info_su)) max_mean_noise = setting['deform_exp'][ im_info['deform_exp']]['Im_NoiseAverage'] random_mean = random_state.uniform(-max_mean_noise, max_mean_noise) if setting['data'][im_info['data']]['ImageByte'] in [ sitk.sitkUInt8, sitk.sitkUInt16, sitk.sitkUInt32, sitk.sitkUInt64, sitk.sitkInt8, sitk.sitkInt16, sitk.sitkInt32, sitk.sitkInt64 ]: random_mean = int(random_mean) deformed_im_noise_sitk = sitk.AdditiveGaussianNoise( deformed_im_previous_sitk, sigma_noise, random_mean, 0) if setting['UseTorsoMask']: # no noise outside of Torso region. if deformed_torso_sitk is None: deformed_torso_sitk = sitk.ReadImage(torso_address) deformed_torso = sitk.GetArrayFromImage(deformed_torso_sitk) deformed_im_noise = sitk.GetArrayFromImage(deformed_im_noise_sitk) deformed_im_previous = sitk.GetArrayFromImage( deformed_im_previous_sitk) deformed_im_noise[deformed_torso == 0] = deformed_im_previous[ deformed_torso == 0] deformed_im_noise_sitk = ip.array_to_sitk( deformed_im_noise, im_ref=deformed_im_previous_sitk) return deformed_im_noise_sitk
def add_occlusion(setting, im_info, stage, deformed_im_previous_sitk=None, dvf_sitk=None): im_info_su = { 'data': im_info['data'], 'deform_exp': im_info['deform_exp'], 'type_im': im_info['type_im'], 'cn': im_info['cn'], 'dsmooth': im_info['dsmooth'], 'stage': 1, 'padto': im_info['padto'] } seed_number = ag_utils.seed_number_by_im_info(im_info, 'add_occlusion', stage=stage) random_state = np.random.RandomState(seed_number) if deformed_im_previous_sitk is None: deformed_im_previous_sitk = sitk.ReadImage( su.address_generator(setting, 'DeformedIm', deformed_im_ext='Noise', **im_info_su)) if dvf_sitk is None: dvf_address = su.address_generator(setting, 'DeformedDVF', **im_info_su) dvf_sitk = sitk.ReadImage(dvf_address) deformed_lung_address = su.address_generator(setting, 'DeformedLung', **im_info_su) if not os.path.isfile(deformed_lung_address): im_lung_sitk = sitk.ReadImage( su.address_generator(setting, 'Lung', **im_info_su)) dvf_t = sitk.DisplacementFieldTransform( sitk.Cast(dvf_sitk, sitk.sitkVectorFloat64)) deformed_lung_sitk = ip.resampler_by_transform( im_lung_sitk, dvf_t, im_ref=deformed_im_previous_sitk, default_pixel_value=0, interpolator=sitk.sitkNearestNeighbor) sitk.WriteImage(sitk.Cast(deformed_lung_sitk, sitk.sitkInt8), deformed_lung_address) time.sleep(5) deformed_im_noise = sitk.GetArrayFromImage(deformed_im_previous_sitk) deformed_lung = sitk.GetArrayFromImage( sitk.ReadImage(deformed_lung_address)) struct = np.ones((9, 9, 9), dtype=bool) deformed_lung_erode = ndimage.binary_erosion(deformed_lung, structure=struct).astype( np.bool) ellipse_lung = np.zeros(deformed_im_noise.shape, dtype=np.bool) ellipse_center_lung = deformed_lung_erode.copy() for ellipse_number in range(setting['deform_exp'][im_info['deform_exp']] ['Occlusion_NumberOfEllipse']): center_list = np.where(ellipse_center_lung > 0) selected_center_i = int( random_state.randint(0, len(center_list[0]) - 1, 1, dtype=np.int64)) a = random_state.random_sample() * setting['deform_exp'][ im_info['deform_exp']]['Occlusion_Max_a'] b = random_state.random_sample() * setting['deform_exp'][ im_info['deform_exp']]['Occlusion_Max_b'] c = random_state.random_sample() * setting['deform_exp'][ im_info['deform_exp']]['Occlusion_Max_c'] if a < 3: a = 3 if b < 3: b = 3 if c < 3: c = 3 ellipse_crop = np.zeros( [2 * round(a) + 1, 2 * round(b) + 1, 2 * round(c) + 1]) for i1 in range(np.shape(ellipse_crop)[0]): for i2 in range(np.shape(ellipse_crop)[1]): for i3 in range(np.shape(ellipse_crop)[2]): if (((i1 - a) / a)**2 + ((i2 - b) / b)**2 + ((i3 - c) / c)**2) < 1: ellipse_crop[i1, i2, i3] = 1 ellipse_lung[center_list[0][selected_center_i]-round(a/2): center_list[0][selected_center_i]-round(a/2)+np.shape(ellipse_crop)[0], center_list[1][selected_center_i]-round(b/2): center_list[1][selected_center_i]-round(b/2)+np.shape(ellipse_crop)[1], center_list[2][selected_center_i]-round(c/2): center_list[2][selected_center_i]-round(c/2)+np.shape(ellipse_crop)[2]] = \ ellipse_crop margin = 5 ellipse_center_lung[center_list[0][selected_center_i] - round(a / 2) - margin:center_list[0][selected_center_i] - round(a / 2) + np.shape(ellipse_crop)[0] + margin, center_list[1][selected_center_i] - round(b / 2) - margin:center_list[1][selected_center_i] - round(b / 2) + np.shape(ellipse_crop)[1] + margin, center_list[2][selected_center_i] - round(c / 2) - margin:center_list[2][selected_center_i] - round(c / 2) + np.shape(ellipse_crop)[2] + margin] = 0 sitk.WriteImage( sitk.Cast( ip.array_to_sitk(ellipse_lung.astype(np.int8), im_ref=deformed_im_previous_sitk), sitk.sitkInt8), su.address_generator(setting, 'DeformedLungOccluded', **im_info_su)) ellipse_lung_erode = (ellipse_lung.copy()).astype(np.bool) struct = np.array([[[0, 0, 0], [0, 1, 0], [0, 0, 0]], [[0, 1, 0], [1, 1, 1], [0, 1, 0]], [[0, 0, 0], [0, 1, 0], [0, 0, 0]]]) weight_occluded_list = np.array([0.2, 0.6, 0.9]) weight_image_list = 1 - weight_occluded_list print( '--------------------------------------will be corrected: occlusion intensity is not always an integer' ) print( '--------------------------------------will be corrected: occlusion intensity is not always an integer' ) print( '--------------------------------------will be corrected: occlusion intensity is not always an integer' ) occlusion_intensity = int( random_state.randint(setting['deform_exp'][ im_info['deform_exp']]['Occlusion_IntensityRange'][0], setting['deform_exp'][im_info['deform_exp']] ['Occlusion_IntensityRange'][1], 1, dtype=np.int64)) for i in range(3): ellipse_lung_erode_new = ndimage.binary_erosion( ellipse_lung_erode, structure=struct).astype(np.bool) edge_lung = ellipse_lung_erode ^ ellipse_lung_erode_new i_edge = np.where(edge_lung) deformed_im_noise[ i_edge] = deformed_im_noise[i_edge] * weight_image_list[ i] + occlusion_intensity * weight_occluded_list[i] ellipse_lung_erode = ellipse_lung_erode_new.copy() i_inside = np.where(ellipse_lung_erode_new > 0) deformed_im_noise[i_inside] = occlusion_intensity + random_state.normal( scale=setting['deform_exp'][im_info['deform_exp']]['Im_NoiseSigma'], size=len(i_inside[0])) deformed_im_occluded_sitk = ip.array_to_sitk( deformed_im_noise, im_ref=deformed_im_previous_sitk) return deformed_im_occluded_sitk
def add_sponge_model(setting, im_info, stage, deformed_im_previous_sitk=None, dvf=None, deformed_torso_sitk=None, spacing=None, gonna_generate_next_im=False): im_info_su = { 'data': im_info['data'], 'deform_exp': im_info['deform_exp'], 'type_im': im_info['type_im'], 'cn': im_info['cn'], 'dsmooth': im_info['dsmooth'], 'stage': stage, 'padto': im_info['padto'] } seed_number = ag_utils.seed_number_by_im_info( im_info, 'add_sponge_model', stage=stage, gonna_generate_next_im=gonna_generate_next_im) random_state = np.random.RandomState(seed_number) if gonna_generate_next_im: jac_address = su.address_generator(setting, 'NextJac', **im_info_su) torso_address = su.address_generator(setting, 'NextTorso', **im_info_su) else: jac_address = su.address_generator(setting, 'Jac', **im_info_su) torso_address = su.address_generator(setting, 'DeformedTorso', **im_info_su) if deformed_im_previous_sitk is None: deformed_im_previous_sitk = sitk.ReadImage( su.address_generator(setting, 'DeformedIm', deformed_im_ext='Clean', **im_info_su)) deformed_im_clean = sitk.GetArrayFromImage(deformed_im_previous_sitk) if not os.path.isfile(jac_address): if dvf is None: dvf = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, 'DeformedDVF', **im_info_su))) if spacing is None: spacing = deformed_im_previous_sitk.GetSpacing()[::-1] jac = ip.calculate_jac(dvf, spacing) if not gonna_generate_next_im: sitk.WriteImage(sitk.GetImageFromArray(jac.astype(np.float32)), jac_address) else: jac = sitk.GetArrayFromImage(sitk.ReadImage(jac_address)) random_scale = random_state.uniform(0.9, 1.1) jac[jac < 0.7] = 0.7 jac[jac > 1.3] = 1.3 deformed_im_sponge = deformed_im_clean / jac * random_scale if setting['UseTorsoMask']: # no scaling outside of Torso region. if deformed_torso_sitk is None: deformed_torso_sitk = sitk.ReadImage(torso_address) deformed_torso = sitk.GetArrayFromImage(deformed_torso_sitk) deformed_im_previous = sitk.GetArrayFromImage( deformed_im_previous_sitk) deformed_im_sponge[deformed_torso == 0] = deformed_im_previous[ deformed_torso == 0] deformed_im_sponge_sitk = ip.array_to_sitk( deformed_im_sponge, im_ref=deformed_im_previous_sitk) return deformed_im_sponge_sitk
def multi_stage(setting, pair_info, overwrite=False): """ :param setting: :param pair_info: information of the pair to be registered. :param overwrite: :return: The output moved images and dvf will be written to the disk. 1: registration is performed correctly 2: skip overwriting 3: the dvf is available from the previous experiment [4, 2, 1]. Then just upsample it. """ stage_list = setting['ImagePyramidSchedule'] if setting['read_pair_mode'] == 'synthetic': deformed_im_ext = pair_info[0].get('deformed_im_ext', None) im_info_su = { 'data': pair_info[0]['data'], 'deform_exp': pair_info[0]['deform_exp'], 'type_im': pair_info[0]['type_im'], 'cn': pair_info[0]['cn'], 'dsmooth': pair_info[0]['dsmooth'], 'padto': pair_info[0]['padto'], 'deformed_im_ext': deformed_im_ext } moved_im_s0_address = su.address_generator(setting, 'MovedIm_AG', stage=1, **im_info_su) moved_torso_s1_address = su.address_generator(setting, 'MovedTorso_AG', stage=1, **im_info_su) moved_lung_s1_address = su.address_generator(setting, 'MovedLung_AG', stage=1, **im_info_su) else: moved_im_s0_address = su.address_generator(setting, 'MovedIm', pair_info=pair_info, stage=0, stage_list=stage_list) moved_torso_s1_address = None moved_lung_s1_address = None if setting['read_pair_mode'] == 'synthetic': if os.path.isfile(moved_im_s0_address) and os.path.isfile( moved_torso_s1_address): if not overwrite: logging.debug('overwrite=False, file ' + moved_im_s0_address + ' already exists, skipping .....') return 2 else: logging.debug('overwrite=True, file ' + moved_im_s0_address + ' already exists, but overwriting .....') else: if os.path.isfile(moved_im_s0_address): if not overwrite: logging.debug('overwrite=False, file ' + moved_im_s0_address + ' already exists, skipping .....') return 2 else: logging.debug('overwrite=True, file ' + moved_im_s0_address + ' already exists, but overwriting .....') pair_stage1 = real_pair.Images( setting, pair_info, stage=1, padto=setting['PadTo'] ['stage1']) # just read the original images without any padding pyr = dict() # pyr: a dictionary of pyramid images pyr['fixed_im_s1_sitk'] = pair_stage1.get_fixed_im_sitk() pyr['moving_im_s1_sitk'] = pair_stage1.get_moved_im_affine_sitk() pyr['fixed_im_s1'] = pair_stage1.get_fixed_im() pyr['moving_im_s1'] = pair_stage1.get_moved_im_affine() if setting['UseMask']: pyr['fixed_mask_s1_sitk'] = pair_stage1.get_fixed_mask_sitk() pyr['moving_mask_s1_sitk'] = pair_stage1.get_moved_mask_affine_sitk() if setting['read_pair_mode'] == 'real': if not (os.path.isdir( su.address_generator(setting, 'full_reg_folder', pair_info=pair_info, stage_list=stage_list))): os.makedirs( su.address_generator(setting, 'full_reg_folder', pair_info=pair_info, stage_list=stage_list)) setting['GPUMemory'], setting['NumberOfGPU'] = tfu.client.read_gpu_memory() time_before_dvf = time.time() # check if DVF is available from the previous experiment [4, 2, 1]. Then just upsample it. if stage_list in [[4, 2], [4]]: dvf0_address = su.address_generator(setting, 'dvf_s0', pair_info=pair_info, stage_list=stage_list) chosen_stage = None if stage_list == [4, 2]: chosen_stage = 2 elif stage_list == [4]: chosen_stage = 4 if chosen_stage is not None: dvf_s_up_address = su.address_generator(setting, 'dvf_s_up', pair_info=pair_info, stage=chosen_stage, stage_list=[4, 2, 1]) if os.path.isfile(dvf_s_up_address): logging.debug('DVF found from prev exp:' + dvf_s_up_address + ', only performing upsampling') dvf_s_up = sitk.ReadImage(dvf_s_up_address) dvf0 = ip.resampler_sitk( dvf_s_up, scale=1 / (chosen_stage / 2), im_ref_size=pyr['fixed_im_s1_sitk'].GetSize(), interpolator=sitk.sitkLinear) sitk.WriteImage(sitk.Cast(dvf0, sitk.sitkVectorFloat32), dvf0_address) return 3 for i_stage, stage in enumerate(setting['ImagePyramidSchedule']): mask_to_zero_stage = setting['network_dict']['stage' + str(stage)]['MaskToZero'] if stage != 1: pyr['fixed_im_s' + str(stage) + '_sitk'] = ip.downsampler_gpu( pyr['fixed_im_s1_sitk'], stage, default_pixel_value=setting['data'][ pair_info[0]['data']]['DefaultPixelValue']) pyr['moving_im_s' + str(stage) + '_sitk'] = ip.downsampler_gpu( pyr['moving_im_s1_sitk'], stage, default_pixel_value=setting['data'][ pair_info[1]['data']]['DefaultPixelValue']) if setting['UseMask']: pyr['fixed_mask_s' + str(stage) + '_sitk'] = ip.resampler_sitk( pyr['fixed_mask_s1_sitk'], scale=stage, im_ref=pyr['fixed_im_s' + str(stage) + '_sitk'], default_pixel_value=0, interpolator=sitk.sitkNearestNeighbor) pyr['moving_mask_s' + str(stage) + '_sitk'] = ip.resampler_sitk( pyr['moving_mask_s1_sitk'], scale=stage, im_ref=pyr['moving_im_s' + str(stage) + '_sitk'], default_pixel_value=0, interpolator=sitk.sitkNearestNeighbor) if setting['WriteMasksForLSTM']: # only to be used in sequential training (LSTM) if setting['read_pair_mode'] == 'synthetic': fixed_mask_stage_address = su.address_generator( setting, 'Deformed' + mask_to_zero_stage, stage=stage, **im_info_su) moving_mask_stage_address = su.address_generator( setting, mask_to_zero_stage, stage=stage, **im_info_su) fixed_im_stage_address = su.address_generator(setting, 'DeformedIm', stage=stage, **im_info_su) sitk.WriteImage( sitk.Cast( pyr['fixed_im_s' + str(stage) + '_sitk'], setting['data'][pair_info[1]['data']] ['ImageByte']), fixed_im_stage_address) sitk.WriteImage(pyr['fixed_mask_s' + str(stage) + '_sitk'], fixed_mask_stage_address) if im_info_su['dsmooth'] != 0 and stage == 4: # not overwirte original images moving_im_stage_address = su.address_generator( setting, 'Im', stage=stage, **im_info_su) sitk.WriteImage( sitk.Cast( pyr['moving_im_s' + str(stage) + '_sitk'], setting['data'][pair_info[1]['data']] ['ImageByte']), moving_im_stage_address) sitk.WriteImage( pyr['moving_mask_s' + str(stage) + '_sitk'], moving_mask_stage_address) else: fixed_im_stage_address = su.address_generator( setting, 'Im', stage=stage, **pair_info[0]) fixed_mask_stage_address = su.address_generator( setting, mask_to_zero_stage, stage=stage, **pair_info[0]) if not os.path.isfile(fixed_im_stage_address): sitk.WriteImage( sitk.Cast( pyr['fixed_im_s' + str(stage) + '_sitk'], setting['data'][pair_info[1]['data']] ['ImageByte']), fixed_im_stage_address) if not os.path.isfile(fixed_mask_stage_address): sitk.WriteImage( pyr['fixed_mask_s' + str(stage) + '_sitk'], fixed_mask_stage_address) if i_stage == 0: moved_im_affine_stage_address = su.address_generator( setting, 'MovedImBaseReg', pair_info=pair_info, stage=stage, **pair_info[1]) moved_mask_affine_stage_address = su.address_generator( setting, 'Moved' + mask_to_zero_stage + 'BaseReg', pair_info=pair_info, stage=stage, **pair_info[1]) if not os.path.isfile(moved_im_affine_stage_address): sitk.WriteImage( sitk.Cast( pyr['moving_im_s' + str(stage) + '_sitk'], setting['data'][pair_info[1] ['data']]['ImageByte']), moved_im_affine_stage_address) if not os.path.isfile(moved_mask_affine_stage_address): sitk.WriteImage( pyr['moving_mask_s' + str(stage) + '_sitk'], moved_mask_affine_stage_address) else: pyr['fixed_mask_s' + str(stage) + '_sitk'] = None pyr['moving_mask_s' + str(stage) + '_sitk'] = None input_regnet_moving_mask = None if i_stage == 0: input_regnet_moving = 'moving_im_s' + str(stage) + '_sitk' if setting['UseMask']: input_regnet_moving_mask = 'moving_mask_s' + str( stage) + '_sitk' else: previous_pyramid = setting['ImagePyramidSchedule'][i_stage - 1] dvf_composed_previous_up_sitk = 'DVF_s' + str( previous_pyramid) + '_composed_up_sitk' dvf_composed_previous_sitk = 'DVF_s' + str( previous_pyramid) + '_composed_sitk' if i_stage == 1: pyr[dvf_composed_previous_sitk] = pyr[ 'DVF_s' + str(setting['ImagePyramidSchedule'][i_stage - 1]) + '_sitk'] elif i_stage > 1: pyr[dvf_composed_previous_sitk] = sitk.Add( pyr['DVF_s' + str(setting['ImagePyramidSchedule'][i_stage - 2]) + '_composed_up_sitk'], pyr['DVF_s' + str(setting['ImagePyramidSchedule'][i_stage - 1]) + '_sitk']) pyr[dvf_composed_previous_up_sitk] = ip.upsampler_gpu( pyr[dvf_composed_previous_sitk], round(previous_pyramid / stage), output_shape_3d=pyr['fixed_im_s' + str(stage) + '_sitk'].GetSize()[::-1], ) if setting['WriteAfterEachStage'] and not setting['WriteNoDVF']: sitk.WriteImage( sitk.Cast(pyr[dvf_composed_previous_up_sitk], sitk.sitkVectorFloat32), su.address_generator(setting, 'dvf_s_up', pair_info=pair_info, stage=previous_pyramid, stage_list=stage_list)) dvf_t = sitk.DisplacementFieldTransform( pyr[dvf_composed_previous_up_sitk]) # after this line DVF_composed_previous_up_sitk is converted to a transform. so we need to load it again. pyr['moved_im_s' + str(stage) + '_sitk'] = ip.resampler_by_transform( pyr['moving_im_s' + str(stage) + '_sitk'], dvf_t, default_pixel_value=setting['data'][ pair_info[1]['data']]['DefaultPixelValue']) if setting['UseMask']: pyr['moved_mask_s' + str(stage) + '_sitk'] = ip.resampler_by_transform( pyr['moving_mask_s' + str(stage) + '_sitk'], dvf_t, default_pixel_value=0, interpolator=sitk.sitkNearestNeighbor) pyr[dvf_composed_previous_up_sitk] = dvf_t.GetDisplacementField() if setting['WriteAfterEachStage']: if setting['read_pair_mode'] == 'synthetic': moved_im_s_address = su.address_generator(setting, 'MovedIm_AG', stage=stage, **im_info_su) moved_mask_s_address = su.address_generator( setting, 'Moved' + mask_to_zero_stage + '_AG', stage=stage, **im_info_su) else: moved_im_s_address = su.address_generator( setting, 'MovedIm', pair_info=pair_info, stage=stage, stage_list=stage_list) moved_mask_s_address = su.address_generator( setting, 'Moved' + mask_to_zero_stage, pair_info=pair_info, stage=stage, stage_list=stage_list) sitk.WriteImage( sitk.Cast( pyr['moved_im_s' + str(stage) + '_sitk'], setting['data'][pair_info[1]['data']]['ImageByte']), moved_im_s_address) if setting['WriteMasksForLSTM']: sitk.WriteImage(pyr['moved_mask_s' + str(stage) + '_sitk'], moved_mask_s_address) input_regnet_moving = 'moved_im_s' + str(stage) + '_sitk' if setting['UseMask']: input_regnet_moving_mask = 'moved_mask_s' + str( stage) + '_sitk' pyr['DVF_s' + str(stage)] = np.zeros( np.r_[pyr['fixed_im_s' + str(stage) + '_sitk'].GetSize()[::-1], 3], dtype=np.float64) if setting['network_dict']['stage'+str(stage)]['R'] == 'Auto' and \ setting['network_dict']['stage'+str(stage)]['Ry'] == 'Auto': current_network_name = setting['network_dict'][ 'stage' + str(stage)]['NetworkDesign'] r_out_erode_default = setting['network_dict'][ 'stage' + str(stage)]['Ry_erode'] r_in, r_out, r_out_erode = network.utils.find_optimal_radius( pyr['fixed_im_s' + str(stage) + '_sitk'], current_network_name, r_out_erode_default, gpu_memory=setting['GPUMemory'], number_of_gpu=setting['NumberOfGPU']) else: r_in = setting['network_dict']['stage' + str(stage)][ 'R'] # Radius of normal resolution patch size. Total size is (2*R +1) r_out = setting['network_dict']['stage' + str(stage)][ 'Ry'] # Radius of output. Total size is (2*Ry +1) r_out_erode = setting['network_dict']['stage' + str(stage)][ 'Ry_erode'] # at the test time, sometimes there are some problems at the border logging.debug( 'stage' + str(stage) + ' ,' + pair_info[0]['data'] + ', CN{}, ImType{}, Size={}'.format( pair_info[0]['cn'], pair_info[0]['type_im'], pyr[ 'fixed_im_s' + str(stage) + '_sitk'].GetSize()[::-1]) + ', ' + setting['network_dict']['stage' + str(stage)]['NetworkDesign'] + ': r_in:{}, r_out:{}, r_out_erode:{}'.format( r_in, r_out, r_out_erode)) pair_pyramid = real_pair.Images( setting, pair_info, stage=stage, fixed_im_sitk=pyr['fixed_im_s' + str(stage) + '_sitk'], moved_im_affine_sitk=pyr[input_regnet_moving], fixed_mask_sitk=pyr['fixed_mask_s' + str(stage) + '_sitk'], moved_mask_affine_sitk=pyr[input_regnet_moving_mask], padto=setting['PadTo']['stage' + str(stage)], r_in=r_in, r_out=r_out, r_out_erode=r_out_erode) # building and loading network tf.reset_default_graph() images_tf = tf.placeholder( tf.float32, shape=[None, 2 * r_in + 1, 2 * r_in + 1, 2 * r_in + 1, 2], name="Images") bn_training = tf.placeholder(tf.bool, name='bn_training') dvf_tf = getattr( getattr( network, setting['network_dict']['stage' + str(stage)]['NetworkDesign']), 'network')(images_tf, bn_training) logging.debug(' Total number of variables %s' % (np.sum([ np.prod(v.get_shape().as_list()) for v in tf.trainable_variables() ]))) saver = tf.train.Saver(tf.global_variables(), max_to_keep=1) sess = tf.Session() saver.restore( sess, su.address_generator( setting, 'saved_model_with_step', current_experiment=setting['network_dict'][ 'stage' + str(stage)]['NetworkLoad'], step=setting['network_dict']['stage' + str(stage)]['GlobalStepLoad'])) while not pair_pyramid.get_sweep_completed(): # The pyr[DVF_S] is the numpy DVF which will be filled. the dvf_np is an output # patch from the network. We control the spatial location of both dvf in this function batch_im, win_center, win_r_before, win_r_after, predicted_begin, predicted_end = pair_pyramid.next_sweep_patch( ) time_before_gpu = time.time() [dvf_np] = sess.run([dvf_tf], feed_dict={ images_tf: batch_im, bn_training: 0 }) time_after_gpu = time.time() logging.debug('GPU: ' + pair_info[0]['data'] + ', CN{} center={} is done in {:.2f}s '.format( pair_info[0]['cn'], win_center, time_after_gpu - time_before_gpu)) pyr['DVF_s'+str(stage)][win_center[0] - win_r_before[0]: win_center[0] + win_r_after[0], win_center[1] - win_r_before[1]: win_center[1] + win_r_after[1], win_center[2] - win_r_before[2]: win_center[2] + win_r_after[2], :] = \ dvf_np[0, predicted_begin[0]:predicted_end[0], predicted_begin[1]:predicted_end[1], predicted_begin[2]:predicted_end[2], :] # rescaling dvf based on the voxel spacing: spacing_ref = [1.0 * stage for _ in range(3)] spacing_current = pyr['fixed_im_s' + str(stage) + '_sitk'].GetSpacing() for dim in range(3): pyr['DVF_s' + str(stage)][:, :, :, dim] = pyr['DVF_s' + str( stage)][:, :, :, dim] * spacing_current[dim] / spacing_ref[dim] pyr['DVF_s' + str(stage) + '_sitk'] = ip.array_to_sitk( pyr['DVF_s' + str(stage)], im_ref=pyr['fixed_im_s' + str(stage) + '_sitk'], is_vector=True) if i_stage == (len(setting['ImagePyramidSchedule']) - 1): # when all stages are finished, final dvf and moved image are written dvf_composed_final_sitk = 'DVF_s' + str(stage) + '_composed_sitk' if len(setting['ImagePyramidSchedule']) == 1: # need to upsample in the case that last stage is not 1 if stage == 1: pyr[dvf_composed_final_sitk] = pyr['DVF_s' + str(stage) + '_sitk'] else: pyr[dvf_composed_final_sitk] = ip.resampler_sitk( pyr['DVF_s' + str(stage) + '_sitk'], scale=1 / stage, im_ref_size=pyr['fixed_im_s1_sitk'].GetSize(), interpolator=sitk.sitkLinear) else: pyr[dvf_composed_final_sitk] = sitk.Add( pyr['DVF_s' + str(setting['ImagePyramidSchedule'][-2]) + '_composed_up_sitk'], pyr['DVF_s' + str(stage) + '_sitk']) if stage != 1: pyr[dvf_composed_final_sitk] = ip.resampler_sitk( pyr[dvf_composed_final_sitk], scale=1 / stage, im_ref_size=pyr['fixed_im_s1_sitk'].GetSize(), interpolator=sitk.sitkLinear) if not setting['WriteNoDVF']: sitk.WriteImage( sitk.Cast(pyr[dvf_composed_final_sitk], sitk.sitkVectorFloat32), su.address_generator(setting, 'dvf_s0', pair_info=pair_info, stage_list=stage_list)) dvf_t = sitk.DisplacementFieldTransform( pyr[dvf_composed_final_sitk]) pyr['moved_im_s0_sitk'] = ip.resampler_by_transform( pyr['moving_im_s1_sitk'], dvf_t, default_pixel_value=setting['data'][ pair_info[1]['data']]['DefaultPixelValue']) sitk.WriteImage( sitk.Cast(pyr['moved_im_s0_sitk'], setting['data'][pair_info[1]['data']]['ImageByte']), moved_im_s0_address) if setting['WriteMasksForLSTM']: mask_to_zero_stage = setting['network_dict'][ 'stage' + str(stage)]['MaskToZero'] if setting['read_pair_mode'] == 'synthetic': moving_mask_sitk = sitk.ReadImage( su.address_generator(setting, mask_to_zero_stage, stage=1, **im_info_su)) moved_mask_stage1 = ip.resampler_by_transform( moving_mask_sitk, dvf_t, default_pixel_value=0, interpolator=sitk.sitkNearestNeighbor) sitk.WriteImage( moved_mask_stage1, su.address_generator(setting, 'Moved' + mask_to_zero_stage + '_AG', stage=1, **im_info_su)) logging.debug('writing ' + su.address_generator(setting, 'Moved' + mask_to_zero_stage + '_AG', stage=1, **im_info_su)) time_after_dvf = time.time() logging.debug( pair_info[0]['data'] + ', CN{}, ImType{} is done in {:.2f}s '.format( pair_info[0]['cn'], pair_info[0]['type_im'], time_after_dvf - time_before_dvf)) return 0
def img_converter(data_folder, data, type_im, cn, ext='.mha', mha_folder_name='mha', point_folder_name='points'): """ convert img images to mha. reading image: 1) Size and voxel spacing of the images are available at https://www.dir-lab.com/ReferenceData.html 2) The superior-inferior axis needs to be flipped 3) Empty slices will be removed copd1_eBHCT.mha slice 0:1 copd2_eBHCT.mha slice 0:6 copd3_eBHCT.mha slice 0:9 copd4_eBHCT.mha slice 0:9 copd5_eBHCT.mha slice NA copd6_eBHCT.mha slice 0:2 copd7_eBHCT.mha slice 0:9 copd8_eBHCT.mha slice 0:7 copd9_eBHCT.mha slice 0:19 copd10_iBHCT.mah slice 0 4) Index modification: 4a) The superior-inferior axis are flipped. The reason is that to make it more similar to SPREAD study. 4b) The indices start at 1. We like them to start at 0. 4c) change indices of landmarks based on the removed slices 5) Normalize the intensity by subtracting by -1024 6) Set the outside value to -2048 :param ext :param cn: :param type_im :param data_folder :param data :param mha_folder_name :param point_folder_name :return: converted mha image and converted landmark files: example: copd1_eBHCT.mha copd1_300_eBH_world_r1_tr.txt: landmarks in world coordinate (truncated) copd1_300_eBH_world_r1_elx.txt: landmarks in world coordinate with two additional lines for elastix copd1_300_eBH_xyz_r1_tr.txt: landmark in indices copd1_300_eBH_xyz_r1_elx.txt: landmark in indices with two additional lines for elastix """ if data == 'DIR-Lab_4D': type_im_list = [ 'T00', 'T10', 'T20', 'T30', 'T40', 'T50', 'T60', 'T70', 'T80', 'T90' ] data_folder_sub = data_folder + 'DIR-Lab/4DCT/' if cn < 6: im_img_name = 'Images/case' + str( cn) + '_' + type_im_list[type_im] + '_s.img' else: im_img_name = 'Images/case' + str( cn) + '_' + type_im_list[type_im] + '.img' im_img_folder = data_folder_sub + 'Case' + str(cn) + 'Pack/' if cn == 8: im_img_folder = data_folder_sub + 'Case' + str(cn) + 'Deploy/' im_mha_name = 'case' + str(cn) + '_' + type_im_list[type_im] + ext im_mha_folder = data_folder_sub + mha_folder_name + '/case' + str( cn) + '/' point_folder = data_folder_sub + point_folder_name + '/case' + str( cn) + '/' if cn < 6: index_tr_old_address_list = [ im_img_folder + '/Sampled4D/case' + str(cn) + '_4D-75_' + type_im_list[type_im] + '.txt', im_img_folder + '/ExtremePhases/case' + str(cn) + '_300_' + type_im_list[type_im] + '_xyz.txt' ] else: index_tr_old_address_list = [ im_img_folder + '/Sampled4D/case' + str(cn) + '_4D-75_' + type_im_list[type_im] + '.txt', im_img_folder + '/ExtremePhases/case' + str(cn) + '_dirLab300_' + type_im_list[type_im] + '_xyz.txt' ] index_tr_new_address_list = [ point_folder + '/case' + str(cn) + '_4D-75_' + type_im_list[type_im] + '_xyz_tr.txt', point_folder + '/case' + str(cn) + '_300_' + type_im_list[type_im] + '_xyz_tr.txt' ] index_elx_new_address_list = [ point_folder + '/case' + str(cn) + '_4D-75_' + type_im_list[type_im] + '_xyz_elx.txt', point_folder + '/case' + str(cn) + '_300_' + type_im_list[type_im] + '_xyz_elx.txt' ] point_tr_new_address_list = [ point_folder + '/case' + str(cn) + '_4D-75_' + type_im_list[type_im] + '_world_tr.txt', point_folder + '/case' + str(cn) + '_300_' + type_im_list[type_im] + '_world_tr.txt' ] point_elx_new_address_list = [ point_folder + '/case' + str(cn) + '_4D-75_' + type_im_list[type_im] + '_world_elx.txt', point_folder + '/case' + str(cn) + '_300_' + type_im_list[type_im] + '_world_elx.txt' ] dirlab_header = dirlab_4dct_header() elif data == 'DIR-Lab_COPD': type_im_list = ['i', 'e'] data_folder_sub = data_folder + 'DIR-Lab/COPDgene/' im_img_name = 'copd' + str( cn) + '_' + type_im_list[type_im] + 'BHCT.img' im_img_folder = data_folder_sub + 'copd' + str(cn) + '/' im_mha_name = 'copd' + str( cn) + '_' + type_im_list[type_im] + 'BHCT' + ext im_mha_folder = data_folder_sub + mha_folder_name + '/' point_folder = data_folder_sub + point_folder_name index_tr_old_address_list = [ im_img_folder + 'copd' + str(cn) + '_300_' + type_im_list[type_im] + 'BH_xyz_r1.txt' ] index_tr_new_address_list = [ point_folder + '/copd' + str(cn) + '_300_' + type_im_list[type_im] + 'BH_xyz_r1_tr.txt' ] index_elx_new_address_list = [ point_folder + '/copd' + str(cn) + '_300_' + type_im_list[type_im] + 'BH_xyz_r1_elx.txt' ] point_tr_new_address_list = [ point_folder + '/copd' + str(cn) + '_300_' + type_im_list[type_im] + 'BH_world_r1_tr.txt' ] point_elx_new_address_list = [ point_folder + '/copd' + str(cn) + '_300_' + type_im_list[type_im] + 'BH_world_r1_elx.txt' ] dirlab_header = dirlab_copd_header() else: raise ValueError('Data=' + data + ", it should be in ['DIR-Lab_4D', 'DIR-Lab_COPD']") if not os.path.isdir(im_mha_folder): os.makedirs(im_mha_folder) if not os.path.isdir(point_folder): os.makedirs(point_folder) im_img_address = im_img_folder + im_img_name im_mha_address = im_mha_folder + im_mha_name if not os.path.isfile(im_mha_address): # 1,2) reading image:---------------------------------------------------------------- fid = open(im_img_address, 'rb') im_data = np.fromfile(fid, np.int16) image_old = im_data.reshape(dirlab_header['case' + str(cn)]['Size'][::-1]) image_old = np.flip( image_old, axis=0) # The superior-inferior axis needs to be flipped origin = [0, 0, 0] image = copy.deepcopy(image_old) # reading landmarks: for ii, index_tr_old_address in enumerate(index_tr_old_address_list): index_tr_new_address = index_tr_new_address_list[ii] index_elx_new_address = index_elx_new_address_list[ii] point_tr_new_address = point_tr_new_address_list[ii] point_elx_new_address = point_elx_new_address_list[ii] if os.path.isfile(index_tr_old_address): index_tr_old_raw = np.loadtxt(index_tr_old_address) # 4a&b) The superior-inferior axis is flipped. be careful about that indices start at 1. after converting to zero-start, # there is no -1 in the SI direction. index_tr_old = np.array([[ index_tr_old_raw[i, 0] - 1, index_tr_old_raw[i, 1] - 1, image_old.shape[0] - index_tr_old_raw[i, 2] ] for i in range(index_tr_old_raw.shape[0])]) # 3) remove empty slices only in DIR-Lab_COPD----------------------------------------- if data == 'DIR-Lab_COPD': image, slices_to_remove = remove_empty_slices(image_old) print(im_img_name + ' slices are removed: ' + str(slices_to_remove)) shift_indices = len(slices_to_remove) shift_world = shift_indices * dirlab_header[ 'case' + str(cn)]['Spacing'][2] origin[2] = shift_world # 4c) change indices of landmarks based on the removed slices index_tr_new = [[ index_tr_old[i, 0], index_tr_old[i, 1], index_tr_old[i, 2] - shift_indices ] for i in range(index_tr_old.shape[0])] else: index_tr_new = index_tr_old.copy() np.savetxt(index_tr_new_address, index_tr_new, fmt='%d') point_tr_new = ip.index_to_world( index_tr_new, spacing=dirlab_header['case' + str(cn)]['Spacing'], origin=origin) np.savetxt(point_tr_new_address, point_tr_new, fmt='%-9.3f') open_text = open(index_tr_new_address, "r") number_of_landmarks = index_tr_new.shape[0] with open(index_elx_new_address, "w") as open_elx: open_elx.write('index \n') open_elx.write(str(number_of_landmarks) + ' \n') open_elx.write(open_text.read()) open_text.close() open_text = open(point_tr_new_address, "r") with open(point_elx_new_address, "w") as open_elx: open_elx.write('point \n') open_elx.write(str(number_of_landmarks) + ' \n') open_elx.write(open_text.read()) open_text.close() # 5) normalize the intensity image = image - 1024 # we are not sure about the slope and intercept. # 6) set the outside value to -2048 image[image == -3024] = -2048 image_sitk = ip.array_to_sitk( image, spacing=dirlab_header['case' + str(cn)]['Spacing'], origin=origin) sitk.WriteImage(image_sitk, im_mha_address) print('case' + str(cn) + ' type' + str(type_im) + ' is done..')
def check_downsampled_base_reg(setting, stage, base_reg=None, pair_info=None, mask_to_zero_stage=None): if 'DownSamplingByGPU' not in setting.keys(): setting['DownSamplingByGPU'] = False im_info_moving = pair_info[1] im_list_downsample = [ { 'Image': 'MovedImBaseReg', 'interpolator': 'BSpline', 'DefaultPixelValue': setting['data'][im_info_moving['data']]['DefaultPixelValue'], 'ImageByte': setting['data'][im_info_moving['data']]['ImageByte'] }, { 'Image': 'Moved' + mask_to_zero_stage + 'BaseReg', 'interpolator': 'NearestNeighbor', 'DefaultPixelValue': 0, 'ImageByte': sitk.sitkInt8 }, ] # # im_stage_address = su.address_generator(setting, 'MovedImBaseReg', pair_info=pair_info, # stage=stage, base_reg=base_reg, **im_info_moving) # mask_stage_address = su.address_generator(setting, 'Moved' + mask_to_zero_stage + 'BaseReg', pair_info=pair_info, # stage=stage, base_reg=base_reg, **im_info_moving) for im_dict in im_list_downsample: im_stage_address = su.address_generator(setting, im_dict['Image'], stage=stage, pair_info=pair_info, base_reg=base_reg, **im_info_moving) if not os.path.isfile(im_stage_address): im_s1_sitk = sitk.ReadImage( su.address_generator(setting, im_dict['Image'], stage=1, pair_info=pair_info, base_reg=base_reg, **im_info_moving)) if setting['DownSamplingByGPU'] and im_dict[ 'Image'] == 'MovedImBaseReg': im_s1 = sitk.GetArrayFromImage(im_s1_sitk) im_stage = ip.downsampler_gpu( im_s1, stage, normalize_kernel=True, default_pixel_value=im_dict['DefaultPixelValue']) im_stage_sitk = ip.array_to_sitk( im_stage, origin=im_s1_sitk.GetOrigin(), spacing=tuple(i * stage for i in im_s1_sitk.GetSpacing()), direction=im_s1_sitk.GetDirection()) else: if im_dict['interpolator'] == 'NearestNeighbor': interpolator = sitk.sitkNearestNeighbor elif im_dict['interpolator'] == 'BSpline': interpolator = sitk.sitkBSpline else: raise ValueError( "interpolator should be in ['NearestNeighbor', 'BSpline']" ) if im_dict['Image'] in [ 'MovedTorsoBaseReg', 'MovedLungBaseReg' ]: im_ref_sitk = sitk.ReadImage( su.address_generator(setting, 'MovedImBaseReg', pair_info=pair_info, stage=stage, base_reg=base_reg, **im_info_moving)) else: im_ref_sitk = None im_stage_sitk = ip.resampler_sitk( im_s1_sitk, scale=stage, im_ref=im_ref_sitk, default_pixel_value=im_dict['DefaultPixelValue'], interpolator=interpolator) sitk.WriteImage(sitk.Cast(im_stage_sitk, im_dict['ImageByte']), im_stage_address) return 0
def single_freq(setting, im_info, stage, im_input_sitk, gonna_generate_next_im=False): im_info_su = { 'data': im_info['data'], 'deform_exp': im_info['deform_exp'], 'type_im': im_info['type_im'], 'cn': im_info['cn'], 'dsmooth': im_info['dsmooth'], 'stage': stage, 'padto': im_info['padto'] } seed_number = ag_utils.seed_number_by_im_info( im_info, 'single_freq', stage=stage, gonna_generate_next_im=gonna_generate_next_im) deform_number = im_info['deform_number'] if gonna_generate_next_im: max_deform = setting['deform_exp'][ im_info['deform_exp']]['NextIm_MaxDeform'] dim_im = 3 # The deformation of the NextIm is always 3D seed_number = seed_number + 1 grid_border_to_zero = setting['deform_exp'][ im_info['deform_exp']]['SingleFrequency_SetGridBorderToZero'][0] grid_spacing = setting['deform_exp'][ im_info['deform_exp']]['SingleFrequency_BSplineGridSpacing'][0] grid_smoothing_sigma = [ i / stage for i in setting['deform_exp'][im_info['deform_exp']] ['SingleFrequency_GridSmoothingSigma'][0] ] bspline_transform_address = su.address_generator( setting, 'NextBSplineTransform', **im_info_su) bspline_im_address = su.address_generator(setting, 'NextBSplineTransformIm', **im_info_su) else: max_deform = setting['deform_exp'][im_info['deform_exp']]['MaxDeform'] * \ setting['deform_exp'][im_info['deform_exp']]['SingleFrequency_MaxDeformRatio'][deform_number] dim_im = 3 grid_border_to_zero = setting['deform_exp'][im_info['deform_exp']][ 'SingleFrequency_SetGridBorderToZero'][deform_number] grid_spacing = setting['deform_exp'][im_info['deform_exp']][ 'SingleFrequency_BSplineGridSpacing'][deform_number] grid_smoothing_sigma = [ i / stage for i in setting['deform_exp'][im_info['deform_exp']] ['SingleFrequency_GridSmoothingSigma'][deform_number] ] bspline_transform_address = su.address_generator( setting, 'BSplineTransform', **im_info_su) bspline_im_address = su.address_generator(setting, 'BSplineTransformIm', **im_info_su) random_state = np.random.RandomState(seed_number) if setting['DVFPad_S' + str(stage)] > 0: # im_input is already zeropadded in this case padded_mm = setting['DVFPad_S' + str(stage)] * im_input_sitk.GetSpacing()[0] grid_border_to_zero = (grid_border_to_zero + np.ceil( np.repeat(padded_mm, int(dim_im)) / grid_spacing)).astype(np.int) if len(np.unique(im_input_sitk.GetSpacing())) > 1: raise ValueError( 'dvf_generation: padding is only implemented for isotropic voxel size. current voxel size = [{}, {}, {}]' .format(im_input_sitk.GetSpacing()[0], im_input_sitk.GetSpacing()[1], im_input_sitk.GetSpacing()[2])) bcoeff = bspline_coeff(im_input_sitk, max_deform, grid_border_to_zero, grid_smoothing_sigma, grid_spacing, random_state, dim_im, artificial_generation='single_frequency') if setting['WriteBSplineTransform']: sitk.WriteTransform(bcoeff, bspline_transform_address) bspline_im_sitk_tuple = bcoeff.GetCoefficientImages() bspline_im = np.concatenate( (np.expand_dims(sitk.GetArrayFromImage(bspline_im_sitk_tuple[0]), axis=-1), np.expand_dims(sitk.GetArrayFromImage(bspline_im_sitk_tuple[1]), axis=-1), np.expand_dims(sitk.GetArrayFromImage(bspline_im_sitk_tuple[1]), axis=-1)), axis=-1) bspline_spacing = bspline_im_sitk_tuple[0].GetSpacing() bspling_origin = [ list(bspline_im_sitk_tuple[0].GetOrigin())[i] + list(im_input_sitk.GetOrigin())[i] for i in range(3) ] bspline_direction = im_input_sitk.GetDirection() bspline_im_sitk = ip.array_to_sitk(bspline_im, origin=bspling_origin, spacing=bspline_spacing, direction=bspline_direction, is_vector=True) sitk.WriteImage(bspline_im_sitk, bspline_im_address) dvf_filter = sitk.TransformToDisplacementFieldFilter() dvf_filter.SetSize(im_input_sitk.GetSize()) dvf_sitk = dvf_filter.Execute(bcoeff) dvf = sitk.GetArrayFromImage(dvf_sitk) mask_to_zero = setting['deform_exp'][im_info['deform_exp']]['MaskToZero'] if mask_to_zero is not None and not gonna_generate_next_im: sigma = setting['deform_exp'][im_info['deform_exp']][ 'SingleFrequency_BackgroundSmoothingSigma'][deform_number] dvf = do_mask_to_zero_gaussian(setting, im_info_su, dvf, mask_to_zero, stage, max_deform, sigma) if setting['deform_exp'][im_info['deform_exp']]['DVFNormalization']: dvf = normalize_dvf(dvf, max_deform) return dvf
def get_dvf_and_deformed_images_seq(setting, im_info=None, stage_sequence=None, mode_synthetic_dvf='generation'): """ This function generates the synthetic displacement vector fields and writes them to disk and returns them. If synthetic DVFs are already generated and can be found on the disk, this function just reads and returns them. Please note that in 2D setting, we still have a 3D DVF with zero values for the third direction. :param setting: :param im_info: 'data': 'deform_exp': 'type_im': 'CN": Case Number: (Image Number )Please note that it starts from 1 not 0 'dsmooth': This variable is used to generate another deformed version of the moving image. Then, use that image to make synthetic DVFs. More information available on [sokooti2017nonrigid] 'deform_method' 'deform_number' :param stage_sequence :param mode_synthetic_dvf: 'generation': generating images 'reading': : only reading images without generating them. In this mode, the function will just wait :return im image with mentioned ImageType and CN :return deformed_im Deformed image by applying the synthetic DeformedDVF_ on the Im_ :return dvf Syntethic DVF """ im_info_su = { 'data': im_info['data'], 'deform_exp': im_info['deform_exp'], 'type_im': im_info['type_im'], 'cn': im_info['cn'], 'dsmooth': im_info['dsmooth'], 'padto': im_info['padto'] } # A dictionary of arguments, which only be used in setting_utils.address_generator. This dictionary helps to have shorter code line. logging.debug('artifical_generation[' + mode_synthetic_dvf + ']: Data=' + im_info['data'] + ', TypeIm=' + str(im_info['type_im']) + ', CN=' + str(im_info['cn']) + ' Dsmooth=' + str(im_info['dsmooth']) + ' D=' + str(im_info['deform_number']) + ' starting') time_before = time.time() if stage_sequence != [4, 2, 1]: raise ValueError(' not implemented ') # later # for stage in stage_sequence: # if stage != 1: # check_downsampled_images(setting, im_info, stage) mask_to_zero = setting['deform_exp'][im_info['deform_exp']]['MaskToZero'] # this is the last image to write by registration: if setting['UseRegisteredImages']: moved_mask_s1 = su.address_generator(setting, 'Moved' + mask_to_zero + '_AG', stage=1, **im_info_su) while not os.path.isfile(moved_mask_s1): logging.debug('artifical_generation[' + mode_synthetic_dvf + ']: Data=' + im_info['data'] + ', TypeIm=' + str(im_info['type_im']) + ', CN=' + str(im_info['cn']) + ' Dsmooth=' + str(im_info['dsmooth']) + ' D=' + str(im_info['deform_number']) + ' waiting for moved images by registration') time.sleep(5) if (time.time() - os.path.getmtime(moved_mask_s1)) < 5: time.sleep(5) else: check_downsampled_images(setting, im_info, stage=2) check_downsampled_images(setting, im_info, stage=4) fixed_im_seq = dict() fixed_mask_seq = dict() moved_im_seq = dict() moved_mask_seq = dict() for stage in stage_sequence: fixed_im_seq['stage' + str(stage)] = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator( setting, 'DeformedIm', deformed_im_ext=im_info['deformed_im_ext'], stage=stage, **im_info_su))) fixed_mask_seq['stage' + str(stage)] = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator( setting, 'Deformed' + mask_to_zero, deformed_im_ext=im_info['deformed_im_ext'], stage=stage, **im_info_su))) moved_im_seq['stage4'] = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, 'Im', stage=4, **im_info_su))) moved_mask_seq['stage4'] = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, mask_to_zero, stage=4, **im_info_su))) for stage in [2, 1]: if setting['UseRegisteredImages']: moved_im_seq['stage' + str(stage)] = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, 'MovedIm_AG', stage=stage, **im_info_su))) moved_mask_seq['stage' + str(stage)] = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, 'Moved' + mask_to_zero + '_AG', stage=stage, **im_info_su))) else: moved_im_seq['stage' + str(stage)] = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, 'Im', stage=stage, **im_info_su))) moved_mask_seq['stage' + str(stage)] = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, mask_to_zero, stage=stage, **im_info_su))) if mask_to_zero is not None: for stage in stage_sequence: size_fixed_im = np.array( np.shape(fixed_im_seq['stage' + str(stage)])) size_fixed_mask = np.array( np.shape(fixed_mask_seq['stage' + str(stage)])) size_diff = size_fixed_im - size_fixed_mask if abs(sum(size_diff)): if sum(size_diff) > 0: # mask is smaller so we need to pad it fixed_mask_seq['stage' + str(stage)] = np.pad( fixed_mask_seq['stage' + str(stage)], ((0, size_diff[0]), (0, size_diff[1]), (0, size_diff[2])), 'constant', constant_values=(0, )) else: # mask is bigger size_mask_crop = size_fixed_mask + size_diff fixed_mask_seq['stage' + str(stage)] = fixed_mask_seq[ 'stage' + str(stage)][0:size_mask_crop[0], 0:size_mask_crop[1], 0:size_mask_crop[2]] size_moved_im = np.array( np.shape(moved_im_seq['stage' + str(stage)])) size_moved_mask = np.array( np.shape(moved_mask_seq['stage' + str(stage)])) size_diff = size_moved_im - size_moved_mask if abs(sum(size_diff)): logging.debug( 'warning size are not same.............. size_dife={}'. format(size_diff)) if sum(size_diff) > 0: # mask is smaller so we need to pad it moved_mask_seq['stage' + str(stage)] = np.pad( moved_mask_seq['stage' + str(stage)], ((0, size_diff[0]), (0, size_diff[1]), (0, size_diff[2])), 'constant', constant_values=(0, )) else: # mask is bigger moved_mask_seq['stage' + str(stage)] = moved_mask_seq[ 'stage' + str(stage)][0:size_diff[0], 0:size_diff[1], 0:size_diff[2]] fixed_im_seq['stage' + str(stage)][fixed_mask_seq[ 'stage' + str(stage)] == 0] = setting['data'][ im_info['data']]['DefaultPixelValue'] moved_im_seq['stage' + str(stage)][moved_mask_seq[ 'stage' + str(stage)] == 0] = setting['data'][ im_info['data']]['DefaultPixelValue'] for stage in stage_sequence: # stage 4 and 2 has more padding in order to be possible that all patches have the same center if setting['ImPad_S' + str(stage)] > 0: fixed_im_seq['stage' + str(stage)] = np.pad( fixed_im_seq['stage' + str(stage)], setting['ImPad_S' + str(stage)], 'constant', constant_values=( setting['data'][im_info['data']]['DefaultPixelValue'], )) moved_im_seq['stage' + str(stage)] = np.pad( moved_im_seq['stage' + str(stage)], setting['ImPad_S' + str(stage)], 'constant', constant_values=( setting['data'][im_info['data']]['DefaultPixelValue'], )) dvf_threshold_list = setting['DVFThresholdList'] dvf_label_address = su.address_generator( setting, 'DeformedDVFLabel', stage=1, dvf_threshold_list=dvf_threshold_list, **im_info_su) if not os.path.isfile(dvf_label_address): dvf_address = su.address_generator(setting, 'DeformedDVF', stage=1, **im_info_su) dvf = sitk.GetArrayFromImage(sitk.ReadImage(dvf_address)) dvf_magnitude = np.sqrt( np.square(dvf[:, :, :, 0]) + np.square(dvf[:, :, :, 1]) + np.square(dvf[:, :, :, 2])) dvf_label = np.zeros(dvf_magnitude.shape, dtype=np.int8) for i_label in range(len(dvf_threshold_list) - 1): dvf_label[(dvf_threshold_list[i_label] <= dvf_magnitude) & ( dvf_magnitude < dvf_threshold_list[i_label + 1])] = i_label dvf_label_sitk = ip.array_to_sitk( dvf_label, im_ref=sitk.ReadImage( su.address_generator( setting, 'DeformedIm', deformed_im_ext=im_info['deformed_im_ext'], stage=stage, **im_info_su))) sitk.WriteImage(sitk.Cast(dvf_label_sitk, sitk.sitkInt8), dvf_label_address) else: dvf_label = sitk.GetArrayFromImage(sitk.ReadImage(dvf_label_address)) # no mask for now # dvf_mask = sitk.GetArrayFromImage(sitk.ReadImage(su.address_generator( # setting, 'Deformed' + setting['Label_Mask'], deformed_im_ext=im_info['deformed_im_ext'], stage=stage, **im_info_su))) # dvf_label[dvf_mask == 0] = 0 time_after = time.time() logging.debug('artifical_generation[' + mode_synthetic_dvf + ']: Data=' + im_info['data'] + ', TypeIm=' + str(im_info['type_im']) + ', CN=' + str(im_info['cn']) + ' Dsmooth=' + str(im_info['dsmooth']) + ' D=' + str(im_info['deform_number']) + ' is Done in {:.3f}s'.format(time_after - time_before)) return fixed_im_seq, moved_im_seq, dvf_label, fixed_mask_seq
def check_downsampled_images(setting, im_info, stage): padto = im_info['padto'] im_info_su = { 'data': im_info['data'], 'deform_exp': im_info['deform_exp'], 'type_im': im_info['type_im'], 'cn': im_info['cn'], 'dsmooth': im_info['dsmooth'] } im_list_downsample = [{ 'Image': 'Im', 'interpolator': 'BSpline', 'DefaultPixelValue': setting['data'][im_info['data']]['DefaultPixelValue'], 'ImageByte': setting['data'][im_info['data']]['ImageByte'] }, { 'Image': 'Lung', 'interpolator': 'NearestNeighbor', 'DefaultPixelValue': 0, 'ImageByte': sitk.sitkInt8 }, { 'Image': 'Torso', 'interpolator': 'NearestNeighbor', 'DefaultPixelValue': 0, 'ImageByte': sitk.sitkInt8 }, { 'Image': 'DeformedIm', 'interpolator': 'BSpline', 'DefaultPixelValue': setting['data'][im_info['data']]['DefaultPixelValue'], 'ImageByte': setting['data'][im_info['data']]['ImageByte'] }, { 'Image': 'DeformedLung', 'interpolator': 'NearestNeighbor', 'DefaultPixelValue': 0, 'ImageByte': sitk.sitkInt8 }, { 'Image': 'DeformedTorso', 'interpolator': 'NearestNeighbor', 'DefaultPixelValue': 0, 'ImageByte': sitk.sitkInt8 }] for im_dict in im_list_downsample: im_stage_address = su.address_generator( setting, im_dict['Image'], stage=stage, padto=padto, deformed_im_ext=im_info['deformed_im_ext'], **im_info_su) # remove the second condition later, that was for fixing some images ['Im', 'Lung'] --> I removed if not os.path.isfile(im_stage_address): im_s1_sitk = sitk.ReadImage( su.address_generator( setting, im_dict['Image'], stage=1, padto=padto, deformed_im_ext=im_info['deformed_im_ext'], **im_info_su)) if setting['DownSamplingByGPU'] and im_dict[ 'Image'] == 'OriginalIm': im_s1 = sitk.GetArrayFromImage(im_s1_sitk) im_stage = ip.downsampler_gpu( im_s1, stage, normalize_kernel=True, default_pixel_value=im_dict['DefaultPixelValue']) im_stage_sitk = ip.array_to_sitk( im_stage, origin=im_s1_sitk.GetOrigin(), spacing=tuple(i * stage for i in im_s1_sitk.GetSpacing()), direction=im_s1_sitk.GetDirection()) else: if im_dict['interpolator'] == 'NearestNeighbor': interpolator = sitk.sitkNearestNeighbor elif im_dict['interpolator'] == 'BSpline': interpolator = sitk.sitkBSpline else: raise ValueError( "interpolator should be in ['NearestNeighbor', 'BSpline']" ) if im_dict['Image'] in ['Torso', 'Lung']: im_ref_sitk = sitk.ReadImage( su.address_generator(setting, 'Im', stage=stage, padto=padto, **im_info_su)) else: im_ref_sitk = None im_stage_sitk = ip.resampler_sitk( im_s1_sitk, scale=stage, im_ref=im_ref_sitk, default_pixel_value=im_dict['DefaultPixelValue'], interpolator=interpolator) # for debugging # sitk.WriteImage(sitk.Cast(im_stage_sitk, im_dict['ImageByte']), # su.address_generator(setting, im_dict['Image'], stage=stage, padto=None, **im_info_su)) if padto is not None: dim_im = setting['Dim'] pad_before = np.zeros(dim_im, dtype=np.int) pad_after = np.zeros(dim_im, dtype=np.int) im_size = np.array(im_stage_sitk.GetSize()) extra_to_pad = padto - im_size for d in range(dim_im): if extra_to_pad[d] < 0: raise ValueError( 'size of the padto=' + str(padto) + ' should be smaller than the size of the image {}' .format(im_size)) elif extra_to_pad[d] == 0: pad_before[d] = 0 pad_after[d] = 0 else: if extra_to_pad[d] % 2 == 0: pad_before[d] = np.int(extra_to_pad[d] / 2) pad_after[d] = np.int(extra_to_pad[d] / 2) else: pad_before[d] = np.floor(extra_to_pad[d] / 2) pad_after[d] = np.floor( extra_to_pad[d] / 2) + 1 pad_before = [int(p) for p in pad_before] pad_after = [int(p) for p in pad_after] im_stage_sitk = sitk.ConstantPad( im_stage_sitk, [pad_before[0], pad_before[1], pad_before[2]], [pad_after[0], pad_after[1], pad_after[2]], constant=im_dict['DefaultPixelValue'], ) sitk.WriteImage(sitk.Cast(im_stage_sitk, im_dict['ImageByte']), im_stage_address) return 0
def generate_next_im(setting, im_info, stage): im_info_su = { 'data': im_info['data'], 'deform_exp': im_info['deform_exp'], 'type_im': im_info['type_im'], 'cn': im_info['cn'], 'dsmooth': im_info['dsmooth'], 'stage': stage, 'padto': im_info['padto'] } next_folder = su.address_generator(setting, 'NextFolder', **im_info_su) if not os.path.exists(next_folder): os.makedirs(next_folder) original_im_sitk = sitk.ReadImage( su.address_generator(setting, 'OriginalIm', **im_info_su)) next_dvf = dvf_generation.single_freq(setting, im_input_sitk=original_im_sitk, im_info=im_info, stage=stage, gonna_generate_next_im=True) next_dvf_sitk = ip.array_to_sitk(next_dvf, is_vector=True, im_ref=original_im_sitk) if setting['verbose_image']: sitk.WriteImage(sitk.Cast(next_dvf_sitk, sitk.sitkVectorFloat32), su.address_generator(setting, 'NextDVF', **im_info_su)) dvf_t = sitk.DisplacementFieldTransform( next_dvf_sitk ) # After this line you cannot save NextDVF any more !!!!!!!!! next_im_clean_sitk = ip.resampler_by_transform( original_im_sitk, dvf_t, im_ref=original_im_sitk, default_pixel_value=setting['data'][ im_info['data']]['DefaultPixelValue']) if setting['UseLungMask']: original_mask_sitk = sitk.ReadImage( su.address_generator(setting, 'OriginalLung', **im_info_su)) next_mask_sitk = ip.resampler_by_transform( original_mask_sitk, dvf_t, default_pixel_value=0, interpolator=sitk.sitkNearestNeighbor) sitk.WriteImage( sitk.Cast(next_mask_sitk, sitk.sitkInt8), su.address_generator(setting, 'NextLung', **im_info_su)) if setting['UseTorsoMask']: original_torso_sitk = sitk.ReadImage( su.address_generator(setting, 'OriginalTorso', **im_info_su)) next_torso_sitk = ip.resampler_by_transform( original_torso_sitk, dvf_t, default_pixel_value=0, interpolator=sitk.sitkNearestNeighbor) sitk.WriteImage( sitk.Cast(next_torso_sitk, sitk.sitkInt8), su.address_generator(setting, 'NextTorso', **im_info_su)) next_im_sponge_sitk = intensity_augmentation.add_sponge_model( setting, im_info, stage=stage, deformed_im_previous_sitk=next_im_clean_sitk, dvf=next_dvf, gonna_generate_next_im=True) next_im_sitk = intensity_augmentation.add_noise( setting, im_info, stage=stage, deformed_im_previous_sitk=next_im_sponge_sitk, gonna_generate_next_im=True) sitk.WriteImage( sitk.Cast(next_im_sitk, setting['data'][im_info['data']]['ImageByte']), su.address_generator(setting, 'NextIm', **im_info_su))
def get_dvf_and_deformed_images(setting, im_info=None, stage=None, mode_synthetic_dvf='generation'): """ This function generates the synthetic displacement vector fields and writes them to disk and returns them. If synthetic DVFs are already generated and can be found on the disk, this function just reads and returns them. Please note that in 2D setting, we still have a 3D DVF with zero values for the third direction. :param setting: :param im_info: 'data': 'deform_exp': 'type_im': 'CN": Case Number: (Image Number )Please note that it starts from 1 not 0 'dsmooth': This variable is used to generate another deformed version of the moving image. Then, use that image to make synthetic DVFs. More information available on [sokooti2017nonrigid] 'deform_method' 'deform_number' :param stage :param mode_synthetic_dvf: 'generation': generating images 'reading': : only reading images without generating them. In this mode, the function will just wait :return im image with mentioned ImageType and CN :return deformed_im Deformed image by applying the synthetic DeformedDVF_ on the Im_ :return dvf Syntethic DVF """ im_info_su = { 'data': im_info['data'], 'deform_exp': im_info['deform_exp'], 'type_im': im_info['type_im'], 'cn': im_info['cn'], 'dsmooth': im_info['dsmooth'], 'stage': stage, 'padto': im_info['padto'] } # A dictionary of arguments, which only be used in setting_utils.address_generator. This dictionary helps to have shorter code line. if stage > 1: check_downsampled_original_images(setting, im_info, stage) if im_info['dsmooth'] == 0: im_sitk = ip.ReadImage( su.address_generator(setting, 'OriginalIm', **im_info_su)) if setting['UseTorsoMask']: im_torso_sitk = sitk.ReadImage( su.address_generator(setting, 'OriginalTorso', **im_info_su)) if setting['UseLungMask']: im_lung_sitk = sitk.ReadImage( su.address_generator(setting, 'OriginalLung', **im_info_su)) else: next_im_address = (su.address_generator(setting, 'NextIm', **im_info_su)) if not os.path.isfile(next_im_address): if mode_synthetic_dvf == 'reading': wait_for_image(next_im_address) if mode_synthetic_dvf == 'generation': logging.debug( 'artifical_generation[generation]: start ' + su.address_generator( setting, 'NextIm', print_mode=True, **im_info_su)) generate_next_im(setting, im_info=im_info, stage=stage) im_sitk = ip.ReadImage(next_im_address, waiting_time=3) if setting['UseTorsoMask']: # please note that torso might be created a few minutes after NextIm. So we have to wait for the torso. im_torso_address = su.address_generator(setting, 'NextTorso', **im_info_su) im_lung_address = su.address_generator(setting, 'NextLung', **im_info_su) if mode_synthetic_dvf == 'reading': wait_for_image(im_torso_address) wait_for_image(im_lung_address) im_torso_sitk = ip.ReadImage(im_torso_address, waiting_time=1) im_lung_sitk = ip.ReadImage(im_lung_address, waiting_time=1) im = sitk.GetArrayFromImage(im_sitk) start_time = time.time() dvf_address = su.address_generator(setting, 'DeformedDVF', **im_info_su) deformed_im_address = su.address_generator( setting, 'DeformedIm', deformed_im_ext=im_info['deformed_im_ext'], **im_info_su) if not os.path.isfile(deformed_im_address): if mode_synthetic_dvf == 'reading': wait_for_image(dvf_address) wait_for_image(deformed_im_address) if mode_synthetic_dvf == 'generation': if os.path.isfile(dvf_address): dvf_sitk = sitk.ReadImage(dvf_address) else: logging.debug( 'artifical_generation[generation]: start ' + su.address_generator( setting, 'DeformedDVF', print_mode=True, **im_info_su)) if not os.path.exists( su.address_generator(setting, 'DFolder', ** im_info_su)): os.makedirs( su.address_generator(setting, 'DFolder', **im_info_su)) if setting['DVFPad_S' + str(stage)] > 0: pad = setting['DVFPad_S' + str(stage)] dvf_ref_sitk = sitk.ConstantPad( im_sitk, [pad, pad, pad], [pad, pad, pad], constant=setting['data'][ im_info['data']]['DefaultPixelValue']) else: dvf_ref_sitk = im_sitk if im_info['deform_method'] == 'single_frequency': dvf = dvf_generation.single_freq( setting, im_info, stage=stage, im_input_sitk=dvf_ref_sitk) elif im_info['deform_method'] == 'mixed_frequency': dvf = dvf_generation.mixed_freq(setting, im_info, stage=stage) elif im_info['deform_method'] == 'translation': dvf = dvf_generation.translation( setting, im_info, stage=stage, im_input_sitk=dvf_ref_sitk) elif im_info['deform_method'] == 'zero': dvf = dvf_generation.zero(im_input_sitk=dvf_ref_sitk) elif im_info['deform_method'] == 'respiratory_motion': dvf = dvf_generation.respiratory_motion( setting, im_info, stage=stage, moving_image_mode='Exhale') else: raise ValueError('DeformMethod= ' + im_info['deform_method'] + ' is not defined. ') dvf_sitk = ip.array_to_sitk(dvf, im_ref=dvf_ref_sitk, is_vector=True) sitk.WriteImage(sitk.Cast(dvf_sitk, sitk.sitkVectorFloat32), dvf_address) if setting['WriteDVFStatistics']: dvf_statistics(setting, dvf, spacing=im_sitk.GetSpacing()[::-1], im_info=im_info, stage=stage) deformed_im_clean_address = su.address_generator( setting, 'DeformedIm', deformed_im_ext='Clean', **im_info_su) deformed_torso_address = su.address_generator( setting, 'DeformedTorso', **im_info_su) deformed_lung_address = su.address_generator( setting, 'DeformedLung', **im_info_su) write_intermediate_images = setting['deform_exp'][im_info[ 'deform_exp']]['WriteIntermediateIntensityAugmentation'] if not os.path.isfile(deformed_im_clean_address) or \ (setting['UseTorsoMask'] and not os.path.isfile(deformed_torso_address)) or \ (setting['UseLungMask'] and not os.path.isfile(deformed_lung_address)): dvf_t = sitk.DisplacementFieldTransform( sitk.Cast(dvf_sitk, sitk.sitkVectorFloat64) ) # After this line you cannot save dvf_sitk any more !!!!!!!!! if not os.path.isfile(deformed_im_clean_address): deformed_im_clean_sitk = ip.resampler_by_transform( im_sitk, dvf_t, im_ref=im_sitk, default_pixel_value=setting['data'][ im_info['data']]['DefaultPixelValue']) if write_intermediate_images: sitk.WriteImage( sitk.Cast( deformed_im_clean_sitk, setting['data'][im_info['data']]['ImageByte']), deformed_im_clean_address) else: deformed_im_clean_sitk = sitk.ReadImage( deformed_im_clean_address) if setting['UseTorsoMask']: deformed_torso_sitk = ip.resampler_by_transform( im_torso_sitk, dvf_t, im_ref=im_sitk, default_pixel_value=0, interpolator=sitk.sitkNearestNeighbor) sitk.WriteImage(sitk.Cast(deformed_torso_sitk, sitk.sitkInt8), deformed_torso_address) if setting['UseLungMask']: deformed_lung_sitk = ip.resampler_by_transform( im_lung_sitk, dvf_t, im_ref=im_sitk, default_pixel_value=0, interpolator=sitk.sitkNearestNeighbor) sitk.WriteImage(sitk.Cast(deformed_lung_sitk, sitk.sitkInt8), deformed_lung_address) if deformed_im_clean_address != deformed_im_address: deformed_im_ext_combined = ['Clean'] deformed_im_previous_sitk = sitk.Image(deformed_im_clean_sitk) for i_ext, deformed_im_ext_current in enumerate( im_info['deformed_im_ext']): if deformed_im_ext_current != 'Clean': # deformed_im_previous_address = su.address_generator(setting, 'DeformedIm', deformed_im_ext=deformed_im_ext_combined, **im_info_su) # deformed_im_previous_sitk = ip.ReadImage(deformed_im_previous_address, waiting_time=2) deformed_im_ext_combined.append( deformed_im_ext_current) deformed_im_ext_combined_address = su.address_generator( setting, 'DeformedIm', deformed_im_ext=deformed_im_ext_combined, **im_info_su) if not os.path.isfile( deformed_im_ext_combined_address): if deformed_im_ext_current == 'Noise': deformed_im_current_sitk = intensity_augmentation.add_noise( setting, im_info, stage, deformed_im_previous_sitk= deformed_im_previous_sitk) elif deformed_im_ext_current == 'Occluded': deformed_im_current_sitk = intensity_augmentation.add_occlusion( setting, im_info, stage, deformed_im_previous_sitk= deformed_im_previous_sitk) elif deformed_im_ext_current == 'Sponge': deformed_im_current_sitk = intensity_augmentation.add_sponge_model( setting, im_info, stage, deformed_im_previous_sitk= deformed_im_previous_sitk) else: raise ValueError( "deformed_im_ext should be in ['Noise', 'Sponge', 'Occluded']" ) if write_intermediate_images or i_ext == ( len(im_info['deformed_im_ext']) - 1): sitk.WriteImage( sitk.Cast( deformed_im_current_sitk, setting['data'][ im_info['data']]['ImageByte']), deformed_im_ext_combined_address) deformed_im_previous_sitk = sitk.Image( deformed_im_current_sitk) else: deformed_im_previous_sitk = sitk.ReadImage( deformed_im_ext_combined_address) dvf_sitk = ip.ReadImage(dvf_address, waiting_time=4) dvf = sitk.GetArrayFromImage(dvf_sitk) deformed_im_sitk = ip.ReadImage(deformed_im_address, waiting_time=2) deformed_im = sitk.GetArrayFromImage(deformed_im_sitk) dvf = dvf.astype(np.float32) mask_to_zero = setting['deform_exp'][im_info['deform_exp']]['MaskToZero'] if mask_to_zero is not None: im_mask = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, mask_to_zero, **im_info_su))) im[im_mask == 0] = setting['data'][ im_info['data']]['DefaultPixelValue'] deformed_mask = sitk.GetArrayFromImage( sitk.ReadImage( su.address_generator(setting, 'Deformed' + mask_to_zero, **im_info_su))) deformed_im[deformed_mask == 0] = setting['data'][ im_info['data']]['DefaultPixelValue'] # UseTorsoMask has the same size as DVF not the ImPad. We've already used im_torso to # mask the image. Later we use it only to find the indices. So it should have the # the same size as the dvf. dvf_pad = setting['DVFPad_S' + str(stage)] if dvf_pad > 0: im_mask = np.pad(im_mask, dvf_pad, 'constant', constant_values=(0, )) else: im_mask = None im_pad = setting['ImPad_S' + str(stage)] if im_pad > 0: im = np.pad( im, im_pad, 'constant', constant_values=( setting['data'][im_info['data']]['DefaultPixelValue'], )) deformed_im = np.pad( deformed_im, im_pad, 'constant', constant_values=( setting['data'][im_info['data']]['DefaultPixelValue'], )) end_time = time.time() if setting['verbose']: logging.debug('artifical_generation[' + mode_synthetic_dvf + ']: Data=' + im_info['data'] + ', TypeIm=' + str(im_info['type_im']) + ', CN=' + str(im_info['cn']) + ' Dsmooth=' + str(im_info['dsmooth']) + ' D=' + str(im_info['deform_number']) + ' is Done in {:.3f}s'.format(end_time - start_time)) return im, deformed_im, dvf, im_mask