def label_ROI(roiDir, ROI_exp, allRoisView, roiBaseImage, label): #for ROI in fnmatch.filter(os.listdir(roiDir), ROI_exp): #print(f'{ROI_exp} {label}') found = False for ROI in os.listdir(roiDir): #print('here ' + ROI + ' ' + ROI_exp) if fnmatch.fnmatch(ROI.lower(), ROI_exp): #print('yes ' + ROI) print(os.path.join(roiDir, ROI)) roisImage = itk.imread(os.path.join(roiDir, ROI)) # resize roisImage = gt.applyTransformation(input=roisImage, like=roiBaseImage, force_resample=True, interpolation_mode='NN') #itk.imwrite(roisImage, f'resized_{ROI}') roisView = itk.array_from_image(roisImage) allRoisView += roisView * label if np.any(allRoisView > label): f = open(f'{taskfolder_3D}/errorlog.txt', 'a') f.write("Overlapping structures: " + str(int(allRoisView[allRoisView > label][0] - label)) + " and " + str(label) + "\n") f.close() print("Overlapping structures: " + str(int(allRoisView[allRoisView > label][0] - label)) + " and " + str(label)) allRoisView = np.where(allRoisView > label, label, allRoisView) #return allRoisView, False found = True #return allRoisView, True return allRoisView, found
def faf_ACGM_image(gm, acf, factor=4.168696975): if gm.GetImageDimension() != 2: print("gm image dimension (" + str(gm.GetImageDimension()) + ") is not 2") sys.exit(1) if acf.GetImageDimension() != 2: print("acf image dimension (" + str(acf.GetImageDimension()) + ") is not 2") sys.exit(1) resampleACF = gt.applyTransformation(input=acf, like=gm, force_resample=True, pad=-1) resampleACFArray = itk.array_from_image(resampleACF) gmArray = itk.array_from_image(gm) acgmArray = np.zeros(gmArray.shape) negativeACFIndex = np.where(resampleACFArray == -1) positiveACFIndex = np.where(resampleACFArray != -1) acgmArray[negativeACFIndex] = factor * gmArray[negativeACFIndex] acgmArray[positiveACFIndex] = resampleACFArray[positiveACFIndex] * gmArray[ positiveACFIndex] acgmImage = itk.image_from_array(acgmArray) acgmImage.CopyInformation(gm) return acgmImage
def test_dvh_volume(self): logger.info('Test_DVH test_dvh_volume') tmpdirpath = tempfile.mkdtemp() filenameStruct = wget.download( "https://gitlab.in2p3.fr/opengate/gatetools_data/-/raw/master/rtstruct.dcm?inline=false", out=tmpdirpath, bar=None) structset = pydicom.read_file(os.path.join(tmpdirpath, filenameStruct)) filenameDose = wget.download( "https://gitlab.in2p3.fr/opengate/gatetools_data/-/raw/master/rtdose.dcm?inline=false", out=tmpdirpath, bar=None) doseImage = gt.read_3d_dicom([os.path.join(tmpdirpath, filenameDose)]) transformImage = gt.applyTransformation(input=doseImage, neworigin=[-176, -320, -235]) aroi = gt.region_of_interest(structset, "PTV") mask = aroi.get_mask(transformImage, corrected=False) doseValues, volumePercentage = createDVH(transformImage, mask, bins=100, useCm3=True) self.assertTrue(np.all(volumePercentage >= 0)) self.assertTrue(np.all(volumePercentage <= 115120)) self.assertTrue(len(doseValues) == 100) self.assertTrue(len(volumePercentage) == 100) shutil.rmtree(tmpdirpath)
def update_roi_characteristics(db, r, background=0): ''' Update roi volume, density and mass ''' im_roi = syd.find_one(db['Image'], roi_id=r['id']) dicom_struct = syd.find_one(db['DicomStruct'], id=r['dicom_struct_id']) if dicom_struct is not None: im_ct = syd.find_one(db['Image'], dicom_series_id=dicom_struct['dicom_series_id']) else: im_ct = syd.find_one( db['Image'], frame_of_reference_uid=r['frame_of_reference_uid'], modality='CT') file_img = syd.find_one(db['File'], id=im_roi['file_mhd_id']) if im_ct is not None: file_img_ct = syd.find_one(db['File'], id=im_ct['file_mhd_id']) else: print(f'Could not find the CT file image for the roi {r.id}') return 0 filename_im = os.path.join( db.absolute_data_folder, os.path.join(file_img['folder'], file_img['filename'])) filename_ct = os.path.join( db.absolute_data_folder, os.path.join(file_img_ct['folder'], file_img_ct['filename'])) roi = itk.imread(filename_im) ct = itk.imread(filename_ct) array_im = itk.array_from_image(roi) spacing = roi.GetSpacing() ### Volume ### e = np.count_nonzero(array_im != background) volume_elem = spacing[0] * spacing[1] * spacing[2] # spacing is in mm volume_elem = volume_elem * 0.001 # convert mm3 to cm3 (/1000) volume = e * volume_elem r['volume'] = volume syd.update_one(db['Roi'], r) ### Density ### mask = gt.applyTransformation(input=roi, like=ct, force_resample=True, interpolation_mode='NN') stats = gt.imageStatistics(input=ct, mask=mask) HU_mean = stats['mean'] density = 1 + (HU_mean / 1000) r['density'] = density syd.update_one(db['Roi'], r) ### Mass ### mass = np.multiply(volume, density) r['mass'] = mass syd.update_one(db['Roi'], r) return 1
def attenuation_local(prim_per_proj, proj_path): if not os.path.exists(proj_path): os.makedirs(proj_path) interp_secfolder = 'interpolated_secondaries' if not os.path.exists(interp_secfolder): os.makedirs(interp_secfolder) #IMC=PMC×#primaries_per_projection×(512/128)^2+SMC size_primary = 512 size_scatter = 64 factor = prim_per_proj * pow(size_primary / size_scatter, 2) # get all the primary projections primary_files = sorted(glob.glob('./output/primary*.mha')) interpolate_secondaries(secondary_folder, interp_secfolder, 4, len(primary_files)) for projnum, primary_filename in enumerate(primary_files): # load the primary, secondary, and flatfield primary = itk.imread(primary_filename) flatfield = itk.imread(primary_filename.replace( "primary", "flatfield")) #not needed anymore - secondaries only have half the projections, so the secondary projection number = projnum/2 #second_projnum = projnum // 4 #secondary = itk.imread(f'./output/secondary{second_projnum:04d}.mha') secondary = itk.imread( f'{interp_secfolder}/secondary{projnum:04d}.mha') resizedsecondary = gt.applyTransformation( input=secondary, newsize=itk.size(primary), neworigin=itk.origin(primary), adaptive=True, force_resample=True) flatfield = itk.MultiplyImageFilter(flatfield, factor) prim_second = itk.AddImageFilter( itk.MultiplyImageFilter(primary, factor), resizedsecondary) #flatfield_sq = itk.MultiplyImageFilter(flatfield,flatfield) S = itk.DivideImageFilter(prim_second, flatfield) S = itk.MultiplyImageFilter(S, itk.MedianImageFilter(flatfield)) attenuation = itk.LogImageFilter(S) #attenuation = itk.LogImageFilter(itk.DivideImageFilter(prim_second,flatfield)) attenuation = itk.MultiplyImageFilter(attenuation, -1) itk.imwrite( attenuation, primary_filename.replace('./output/primary', f'{proj_path}/attenuation_sec'))
def test_dvh_compute_d(self): logger.info('Test_DVH test_dvh_compute_d') tmpdirpath = tempfile.mkdtemp() filenameStruct = wget.download("https://github.com/OpenGATE/GateTools/raw/master/dataTest/rtstruct.dcm", out=tmpdirpath, bar=None) structset = pydicom.read_file(os.path.join(tmpdirpath, filenameStruct)) filenameDose = wget.download("https://github.com/OpenGATE/GateTools/raw/master/dataTest/rtdose.dcm", out=tmpdirpath, bar=None) doseImage = gt.read_3d_dicom([os.path.join(tmpdirpath, filenameDose)]) transformImage = gt.applyTransformation(input=doseImage, neworigin=[-176, -320, -235]) aroi = gt.region_of_interest(structset, "PTV") mask = aroi.get_mask(transformImage, corrected=False) doseValues, volumePercentage = createDVH(transformImage, mask) self.assertTrue(np.isclose(computeD(doseValues, volumePercentage, 95), 0.15428162737918327)) shutil.rmtree(tmpdirpath)
def test_dvh(self): logger.info('Test_DVH test_dvh') tmpdirpath = tempfile.mkdtemp() filenameStruct = wget.download("https://github.com/OpenGATE/GateTools/raw/master/dataTest/rtstruct.dcm", out=tmpdirpath, bar=None) structset = pydicom.read_file(os.path.join(tmpdirpath, filenameStruct)) filenameDose = wget.download("https://github.com/OpenGATE/GateTools/raw/master/dataTest/rtdose.dcm", out=tmpdirpath, bar=None) doseImage = gt.read_3d_dicom([os.path.join(tmpdirpath, filenameDose)]) transformImage = gt.applyTransformation(input=doseImage, neworigin=[-176, -320, -235]) aroi = gt.region_of_interest(structset, "PTV") mask = aroi.get_mask(transformImage, corrected=False) doseValues, volumePercentage = createDVH(transformImage, mask, bins=100) self.assertTrue(np.allclose(doseValues, np.array([0.10095047205686569, 0.3028514161705971, 0.5047523528337479, 0.7066532969474792, 0.9085542261600494, 1.1104551553726196, 1.3123561143875122, 1.5142570734024048, 1.7161580324172974, 1.9180589318275452, 2.119959831237793, 2.3218607902526855, 2.523761749267578, 2.7256627082824707, 2.9275636672973633, 3.129464626312256, 3.3313655853271484, 3.533266544342041, 3.7351675033569336, 3.9370683431625366, 4.13896918296814, 4.340870141983032, 4.542771100997925, 4.744672060012817, 4.94657301902771, 5.1484739780426025, 5.350374937057495, 5.552275896072388, 5.75417685508728, 5.956077814102173, 6.157978773117065, 6.359879732131958, 6.561780691146851, 6.763681650161743, 6.965582609176636, 7.167483568191528, 7.369384527206421, 7.5712854862213135, 7.773186445236206, 7.9750871658325195, 8.176988124847412, 8.378889083862305, 8.580790042877197, 8.78269100189209, 8.984591960906982, 9.186492919921875, 9.388393878936768, 9.59029483795166, 9.792195796966553, 9.994096755981445, 10.195997714996338, 10.39789867401123, 10.599799633026123, 10.801700592041016, 11.003601551055908, 11.2055025100708, 11.407403469085693, 11.609304428100586, 11.811205387115479, 12.013106346130371, 12.215007305145264, 12.416908264160156, 12.618809223175049, 12.820710182189941, 13.022610664367676, 13.224511623382568, 13.426412582397461, 13.628313541412354, 13.830214500427246, 14.032115459442139, 14.234016418457031, 14.435917377471924, 14.637818336486816, 14.839719295501709, 15.041620254516602, 15.243521213531494, 15.445422172546387, 15.64732313156128, 15.849224090576172, 16.051124572753906, 16.253026008605957, 16.454927444458008, 16.656827926635742, 16.858728408813477, 17.060629844665527, 17.262531280517578, 17.464431762695312, 17.666332244873047, 17.868233680725098, 18.07013511657715, 18.272035598754883, 18.473936080932617, 18.675837516784668, 18.87773895263672, 19.079639434814453, 19.281539916992188, 19.483440399169922, 19.685341835021973, 19.887243270874023, 20.089143753051758]))) self.assertTrue(np.all(volumePercentage >= 0)) self.assertTrue(np.all(volumePercentage <= 100)) self.assertTrue(len(doseValues) == 100) self.assertTrue(len(volumePercentage) == 100) shutil.rmtree(tmpdirpath)
def imageStatistics(input=None, mask=None, resample=False, histogramBins=1000): if input is None: logger.error("Set an input") sys.exit(1) inputArray = itk.array_from_image(input) outputStats = {} outputStats["nbPixel"] = inputArray.size if not mask is None: if resample: mask = gt.applyTransformation(input=mask, like=input, force_resample=True) if not np.allclose(mask.GetSpacing(), input.GetSpacing()): logger.error("Input and mask do not have the same spacing") sys.exit(1) if not np.allclose(mask.GetOrigin(), input.GetOrigin()): logger.error("Input and mask do not have the same origin") sys.exit(1) if not np.allclose(itk.array_from_matrix(mask.GetDirection()), itk.array_from_matrix(input.GetDirection())): logger.error("Input and mask do not have the same direction") sys.exit(1) if not np.allclose(mask.GetLargestPossibleRegion().GetSize(), input.GetLargestPossibleRegion().GetSize()): logger.error("Input and mask do not have the same size") sys.exit(1) maskArray = itk.array_from_image(mask) if len(np.where(maskArray > 1)[0]) >0: logger.error("The mask seems to be a non-binary image") index = np.where(maskArray == 1) outputStats["nbPixel"] = len(index[0]) inputArray = inputArray[index] outputStats["minimum"] = np.amin(inputArray) outputStats["maximum"] = np.amax(inputArray) outputStats["sum"] = np.sum(inputArray) outputStats["median"] = np.median(inputArray) outputStats["mean"] = np.mean(outputStats["sum"]/outputStats["nbPixel"]) outputStats["variance"] = np.var(inputArray) outputStats["sigma"] = np.sqrt(outputStats["variance"]) outputStats["hist"] = np.histogram(inputArray, histogramBins) return outputStats
def match_with_lyon(realcbcts_path, FOV_mask_path): FOV_mask_image = itk.imread(FOV_mask_path) FOV_mask = itk.GetArrayFromImage(FOV_mask_image) files = sorted(glob.glob(f'{realcbcts_path}/*/cbct*.mhd')) x_masked = [] x_wo_outliers = [] merged_values_masked = [] merged_counts_masked = [] merged_values_wo_outliers = [] merged_counts_wo_outliers = [] for ind, fname in enumerate(files): lyon_image = itk.imread(fname) # resize the image #img_name = 'rennes_' + os.path.basename(fname).replace('.nii.gz','') resized_lyonimg = gt.applyTransformation( input=lyon_image, newsize=itk.size(FOV_mask_image), force_resample=True, pad=-1024) #, adaptive=True #itk.imwrite(resized_lyonimg, 'resized_lyon/resizedlyonimg_' + os.path.basename(fname) + '.mha') lyonimg_origin = resized_lyonimg.GetOrigin() lyon_array = itk.GetArrayFromImage(resized_lyonimg) # get patient mask #cbct_id = os.path.basename(fname).replace('cbct','').replace('.nii.gz') #patient_mask_name = f'patientmask{cbct_id}.nii.gz' patient_mask_path = fname.replace('cbct', 'patientmask') mask_command = f"clitkExtractPatient -i {fname} -o {patient_mask_path} --upper=-800" os.system(mask_command) # load and apply patient mask lyon_maskimage = itk.imread(patient_mask_path) resized_mask_img = gt.applyTransformation(input=lyon_maskimage, like=resized_lyonimg, force_resample=True, pad=0, interpolation_mode='NN') #itk.imwrite(resized_mask_img, 'resized_rennes_images/resizedpatientmask_' + os.path.basename(fname) + '.mha') lyonpatient_mask = itk.GetArrayFromImage(resized_mask_img) lyon_mask_intersection = (lyonpatient_mask == 1) & (FOV_mask == 1) lyon_masked = np.ma.compressed( np.around(np.ma.masked_array(lyon_array, ~lyon_mask_intersection))) # lyon_values_mask = np.where( (lyon_array <= np.percentile(lyon_array, 0.5)) | (lyon_array >= np.percentile(lyon_array, 99.5)), 0, 1) # lyon_wo_outliers = np.ma.compressed( np.around( np.ma.masked_array(lyon_array, (lyon_values_mask == 0) | (lyonpatient_mask == 0) | (FOV_mask == 0)))) # #rennes_wo_outliers = np.ma.compressed(np.around(np.ma.masked_array(rennes_array,(rennes_values_mask==0) ))) # #x_masked =np.concatenate((x_masked, lyon_masked )) #x_wo_outliers =np.concatenate((x_wo_outliers, lyon_wo_outliers )) target = np.around(lyon_masked.ravel()) t_values_masked, t_counts_masked = np.unique(target, return_counts=True) merged_values_masked, merged_counts_masked = merge_sorted_arrays( t_values_masked, t_counts_masked, merged_values_masked, merged_counts_masked) target = np.around(lyon_wo_outliers.ravel()) t_values_wo_outliers, t_counts_wo_outliers = np.unique( target, return_counts=True) merged_values_wo_outliers, merged_counts_wo_outliers = merge_sorted_arrays( t_values_wo_outliers, t_counts_wo_outliers, merged_values_wo_outliers, merged_counts_wo_outliers) #print(t_values,t_counts) #print(merged_values,merged_counts) matching_values_masked = f'{realcbcts_path}/matching_values_masked_Lyon.txt' np.savetxt(matching_values_masked, merged_values_masked, fmt='%d') matching_counts_masked = f'{realcbcts_path}/matching_counts_masked_Lyon.txt' #t_counts.tofile(matching_counts,format='%d') np.savetxt(matching_counts_masked, merged_counts_masked, fmt='%d') matching_values_wo_outliers = f'{realcbcts_path}/matching_values_wo_outliers_Lyon.txt' np.savetxt(matching_values_wo_outliers, merged_values_wo_outliers, fmt='%d') matching_counts_wo_outliers = f'{realcbcts_path}/matching_counts_wo_outliers_Lyon.txt' #t_counts.tofile(matching_counts,format='%d') np.savetxt(matching_counts_wo_outliers, merged_counts_wo_outliers, fmt='%d')
def attenuation(prim_per_proj, proj_path, num_jobs): if not os.path.exists(proj_path): os.makedirs(proj_path) interp_secfolder = 'interpolated_secondaries' if not os.path.exists(interp_secfolder): os.makedirs(interp_secfolder) for results_dir in glob.glob('./results.*'): if os.path.isfile(f'{results_dir}/primary0000.mha'): primary_folder = results_dir elif os.path.isfile(f'{results_dir}/secondary0000.mha'): secondary_folder = results_dir #IMC=PMC×#primaries_per_projection×(512/128)^2+SMC size_primary = 512 size_scatter = 64 # get the number of jobs actually completed from the run folder of the scatter simulation #secondary_runfolder = secondary_folder.replace('results','run') #job_completed = len(glob.glob(f"{secondary_runfolder}/output.*")) with open(f"num_completed_jobs.txt", "r") as f: job_completed = int(f.readline()) factor = (prim_per_proj * job_completed / num_jobs) * pow( size_primary / size_scatter, 2) # get all the primary projections primary_files = sorted(glob.glob(f'{primary_folder}/primary*.mha')) interpolate_secondaries(secondary_folder, interp_secfolder, 4, len(primary_files)) for projnum, primary_filename in enumerate(primary_files): # load the primary, secondary, and flatfield primary = itk.imread(primary_filename) flatfield = itk.imread(primary_filename.replace( "primary", "flatfield")) #not needed anymore - secondaries only have half the projections, so the secondary projection number = projnum/2 #second_projnum = projnum // 4 #secondary = itk.imread(f'{secondary_folder}/secondary{second_projnum:04d}.mha') secondary = itk.imread( f'{interp_secfolder}/secondary{projnum:04d}.mha') resizedsecondary = gt.applyTransformation( input=secondary, newsize=itk.size(primary), neworigin=itk.origin(primary), adaptive=True, force_resample=True) flatfield = itk.MultiplyImageFilter(flatfield, factor) prim_second = itk.AddImageFilter( itk.MultiplyImageFilter(primary, factor), resizedsecondary) #flatfield_sq = itk.MultiplyImageFilter(flatfield,flatfield) S = itk.DivideImageFilter(prim_second, flatfield) S = itk.MultiplyImageFilter(S, itk.MedianImageFilter(flatfield)) attenuation = itk.LogImageFilter(S) #attenuation = itk.LogImageFilter(itk.DivideImageFilter(prim_second,flatfield)) attenuation = itk.MultiplyImageFilter(attenuation, -1) attenuation_path = primary_filename.replace( f'{os.path.dirname(primary_filename)}/primary', f'{proj_path}/attenuation_sec') itk.imwrite(attenuation, attenuation_path)
def copy_images(images_training, images_test, task_id, task_name_3D, trainingimage_ch0_name, trainingimage_ch1_name, testimage_ch0_name, testimage_ch1_name, ROI_list, ROI_list_alternatenames, label_dict): image_identifier_3D = 'CBCT_3D' # copy the 3D cbct images to imagesTr in .nii.gz format global taskfolder_3D taskfolder_3D = f'{nnUNet_raw_data}/Task{task_id:03d}_{task_name_3D}' json_filename_3D = f'{taskfolder_3D}/dataset.json' imagesTr_foldername_3D = f'{taskfolder_3D}/imagesTr/' imagesTs_foldername_3D = f'{taskfolder_3D}/imagesTs/' labelsTr_foldername_3D = f'{taskfolder_3D}/labelsTr/' labelsTs_foldername_3D = f'{taskfolder_3D}/labelsTs/' maybe_mkdir_p(imagesTr_foldername_3D) maybe_mkdir_p(imagesTs_foldername_3D) maybe_mkdir_p(labelsTr_foldername_3D) maybe_mkdir_p(labelsTs_foldername_3D) open(f"{taskfolder_3D}/errorlog.txt", "w").close() train_patient_names = [] test_patient_names = [] patient_ind = 0 for patient_folder in sorted(glob.glob(f'{images_training}/*')): print(patient_folder) with open(f'{taskfolder_3D}/errorlog.txt', 'a') as f: f.write(str(patient_ind) + " - " + patient_folder + ": \n") casename_3D = f'{image_identifier_3D}_{patient_ind:04d}' train_patient_names.append(casename_3D) # channel 1 = simu CBCT if 'CLB' in patient_folder: if (apply_matching == False) & ('correctedN4' in trainingimage_ch1_name): cbct_image_path = f'{patient_folder}/{realCBCT_N4imagename}' elif (apply_matching == False) & ('swn_normalized' in trainingimage_ch1_name): cbct_image_path = f'{patient_folder}/{realCBCT_SWNimagename}' else: cbct_image_path = glob.glob(f'{patient_folder}/cbct*.mhd')[0] else: cbct_image_path = f'{patient_folder}/{trainingimage_ch1_name}' # reduce image size and save in the 3D task folder cbct_3D_filename = f'{imagesTr_foldername_3D}/{casename_3D}_0001.nii.gz' #if (apply_matching == False) & ('correctedN4' in trainingimage_name): # no need to resize, already 2 mm spacing # #shutil.copy(cbct_image_path, imagesTr_foldername_3D) # #os.rename(f'{imagesTr_foldername_3D}/{trainingimage_name}', cbct_3D_filename) # convert_command= f'gt_image_convert {cbct_image_path} -o {cbct_3D_filename}' #else: # convert_command= f'gt_affine_transform -i {cbct_image_path} --newspacing=2,2,2 -o {cbct_3D_filename} -fr -a' if spacing2mm == True: convert_command = f'gt_affine_transform -i {cbct_image_path} --newspacing=2,2,2 -o {cbct_3D_filename} -fr -a' os.system(convert_command) else: convert_command = f'gt_image_convert {cbct_image_path} -o {cbct_3D_filename}' os.system(convert_command) # load the simu CBCT image to get the size cbct_image = itk.imread(cbct_3D_filename) cbct_origin = cbct_image.GetOrigin() # channel 0 = real CT if 'CLB' in patient_folder: if (apply_matching == False) & ('correctedN4' in trainingimage_ch0_name): ct_image_path = f'{patient_folder}/{realCBCT_N4imagename}' elif (apply_matching == False) & ('swn_normalized' in trainingimage_ch0_name): ct_image_path = f'{patient_folder}/{realCBCT_SWNimagename}' else: ct_image_path = glob.glob(f'{patient_folder}/cbct*.mhd')[0] else: ct_image_path = f'{patient_folder}/{trainingimage_ch0_name}' # reduce image size and save in the 3D task folder ct_3D_filename = f'{imagesTr_foldername_3D}/{casename_3D}_0000.nii.gz' ct_image = itk.imread(ct_image_path) # resize the image to same size as the simulated cbct if itk.size(cbct_image) == itk.size(ct_image): if spacing2mm == True: convert_command = f'gt_affine_transform -i {ct_image_path} --newspacing=2,2,2 -o {ct_3D_filename} -fr -a' os.system(convert_command) else: convert_command = f'gt_image_convert {ct_image_path} -o {ct_3D_filename}' os.system(convert_command) else: ct_image = gt.applyTransformation(input=ct_image, like=cbct_image, force_resample=True, pad=-1024) itk.imwrite(ct_image, ct_3D_filename) # copy and register label (ROI) with the cbct ROI_dir = f'{patient_folder}/ROI' allRoisImage = create_segmentation_map(ROI_list, ROI_list_alternatenames, ROI_dir, cbct_3D_filename, '') label_3D_filename = f'{labelsTr_foldername_3D}/{casename_3D}.nii.gz' if cropimages == True: crop_training_images(cbct_3D_filename, ct_3D_filename, label_3D_filename, allRoisImage) else: itk.imwrite(allRoisImage, label_3D_filename) patient_ind = patient_ind + 1 #patient_ind = patient_ind + 1 for patient_folder in sorted(glob.glob(f'{images_test}/*')): # if rennes images, the name of the cbct is different and there are more than one cbct per patient if 'Rennes' in patient_folder: cbctimage_prefix = 'cbct' ctimage_prefix = 'pseudo_rec' if (apply_matching == False) & ('correctedN4' in testimage_ch0_name): for cbct_image_path in sorted( glob.glob( f'{patient_folder}/{cbctimage_prefix}*_N4folder/{realCBCT_N4imagename}' )): cbct_id = os.path.dirname(cbct_image_path).replace( f'{patient_folder}/{cbctimage_prefix}', '').replace('_N4folder', '') with open(f'{taskfolder_3D}/errorlog.txt', 'a') as f: f.write( str(patient_ind) + " - " + patient_folder + " - cbct id " + cbct_id + " : \n") print(patient_folder) casename_3D = f'{image_identifier_3D}_{patient_ind:04d}' test_patient_names.append(casename_3D) # channel 1 = real CBCT # save in 3D_outputfolder cbct_3D_filename = f'{imagesTs_foldername_3D}/{casename_3D}_0001.nii.gz' #convert_command= f'gt_image_convert {cbct_image_path} -o {cbct_3D_filename}' #os.system(convert_command) if spacing2mm == True: convert_command = f'gt_affine_transform -i {cbct_image_path} --newspacing=2,2,2 -o {cbct_3D_filename} -fr -a' os.system(convert_command) else: convert_command = f'gt_image_convert {cbct_image_path} -o {cbct_3D_filename}' os.system(convert_command) # load the real CBCT image to get the size cbct_image = itk.imread(cbct_3D_filename) cbct_origin = cbct_image.GetOrigin() # channel 0 = pseudo CT ct_image_path = cbct_image_path.replace( 'realCBCT', 'pseudoCT') # save in the 3D task folder ct_3D_filename = f'{imagesTs_foldername_3D}/{casename_3D}_0000.nii.gz' ct_image = itk.imread(ct_image_path) # resize the image to same size as the real cbct ct_image = gt.applyTransformation(input=ct_image, like=cbct_image, force_resample=True, pad=-1024) itk.imwrite(ct_image, ct_3D_filename) # copy and register label (ROI) with the cbct ROI_dir = f'{patient_folder}/ROI' allRoisImage = create_segmentation_map( ROI_list, ROI_list_alternatenames, ROI_dir, cbct_3D_filename, cbct_id) label_3D_filename = f'{labelsTs_foldername_3D}/{casename_3D}.nii.gz' itk.imwrite(allRoisImage, label_3D_filename) patient_ind = patient_ind + 1 elif (apply_matching == False) & ('swn_normalized' in testimage_ch0_name): for cbct_image_path in sorted( glob.glob( f'{patient_folder}/{cbctimage_prefix}*_SWNfolder/{realCBCT_SWNimagename}' )): cbct_id = os.path.dirname(cbct_image_path).replace( f'{patient_folder}/{cbctimage_prefix}', '').replace('_SWNfolder', '') with open(f'{taskfolder_3D}/errorlog.txt', 'a') as f: f.write( str(patient_ind) + " - " + patient_folder + " - cbct id " + cbct_id + " : \n") print(patient_folder) casename_3D = f'{image_identifier_3D}_{patient_ind:04d}' test_patient_names.append(casename_3D) # channel 1 = real CBCT # save in 3D_outputfolder cbct_3D_filename = f'{imagesTs_foldername_3D}/{casename_3D}_0001.nii.gz' #convert_command= f'gt_image_convert {cbct_image_path} -o {cbct_3D_filename}' #os.system(convert_command) if spacing2mm == True: convert_command = f'gt_affine_transform -i {cbct_image_path} --newspacing=2,2,2 -o {cbct_3D_filename} -fr -a' os.system(convert_command) else: convert_command = f'gt_image_convert {cbct_image_path} -o {cbct_3D_filename}' os.system(convert_command) # load the real CBCT image to get the size cbct_image = itk.imread(cbct_3D_filename) cbct_origin = cbct_image.GetOrigin() # channel 0 = pseudo CT ct_image_path = cbct_image_path.replace( 'realCBCT', 'pseudoCT') # save in the 3D task folder ct_3D_filename = f'{imagesTs_foldername_3D}/{casename_3D}_0000.nii.gz' ct_image = itk.imread(ct_image_path) # resize the image to same size as the real cbct ct_image = gt.applyTransformation(input=ct_image, like=cbct_image, force_resample=True, pad=-1024) itk.imwrite(ct_image, ct_3D_filename) # copy and register label (ROI) with the cbct ROI_dir = f'{patient_folder}/ROI' allRoisImage = create_segmentation_map( ROI_list, ROI_list_alternatenames, ROI_dir, cbct_3D_filename, cbct_id) label_3D_filename = f'{labelsTs_foldername_3D}/{casename_3D}.nii.gz' itk.imwrite(allRoisImage, label_3D_filename) patient_ind = patient_ind + 1 else: for cbct_image_path in sorted( glob.glob( f'{patient_folder}/{cbctimage_prefix}*.nii.gz')): cbct_id = os.path.basename(cbct_image_path).replace( f'{cbctimage_prefix}', '').replace('.nii.gz', '') with open(f'{taskfolder_3D}/errorlog.txt', 'a') as f: f.write( str(patient_ind) + " - " + patient_folder + " - cbct id " + cbct_id + " : \n") print(patient_folder) casename_3D = f'{image_identifier_3D}_{patient_ind:04d}' test_patient_names.append(casename_3D) # channel 1 = real CBCT # convert to float convert_command = f'clitkImageConvert -i {cbct_image_path} -o {cbct_image_path} -t float' os.system(convert_command) # save in 3D_outputfolder cbct_3D_filename = f'{imagesTs_foldername_3D}/{casename_3D}_0001.nii.gz' #convert_command= f'gt_image_convert {cbct_image_path} -o {cbct_3D_filename}' #os.system(convert_command) if spacing2mm == True: convert_command = f'gt_affine_transform -i {cbct_image_path} --newspacing=2,2,2 -o {cbct_3D_filename} -fr -a' os.system(convert_command) else: convert_command = f'gt_image_convert {cbct_image_path} -o {cbct_3D_filename}' os.system(convert_command) # channel 0 = pseudo CT ct_image_path = f'{patient_folder}/{ctimage_prefix}{cbct_id}.nii.gz' # convert to float convert_command = f'clitkImageConvert -i {ct_image_path} -o {ct_image_path} -t float' os.system(convert_command) # save in the 3D task folder ct_3D_filename = f'{imagesTs_foldername_3D}/{casename_3D}_0000.nii.gz' # resize the image to same size as the real cbct elastix_command = f'elastix -f {cbct_image_path} -m {ct_image_path} -p {elastix_param_file} -out {elastix_folder}' os.system(elastix_command) registered_ct_path = f'{elastix_folder}/result.0.mhd' if spacing2mm == True: convert_command = f'gt_affine_transform -i {registered_ct_path} --newspacing=2,2,2 -o {ct_3D_filename} -fr -a' os.system(convert_command) else: convert_command = f'gt_image_convert {registered_ct_path} -o {ct_3D_filename}' os.system(convert_command) # copy and register label (ROI) with the cbct ROI_dir = f'{patient_folder}/ROI' allRoisImage = create_segmentation_map( ROI_list, ROI_list_alternatenames, ROI_dir, cbct_3D_filename, cbct_id) label_3D_filename = f'{labelsTs_foldername_3D}/{casename_3D}.nii.gz' itk.imwrite(allRoisImage, label_3D_filename) patient_ind = patient_ind + 1 # dataset.json 3D json_dict = {} json_dict['name'] = task_name_3D json_dict['description'] = "" json_dict['tensorImageSize'] = "4D" json_dict['reference'] = "saphir" json_dict['licence'] = "" json_dict['release'] = "0.0" json_dict['modality'] = { "0": "CT", "1": "CT", } json_dict['labels'] = label_dict json_dict['numTraining'] = len(train_patient_names) json_dict['numTest'] = len(test_patient_names) json_dict['training'] = [{ 'image': "./imagesTr/%s.nii.gz" % i, "label": "./labelsTr/%s.nii.gz" % i } for i in train_patient_names] json_dict['test'] = [ "./imagesTs/%s.nii.gz" % i for i in test_patient_names ] save_json(json_dict, json_filename_3D)
def apply_N4(inputImageArray, inputImage_size, inputImage_origin, inputImage_spacing, FOV_mask, patient_mask, prefix, shrinkFactor): #inputImage_before # mask values above 300 (bones) bonemask_array = np.where(inputImageArray < 300, 1, 0) #bonemask.SetOrigin(inputImage_origin) bonemaskImage = sitk.GetImageFromArray(bonemask_array) bonemaskImage = sitk.Cast(bonemaskImage, sitk.sitkUInt8) bonemaskImage.SetOrigin(inputImage_origin) bonemaskImage.SetSpacing(inputImage_spacing) sitk.WriteImage(bonemaskImage, f"bonemask_{prefix}.mha") # apply the masks to recenter the values mask_intersection = (FOV_mask != 0) & (patient_mask != 0) inputImage_masked = np.around( np.ma.masked_array(inputImageArray, ~mask_intersection)) # recenter the values to 0 inputImage_shifted = inputImageArray - np.mean(inputImage_masked) # perform thresholding to only keep values above -300 inputImage_shifted[inputImage_shifted < -300] = -300 #bonemask.SetOrigin(inputImage_origin) #sitk.WriteImage(bonemask, "bonemask.mha") # add 300 to bring the values to the positive range inputImage_shifted = inputImage_shifted + 300 new_inputImage = sitk.GetImageFromArray(inputImage_shifted) new_inputImage.SetOrigin(inputImage_origin) new_inputImage.SetSpacing(inputImage_spacing) sitk.WriteImage(new_inputImage, f"shifted_{prefix}.mha") # intensity range between 0 and 255 #inputImageArray = swn_norm(inputImage_masked) #inputImageArray = tuple(tuple(p) for p in inputImageArray) #inputImageArray = ScaleIntensityRanged(keys=inputImageArray, a_min=0.0, a_max=255.0,b_min=0.0, b_max=1.0, clip=True) #print(inputImageArray(0)) #new_inputImage = sitk.GetImageFromArray(inputImageArray) #new_inputImage.SetOrigin(inputImage_origin) #sitk.WriteImage(new_inputImage, "simu_swn_normalized.mha") # bone mask = intensities above 200 #bonemask = new_inputImage<200 #bonemask.SetOrigin(inputImage_origin) #sitk.WriteImage(bonemask, "bonemask.mha") #bonemask_array = sitk.GetArrayFromImage(bonemask) maskImage_array = np.where( (FOV_mask != 0) & (patient_mask != 0) & (bonemask_array != 0), 1, 0) #combined_mask_image = sitk.Cast(combined_mask, combined_mask.GetPixelID()) maskImage = sitk.GetImageFromArray(maskImage_array) maskImage.SetOrigin(inputImage_origin) maskImage.SetSpacing(inputImage_spacing) maskImage = sitk.Cast(maskImage, sitk.sitkUInt8) sitk.WriteImage(maskImage, f"combined_mask_{prefix}.mha") inputImage = sitk.Cast(new_inputImage, sitk.sitkFloat32) #maskImage_before = maskImage #shrinkFactor = 2 if isinstance(shrinkFactor, int): inputImage = sitk.Shrink(inputImage, [shrinkFactor] * inputImage.GetDimension()) maskImage = sitk.Shrink(maskImage, [shrinkFactor] * inputImage.GetDimension()) #print(inputImage.GetPixelIDTypeAsString()) #print(maskImage.GetPixelIDTypeAsString()) corrector = sitk.N4BiasFieldCorrectionImageFilter() #numberFittingLevels=5 #numberOfIterations=100 #if isinstance(numberOfIterations, int): # corrector.SetMaximumNumberOfIterations([numberOfIterations] * numberFittingLevels) output = corrector.Execute(inputImage, maskImage) #output.SetOrigin(inputImage_origin) print('done') sitk.WriteImage(sitk.Subtract(output, inputImage), f"image_difference_{prefix}.mha") outputImagePath = f"{prefix}_correctedN4_beforeshifting.mha" sitk.WriteImage(output, outputImagePath) output_origin = output.GetOrigin() output_spacing = output.GetSpacing() # resize the output if it's shrinked output_itk = itk.GetImageFromArray(sitk.GetArrayFromImage(output)) output_itk.SetOrigin(output_origin) output_itk.SetSpacing(output_spacing) #inputImage_before_itk = itk.GetImageFromArray(sitk.GetArrayFromImage(inputImage_before)) #inputImage_before_itk.SetOrigin(inputImage_origin) #inputImage_before_itk.SetSpacing(inputImage_spacing) #itk.imwrite(inputImage_before_itk, "inputImage_before_itk.mha") output_resized_itk = gt.applyTransformation(input=output_itk, newsize=inputImage_size, force_resample=True, adaptive=True) output_resized_itk.SetOrigin(inputImage_origin) #itk.imwrite(output_resized_itk, "output_resized.mha") #output = sitk.GetImageFromArray(np.where(mask_intersection, itk.GetArrayFromImage(output_resized_itk) -300, inputImageArray )) output = sitk.GetImageFromArray(itk.GetArrayFromImage(output_resized_itk)) output.SetOrigin(inputImage_origin) outputImagePath = f"{prefix}_correctedN4.mha" sitk.WriteImage(output, outputImagePath) return output
def faf_register_planar_image(planar, spect): if planar.GetImageDimension() != 2: print("Planar image dimension (" + str(planar.GetImageDimension()) + ") is not 2") sys.exit(1) if spect.GetImageDimension() != 3: print("Planar image dimension (" + str(spect.GetImageDimension()) + ") is not 3") sys.exit(1) if not (itk.array_from_matrix(spect.GetDirection()) == np.eye( spect.GetImageDimension())).all(): spect = gt.applyTransformation(input=spect, force_resample=True, pad=0) projectedSpect = image_projection.image_projection(spect, 1) flipFilter = itk.FlipImageFilter.New(Input=projectedSpect) flipFilter.SetFlipAxes((False, True)) flipFilter.Update() projectedSpect = flipFilter.GetOutput() projectedSpect = gt.applyTransformation(input=projectedSpect, spacinglike=planar, force_resample=True, adaptive=True) minCorrelation = 10 minCorrelationIndex = 0 for i in range(projectedSpect.GetLargestPossibleRegion().GetSize()[1] + planar.GetLargestPossibleRegion().GetSize()[1] - 1): newOrigin = itk.Vector[itk.D, 2]() newOrigin[0] = projectedSpect.GetOrigin()[0] + ( projectedSpect.GetLargestPossibleRegion().GetSize()[0] - planar.GetLargestPossibleRegion().GetSize()[0] ) * projectedSpect.GetSpacing()[0] / 2.0 newOrigin[1] = projectedSpect.GetOrigin()[1] - ( planar.GetLargestPossibleRegion().GetSize()[1] - 1 - i) * projectedSpect.GetSpacing()[1] centeredPlanar = gt.applyTransformation(input=planar, neworigin=newOrigin) centredPlanarOriginInProjectedSpect = projectedSpect.TransformPhysicalPointToIndex( newOrigin) identityTransform = itk.IdentityTransform[itk.D, 2].New() identityTransform.SetIdentity() interpolator = itk.LinearInterpolateImageFunction[type(planar), itk.D].New() smallRegion = itk.ImageRegion[2]() smallRegionSize = itk.Size[2]() smallRegionSize[0] = min( centeredPlanar.GetLargestPossibleRegion().GetSize()[0], projectedSpect.GetLargestPossibleRegion().GetSize()[0]) smallRegionSize[1] = min( i + 1, projectedSpect.GetLargestPossibleRegion().GetSize()[1] + planar.GetLargestPossibleRegion().GetSize()[1] - 1 - i, projectedSpect.GetLargestPossibleRegion().GetSize()[1]) smallRegion.SetSize(smallRegionSize) smallRegionIndex = itk.Index[2]() smallRegionIndex[0] = max(0, centredPlanarOriginInProjectedSpect[0]) smallRegionIndex[1] = max(0, centredPlanarOriginInProjectedSpect[1]) smallRegion.SetIndex(smallRegionIndex) miCoeffFilter = itk.MattesMutualInformationImageToImageMetric[ type(planar), type(planar)].New() miCoeffFilter.SetMovingImage(centeredPlanar) miCoeffFilter.SetFixedImage(projectedSpect) miCoeffFilter.SetTransform(identityTransform) miCoeffFilter.SetInterpolator(interpolator) miCoeffFilter.SetFixedImageRegion(smallRegion) miCoeffFilter.UseAllPixelsOn() miCoeffFilter.SetNumberOfHistogramBins(50) miCoeffFilter.ReinitializeSeed() miCoeffFilter.Initialize() if miCoeffFilter.GetValue( identityTransform.GetParameters()) < minCorrelation: minCorrelation = miCoeffFilter.GetValue( identityTransform.GetParameters()) minCorrelationIndex = i newOrigin = itk.Vector[itk.D, 2]() newOrigin[0] = projectedSpect.GetOrigin()[0] + ( projectedSpect.GetLargestPossibleRegion().GetSize()[0] - planar.GetLargestPossibleRegion().GetSize()[0] ) * projectedSpect.GetSpacing()[0] / 2.0 newOrigin[1] = projectedSpect.GetOrigin()[1] - ( planar.GetLargestPossibleRegion().GetSize()[1] - 1 - minCorrelationIndex) * projectedSpect.GetSpacing()[1] centeredPlanar = gt.applyTransformation(input=planar, neworigin=newOrigin) return centeredPlanar
def faf_calibration(spect, acgm, injected_activity=1.0, half_life=6.0067, delta_time=1.0, acquisition_duration=900, verbose=False): if spect.GetImageDimension() != 3: print("spect image dimension (" + str(spect.GetImageDimension()) + ") is not 3") sys.exit(1) if acgm.GetImageDimension() != 2: print("acgm image dimension (" + str(acgm.GetImageDimension()) + ") is not 2") sys.exit(1) if not (itk.array_from_matrix(spect.GetDirection()) == np.eye( spect.GetImageDimension())).all(): spect = gt.applyTransformation(input=spect, force_resample=True, pad=0) projectedSPECT = image_projection.image_projection(spect, 1) flipFilter = itk.FlipImageFilter.New(Input=projectedSPECT) flipFilter.SetFlipAxes((False, True)) flipFilter.Update() projectedSPECT = flipFilter.GetOutput() projectedSPECT = gt.applyTransformation(input=projectedSPECT, like=acgm, force_resample=True) projectedSPECTArray = itk.array_from_image(projectedSPECT) acgmArray = itk.array_from_image(acgm) spectArray = itk.array_from_image(spect) lambdaDecay = np.log(2.0) / (half_life * 3600) A0 = injected_activity * np.exp(-lambdaDecay * delta_time * 3600) #integral = (1 - np.exp(-lambdaDecay*acquisition_duration))/lambdaDecay #integralActivity = A0*integral #volume = np.prod(np.array(spect.GetSpacing())) sumSPECT = np.sum(spectArray) sumACGM = np.sum(acgmArray) partialSumACGM = np.sum(acgmArray[projectedSPECTArray > 1]) sensitivityFAF = sumSPECT / (A0 * partialSumACGM / sumACGM) if verbose: print("sum in SPECT (counts): " + str(sumSPECT)) print("partial sum in ACGM (counts): " + str(partialSumACGM)) print("sum in ACGM (counts): " + str(sumACGM)) print("FAF: " + str(partialSumACGM / sumACGM)) print("A0 at the beginning of the SPECT acquisition (MBq): " + str(A0)) print("lambda decay (s-1): " + str(lambdaDecay)) print("sensitivityFAF (counts/MBq): " + str(sensitivityFAF)) #print("volume of SPECT (mm3): " + str(volume)) #print("integral Activity (MBq.s): " + str(integralActivity)) calibrationFactor = 1.0 / sensitivityFAF calibratedSpectArray = spectArray * calibrationFactor calibratedSpectImage = itk.image_from_array(calibratedSpectArray) calibratedSpectImage.CopyInformation(spect) return (calibratedSpectImage, calibrationFactor * 1000000)
def copy_images(images_test, task_id, task_name_3D, patient_ind, testimage_name, ROI_list, ROI_list_alternatenames, label_dict): image_identifier_3D = 'CBCT_3D' #realCBCT_N4imagename = 'realCBCT_correctedN4_beforeshifting.mha' # copy the 3D cbct images to imagesTr in .nii.gz format global taskfolder_3D taskfolder_3D = f'{nnUNet_raw_data}/Task{task_id:03d}_{task_name_3D}' json_filename_3D = f'{taskfolder_3D}/dataset.json' imagesTs_foldername_3D = f'{taskfolder_3D}/imagesTs/' labelsTs_foldername_3D = f'{taskfolder_3D}/labelsTs/' maybe_mkdir_p(imagesTs_foldername_3D) maybe_mkdir_p(labelsTs_foldername_3D) open(f"{taskfolder_3D}/errorlog_test.txt", "w").close() test_patient_names = [] for patient_folder in sorted(glob.glob(f'{images_test}/*')): # if rennes images, the name of the cbct is different and there are more than one cbct per patient if 'Rennes' in patient_folder: #cbct_image_path = glob.glob(f'{patient_folder}/cbct*.nii.gz')[0] if 'pseudo' in patient_folder: image_prefix = 'pseudo_rec' else: image_prefix = 'cbct' if (apply_matching == False) & ('correctedN4' in testimage_name): for cbct_image_path in sorted( glob.glob( f'{patient_folder}/{image_prefix}*_N4folder/{realCBCT_N4imagename}' )): cbct_id = os.path.dirname(cbct_image_path).replace( f'{patient_folder}/{image_prefix}', '').replace('_N4folder', '') with open(f'{taskfolder_3D}/errorlog_test.txt', 'a') as f: f.write( str(patient_ind) + " - " + patient_folder + " - cbct id " + cbct_id + " : \n") print(patient_folder) casename_3D = f'{image_identifier_3D}_{patient_ind:04d}' test_patient_names.append(casename_3D) cbct_3D_filename = f'{imagesTs_foldername_3D}/{casename_3D}_0000.nii.gz' if spacing2mm == True: cbct_img = itk.imread(cbct_image_path) img_origin = cbct_img.GetOrigin() new_cbct_img = gt.applyTransformation( input=cbct_img, neworigin=img_origin, newspacing=img_spacing, adaptive=True, force_resample=True) itk.imwrite(new_cbct_img, cbct_3D_filename) else: convert_command = f'gt_image_convert {cbct_image_path} -o {cbct_3D_filename}' os.system(convert_command) # copy and register label (ROI) with the cbct ROI_dir = f'{patient_folder}/ROI' allRoisImage = create_segmentation_map( ROI_list, ROI_list_alternatenames, ROI_dir, cbct_3D_filename, cbct_id) label_3D_filename = f'{labelsTs_foldername_3D}/{casename_3D}.nii.gz' itk.imwrite(allRoisImage, label_3D_filename) patient_ind = patient_ind + 1 elif (apply_matching == False) & ('swn_normalized' in testimage_name): for cbct_image_path in sorted( glob.glob( f'{patient_folder}/{image_prefix}*_SWNfolder/{realCBCT_SWNimagename}' )): cbct_id = os.path.dirname(cbct_image_path).replace( f'{patient_folder}/{image_prefix}', '').replace('_SWNfolder', '') with open(f'{taskfolder_3D}/errorlog_test.txt', 'a') as f: f.write( str(patient_ind) + " - " + patient_folder + " - cbct id " + cbct_id + " : \n") print(patient_folder) casename_3D = f'{image_identifier_3D}_{patient_ind:04d}' test_patient_names.append(casename_3D) cbct_3D_filename = f'{imagesTs_foldername_3D}/{casename_3D}_0000.nii.gz' if spacing2mm == True: cbct_img = itk.imread(cbct_image_path) img_origin = cbct_img.GetOrigin() new_cbct_img = gt.applyTransformation( input=cbct_img, neworigin=img_origin, newspacing=img_spacing, adaptive=True, force_resample=True) itk.imwrite(new_cbct_img, cbct_3D_filename) else: convert_command = f'gt_image_convert {cbct_image_path} -o {cbct_3D_filename}' os.system(convert_command) # copy and register label (ROI) with the cbct ROI_dir = f'{patient_folder}/ROI' allRoisImage = create_segmentation_map( ROI_list, ROI_list_alternatenames, ROI_dir, cbct_3D_filename, cbct_id) label_3D_filename = f'{labelsTs_foldername_3D}/{casename_3D}.nii.gz' itk.imwrite(allRoisImage, label_3D_filename) patient_ind = patient_ind + 1 else: for cbct_image_path in sorted( glob.glob(f'{patient_folder}/{image_prefix}*.nii.gz')): cbct_id = os.path.basename(cbct_image_path).replace( f'{image_prefix}', '').replace('.nii.gz', '') with open(f'{taskfolder_3D}/errorlog_test.txt', 'a') as f: f.write( str(patient_ind) + " - " + patient_folder + " - cbct id " + cbct_id + " : \n") print(patient_folder) casename_3D = f'{image_identifier_3D}_{patient_ind:04d}' test_patient_names.append(casename_3D) # convert to float convert_command = f'clitkImageConvert -i {cbct_image_path} -o {cbct_image_path} -t float' os.system(convert_command) # reduce image size and save in 3D_outputfolder cbct_3D_filename = f'{imagesTs_foldername_3D}/{casename_3D}_0000.nii.gz' if spacing2mm == True: cbct_img = itk.imread(cbct_image_path) img_origin = cbct_img.GetOrigin() new_cbct_img = gt.applyTransformation( input=cbct_img, neworigin=img_origin, newspacing=img_spacing, adaptive=True, force_resample=True) itk.imwrite(new_cbct_img, cbct_3D_filename) else: convert_command = f'gt_image_convert {cbct_image_path} -o {cbct_3D_filename}' os.system(convert_command) # copy and register label (ROI) with the cbct ROI_dir = f'{patient_folder}/ROI' allRoisImage = create_segmentation_map( ROI_list, ROI_list_alternatenames, ROI_dir, cbct_3D_filename, cbct_id) label_3D_filename = f'{labelsTs_foldername_3D}/{casename_3D}.nii.gz' itk.imwrite(allRoisImage, label_3D_filename) patient_ind = patient_ind + 1 else: with open(f'{taskfolder_3D}/errorlog_test.txt', 'a') as f: f.write(str(patient_ind) + " - " + patient_folder + ": \n") print(patient_folder) casename_3D = f'{image_identifier_3D}_{patient_ind:04d}' test_patient_names.append(casename_3D) if 'CLB' in patient_folder: if (apply_matching == False) & ('correctedN4' in testimage_name): cbct_image_path = f'{patient_folder}/{realCBCT_N4imagename}' elif (apply_matching == False) & ('swn_normalized' in testimage_name): cbct_image_path = f'{patient_folder}/{realCBCT_SWNimagename}' else: cbct_image_path = glob.glob( f'{patient_folder}/cbct*.mhd')[0] else: cbct_image_path = f'{patient_folder}/{testimage_name}' #cbct_image_path = f'{patient_folder}/{testimage_name}' # reduce image size and save in 3D_outputfolder cbct_3D_filename = f'{imagesTs_foldername_3D}/{casename_3D}_0000.nii.gz' #if (apply_matching == False) & ('correctedN4' in testimage_name): # no need to resize, already 2 mm spacing # #shutil.copy(cbct_image_path, imagesTr_foldername_3D) # #os.rename(f'{imagesTr_foldername_3D}/{trainingimage_name}', cbct_3D_filename) # convert_command= f'gt_image_convert {cbct_image_path} -o {cbct_3D_filename}' #else: # convert_command= f'gt_affine_transform -i {cbct_image_path} --newspacing=2,2,2 -o {cbct_3D_filename} -fr -a' if spacing2mm == True: convert_command = f'gt_affine_transform -i {cbct_image_path} --newspacing=2,2,2 -o {cbct_3D_filename} -fr -a' os.system(convert_command) else: convert_command = f'gt_image_convert {cbct_image_path} -o {cbct_3D_filename}' os.system(convert_command) # copy and register label (ROI) with the cbct ROI_dir = f'{patient_folder}/ROI' allRoisImage = create_segmentation_map(ROI_list, ROI_list_alternatenames, ROI_dir, cbct_3D_filename, '') label_3D_filename = f'{labelsTs_foldername_3D}/{casename_3D}.nii.gz' itk.imwrite(allRoisImage, label_3D_filename) patient_ind = patient_ind + 1 # dataset.json 3D json_dict = {} json_dict['name'] = task_name_3D json_dict['description'] = "" json_dict['tensorImageSize'] = "4D" json_dict['reference'] = "saphir" json_dict['licence'] = "" json_dict['release'] = "0.0" json_dict['modality'] = { "0": "CT", } json_dict['labels'] = label_dict json_dict['numTest'] = len(test_patient_names) json_dict['test'] = [ "./imagesTs/%s.nii.gz" % i for i in test_patient_names ] save_json(json_dict, json_filename_3D)
def stitch_image(image1, image2, dimension=2, pad=0): Dimension = image1.GetImageDimension() if image2.GetImageDimension() != Dimension: print("Image1 dimension (" + str(Dimension) + ") and Image2 dimension (" + str(image2.GetImageDimension()) + ") are different") sys.exit(1) #Check negative spacing or non identity direction if not (itk.array_from_matrix(image1.GetDirection()) == np.eye(Dimension)).all(): image1 = gt.applyTransformation(input=image1, force_resample=True, pad=pad) if not (itk.array_from_matrix(image2.GetDirection()) == np.eye(Dimension)).all(): image2 = gt.applyTransformation(input=image2, force_resample=True, pad=pad) #Determine the FOV1image and FOV2image if image1.GetOrigin()[dimension] > image2.GetOrigin()[dimension]: FOV1image = image2 FOV2image = image1 else: FOV1image = image1 FOV2image = image2 #Determine dimension for resampled FOV2 lowFOV2index = itk.ContinuousIndex[itk.D, Dimension]() for i in range(Dimension): lowFOV2index[i] = -0.5 lowFOV2point = FOV2image.TransformContinuousIndexToPhysicalPoint( lowFOV2index) lowFOV2index = FOV1image.TransformPhysicalPointToIndex(lowFOV2point) lowFOV2point = FOV1image.TransformIndexToPhysicalPoint(lowFOV2index) highFOV2index = itk.ContinuousIndex[itk.D, Dimension]() for i in range(Dimension): highFOV2index[i] = FOV2image.GetLargestPossibleRegion().GetSize( )[i] - 0.5 highFOV2point = FOV2image.TransformContinuousIndexToPhysicalPoint( highFOV2index) highFOV2index = FOV1image.TransformPhysicalPointToIndex(highFOV2point) newFOV2Origin = [0] * Dimension for i in range(Dimension): newFOV2Origin[i] = FOV1image.GetOrigin()[i] newFOV2Origin[dimension] = lowFOV2point[dimension] newFOV2Size = [0] * Dimension for i in range(Dimension): newFOV2Size[i] = FOV1image.GetLargestPossibleRegion().GetSize()[i] newFOV2Size[ dimension] = highFOV2index[dimension] - lowFOV2index[dimension] + 1 #Resample FOV2image to be aligned with FOV1image resampledFOV2image = gt.applyTransformation(input=FOV2image, spacinglike=FOV1image, newsize=newFOV2Size, neworigin=newFOV2Origin, force_resample=True, pad=pad) #Determine size of the output outputLastIndex = itk.Index[Dimension]() for i in range(Dimension): outputLastIndex[i] = resampledFOV2image.GetLargestPossibleRegion( ).GetSize()[i] - 1 outputLastPoint = resampledFOV2image.TransformIndexToPhysicalPoint( outputLastIndex) outputLastIndex = FOV1image.TransformPhysicalPointToIndex(outputLastPoint) outputSize = itk.Size[Dimension]() for i in range(Dimension): outputSize[i] = FOV1image.GetLargestPossibleRegion().GetSize()[i] outputSize[dimension] = outputLastIndex[dimension] + 1 #Create output ImageType = itk.Image[itk.template(image1)[1][0], Dimension] outputImage = ImageType.New() outputStart = itk.Index[Dimension]() for i in range(Dimension): outputStart[i] = 0 outputRegion = itk.ImageRegion[Dimension]() outputRegion.SetSize(outputSize) outputRegion.SetIndex(outputStart) outputImage.SetRegions(outputRegion) outputImage.Allocate() outputImage.FillBuffer(pad) outputImage.SetSpacing(FOV1image.GetSpacing()) outputImage.SetDirection(FOV1image.GetDirection()) outputImage.SetOrigin(FOV1image.GetOrigin()) #Fill the output with resampledFOV2image to begin outputArrayView = itk.array_view_from_image(outputImage) resampledFOV2ArrayView = itk.array_view_from_image(resampledFOV2image) FOV1ArrayView = itk.array_view_from_image(FOV1image) outputBeginFOV2Index = itk.Index[Dimension]() for i in range(Dimension): outputBeginFOV2Index[i] = 0 outputBeginFOV2Point = resampledFOV2image.TransformIndexToPhysicalPoint( outputBeginFOV2Index) outputBeginFOV2Index = outputImage.TransformPhysicalPointToIndex( outputBeginFOV2Point) outputArrayView[outputBeginFOV2Index[2]:, outputBeginFOV2Index[1]:, outputBeginFOV2Index[0]:] = resampledFOV2ArrayView[:] #Fill the output with FOV1image where it's superior to current output (to avoid artifact) outputEndFOV1Index = itk.Index[Dimension]() for i in range(Dimension): outputEndFOV1Index[i] = FOV1image.GetLargestPossibleRegion().GetSize( )[i] outputArrayView[np.where( FOV1ArrayView > outputArrayView[:outputEndFOV1Index[2], :outputEndFOV1Index[1], : outputEndFOV1Index[0]] )] = FOV1ArrayView[np.where( FOV1ArrayView > outputArrayView[:outputEndFOV1Index[2], :outputEndFOV1Index[1], : outputEndFOV1Index[0]])] return outputImage
def imageResize(input=None, newsize=None, newsize_mm=None, pad=None): if input is None: logger.error("Set the input") sys.exit(1) if newsize is None and newsize_mm is None: logger.error("Choose between newsize and newsize_mm options") sys.exit(1) if newsize is not None and newsize_mm is not None: logger.error("Choose between newsize and newsize_mm") sys.exit(1) if pad is None: pad = 0.0 imageDimension = input.GetImageDimension() itkSize = itk.Size[imageDimension]() if newsize is None: for i in range(imageDimension): itkSize[i] = int(round(newsize_mm[i] / input.GetSpacing()[i], 0)) else: for i in range(imageDimension): itkSize[i] = newsize[i] differenceSize = [0] * imageDimension for i in range(imageDimension): differenceSize[i] = itkSize[i] - input.GetLargestPossibleRegion( ).GetSize()[i] newSize = itk.Size[imageDimension]() newOrigin = itk.Point[itk.F, imageDimension]() newTranslation = itk.Point[itk.F, imageDimension]() for i in range(imageDimension): if differenceSize[i] > 0: newSize[i] = itkSize[i] if differenceSize[i] % 2 == 0: newTranslation[i] = -differenceSize[i] / 2 * input.GetSpacing( )[i] else: newTranslation[i] = -(differenceSize[i] + 1) / 2 * input.GetSpacing()[i] newOrigin[i] = input.GetOrigin()[i] + newTranslation[i] elif differenceSize[i] < 0: newSize[i] = itkSize[i] if differenceSize[i] % 2 == 0: newTranslation[i] = -differenceSize[i] / 2 * input.GetSpacing( )[i] else: newTranslation[i] = -(differenceSize[i] + 1) / 2 * input.GetSpacing()[i] newOrigin[i] = input.GetOrigin()[i] + newTranslation[i] else: newSize[i] = input.GetLargestPossibleRegion().GetSize()[i] newTranslation[i] = 0 newOrigin[i] = input.GetOrigin()[i] outputImage = gt.applyTransformation(input, newsize=newSize, force_resample=True, translation=newTranslation, pad=pad) outputImage = gt.applyTransformation(outputImage, neworigin=newOrigin) return outputImage
def apply_SWN_allimages(simucbct_path, realcbct_path, CT_path, FOV_mask_path, patient_mask_path): # load images and mask and resize realcbct_image = itk.imread(realcbct_path) realcbct_origin = realcbct_image.GetOrigin() realcbct = itk.GetArrayFromImage(realcbct_image) #print(realcbct) realcbct = realcbct - 1024 #realcbct[realcbct < -1024] = -1024 newrealcbct_image = itk.GetImageFromArray(realcbct) newrealcbct_image.SetOrigin(realcbct_origin) itk.imwrite(newrealcbct_image, 'cbct_shifted.mha') # load real CT and resize CT_image = itk.imread(CT_path) CT_image_resized = gt.applyTransformation(input=CT_image, like=realcbct_image, force_resample=True, pad=-1024) itk.imwrite(CT_image_resized, 'CT_image_resized.mha') realct_origin = CT_image_resized.GetOrigin() realct = itk.GetArrayFromImage(CT_image_resized) simucbct_image = itk.imread(simucbct_path) # resize if different from the real cbct if itk.size(simucbct_image) == itk.size(realcbct_image): simucbct = itk.GetArrayFromImage(simucbct_image) simucbct_origin = simucbct_image.GetOrigin() else: #simucbct = itk.GetArrayFromImage(gt.applyTransformation(input=simucbct_image, like=realcbct_image, force_resample=True,adaptive=True)) simucbct_img = gt.applyTransformation(input=simucbct_image, like=realcbct_image, force_resample=True, pad=0) simucbct_origin = simucbct_img.GetOrigin() itk.imwrite(simucbct_img, 'simucbct_resized.mha') simucbct = itk.GetArrayFromImage(simucbct_img) # rescale value simucbct = (simucbct * 65536) - 1024 FOV_mask_image = itk.imread(FOV_mask_path) if itk.size(FOV_mask_image) == itk.size(realcbct_image): FOV_mask = itk.GetArrayFromImage(FOV_mask_image) else: #FOV_mask = itk.GetArrayFromImage(gt.applyTransformation(input=FOV_mask_image, like=realcbct_image, force_resample=True,adaptive=True)) FOV_mask_img = gt.applyTransformation(input=FOV_mask_image, newsize=itk.size(realcbct_image), force_resample=True, adaptive=True, interpolation_mode='NN') itk.imwrite(FOV_mask_img, 'FOV_mask_resized.mha') FOV_mask = itk.GetArrayFromImage(FOV_mask_img) patient_mask_image = itk.imread(patient_mask_path) if itk.size(patient_mask_image) == itk.size(realcbct_image): patient_mask = itk.GetArrayFromImage(patient_mask_image) else: #patient_mask = itk.GetArrayFromImage(gt.applyTransformation(input=patient_mask_image, like=realcbct_image, force_resample=True,adaptive=True)) patient_mask_img = gt.applyTransformation(input=patient_mask_image, like=realcbct_image, force_resample=True, interpolation_mode='NN') itk.imwrite(patient_mask_img, 'patient_mask_resized.mha') patient_mask = itk.GetArrayFromImage(patient_mask_img) # apply the masks, setting values outside the patient to 0 mask_intersection = (FOV_mask != 0) & (patient_mask != 0) # apply the patient mask to draw the histograms realcbct_masked = np.around( np.ma.masked_array(realcbct, ~mask_intersection)) realct_masked = np.around(np.ma.masked_array(realct, ~mask_intersection)) simucbct_masked = np.around( np.ma.masked_array(simucbct, ~mask_intersection)) #print(np.ma.compressed(realcbct_masked)) #print(np.ma.compressed(simucbct_masked)) #realcbct_masked_img = itk.GetImageFromArray(np.where(mask_intersection,realcbct_masked,0)) #realcbct_masked_img.SetOrigin(realcbct_origin) #itk.imwrite(realcbct_masked_img, 'realcbct_masked_image.mha') name_ext = f'swn_normalized' # apply swn normalization on real ct, reat cbct, and simu cbct # intensity range between 0 and 255 realcbct_normalized_masked = swn_norm(realcbct_masked) simucbct_normalized_masked = swn_norm(simucbct_masked) realct_normalized_masked = swn_norm(realct_masked) #realct_normalized_masked = np.around(np.ma.masked_array(swn_norm(realct_masked),~mask_intersection)) realcbct_normalized = np.where(mask_intersection, realcbct_normalized_masked, 0) simucbct_normalized = np.where(mask_intersection, simucbct_normalized_masked, 0) realct_normalized = np.where(mask_intersection, realct_normalized_masked, 0) # convert to images and save realcbct_normalized_img = itk.GetImageFromArray(realcbct_normalized) realcbct_normalized_img.SetOrigin(realcbct_origin) itk.imwrite(realcbct_normalized_img, f'realCBCT_{name_ext}.mha') simucbct_normalized_img = itk.GetImageFromArray(simucbct_normalized) simucbct_normalized_img.SetOrigin(simucbct_origin) itk.imwrite(simucbct_normalized_img, f'simuCBCT_{name_ext}.mha') realct_normalized_img = itk.GetImageFromArray(realct_normalized) realct_normalized_img.SetOrigin(realct_origin) itk.imwrite(realct_normalized_img, f'realCT_{name_ext}.mha') # apply mask on normalized images to draw histogram #simucbct_matched1_masked = np.ma.compressed(np.around(np.ma.masked_array(simucbct_matched1,~mask_intersection ))) #patient_mask == 0 #simucbct_matched2_masked = np.ma.compressed(np.around(np.ma.masked_array(simucbct_matched2,~mask_intersection))) draw_histograms(realcbct_masked, realcbct_normalized_masked, simucbct_masked, simucbct_normalized_masked, realct_masked, realct_normalized_masked, 'SWN normalized') plot_profiles_all(realcbct_normalized, 'real cbct', simucbct_normalized, 'simu cbct', realct_normalized, 'real ct', 'SWNnormalized')
def apply_N4_cbct(realcbct_path, FOV_mask_path, patient_mask_path): shrinkFactor = 2 # load real cbct realcbct_img = sitk.ReadImage(realcbct_path) realcbct_origin = realcbct_img.GetOrigin() realcbct_size = realcbct_img.GetSize() realcbct_spacing = realcbct_img.GetSpacing() realcbct = sitk.GetArrayFromImage(realcbct_img) if realcbct_img.GetPixelIDValue() == 4: # int, convert to float convert_command = f'clitkImageConvert -i {realcbct_path} -o {realcbct_path} -t float' os.system(convert_command) realcbct_img = sitk.Cast(realcbct_img, sitk.sitkFloat32) # load patient and FOV masks FOV_mask_img = sitk.ReadImage(FOV_mask_path) FOV_mask = sitk.GetArrayFromImage(FOV_mask_img) if FOV_mask_img.GetSize() != realcbct_img.GetSize(): #FOV_mask_img = gt.applyTransformation(input=itk.imread(FOV_mask_path), newsize= realcbct_img.GetSize(), force_resample=True,adaptive=True,interpolation_mode='NN')spacinglike=itk.imread(realcbct_path) FOV_mask_img = gt.applyTransformation(input=itk.imread(FOV_mask_path), newsize=realcbct_img.GetSize(), adaptive=True, force_resample=True, interpolation_mode='NN') itk.imwrite(FOV_mask_img, 'FOV_mask_resized.mha') #FOV_mask = sitk.ReadImage('FOV_mask_resized.mha') FOV_mask = itk.GetArrayFromImage(FOV_mask_img) FOV_mask_img = sitk.ReadImage('FOV_mask_resized.mha') patient_mask_img = sitk.ReadImage(patient_mask_path) patient_mask = sitk.GetArrayFromImage(patient_mask_img) if patient_mask_img.GetSize() != realcbct_img.GetSize(): #patient_mask_img = gt.applyTransformation(input=itk.imread(patient_mask_path), newsize= realcbct_img.GetSize(), force_resample=True,adaptive=True,interpolation_mode='NN') patient_mask_img = gt.applyTransformation( input=itk.imread(patient_mask_path), like=itk.imread(realcbct_path), force_resample=True, interpolation_mode='NN') itk.imwrite(patient_mask_img, 'patient_mask_resized.mha') #patient_mask = sitk.ReadImage('patient_mask_resized.mha') patient_mask = itk.GetArrayFromImage(patient_mask_img) patient_mask_img = sitk.ReadImage('patient_mask_resized.mha') #mask_intersection = (sitk.GetArrayFromImage(FOV_mask) != 0) & (sitk.GetArrayFromImage(patient_mask) != 0) mask_intersection = (FOV_mask != 0) & (patient_mask != 0) # apply the patient mask to draw the histograms realcbct_masked = np.ma.compressed( np.around(np.ma.masked_array(realcbct, ~mask_intersection))) if os.path.isfile('realCBCT_correctedN4.mha'): realcbct_N4 = sitk.ReadImage('realCBCT_correctedN4.mha') else: realcbct_N4 = apply_N4(realcbct, realcbct_size, realcbct_origin, realcbct_spacing, FOV_mask, patient_mask, "realCBCT", shrinkFactor) realcbct_N4_array = sitk.GetArrayFromImage(realcbct_N4) realcbct_N4_masked = np.ma.compressed( np.around(np.ma.masked_array(realcbct_N4_array, ~mask_intersection))) draw_histograms_cbct(realcbct_masked, realcbct_N4_masked, 'N4 corrected') plot_profiles_cbct(realcbct, 'real cbct', realcbct_N4_array, 'real cbct after correction', 'N4corrected')
def apply_N4_allimages(simucbct_path, realcbct_path, CT_path, FOV_mask_path, patient_mask_path): shrinkFactor = 2 # load simulated CBCT simucbct_img = sitk.ReadImage(simucbct_path) simucbct_size = simucbct_img.GetSize() simucbct_origin = simucbct_img.GetOrigin() simucbct_spacing = np.array(simucbct_img.GetSpacing()) # convert to array, multiply by 65536 simucbct = (65536 * sitk.GetArrayFromImage(simucbct_img)) - 1024 #simucbct_img = sitk.GetImageFromArray(simucbct) #simucbct_img.SetOrigin(simucbct_origin) #simucbct_img.SetSpacing(simucbct_spacing) #sitk.WriteImage(inputImage_before, "inputImage_before.mha") #new_inputImage = inputImage_before # load real cbct, N4 corrected simulated cbct, and swn normalized simulated cbct realcbct_img = sitk.ReadImage(realcbct_path) realcbct = sitk.GetArrayFromImage(realcbct_img) # resize if different from simu cbct if realcbct.shape != simucbct.shape: realcbct_img = gt.applyTransformation( input=itk.imread(realcbct_path), like=itk.imread(simucbct_path), force_resample=True ) #like=itk.imread(simucbct_path), newsize=simucbct_size , adaptive= True itk.imwrite(realcbct_img, 'realcbct_resized.mha') #realcbct_img = sitk.ReadImage('realcbct_resized.mha') realcbct = sitk.GetArrayFromImage(realcbct_img) # load patient and FOV masks FOV_mask_img = sitk.ReadImage(FOV_mask_path) FOV_mask = sitk.GetArrayFromImage(FOV_mask_img) if FOV_mask_img.GetSize() != simucbct_img.GetSize( ): #FOV_mask.shape != simucbct.shape: FOV_mask_img = gt.applyTransformation(input=itk.imread(FOV_mask_path), like=itk.imread(simucbct_path), force_resample=True, interpolation_mode='NN') #FOV_mask_img = gt.applyTransformation(input=itk.imread(FOV_mask_path), newsize= simucbct_size, newspacing= simucbct_spacing, force_resample=True,interpolation_mode='NN') # itk.imwrite(FOV_mask_img, 'FOV_mask_resized.mha') FOV_mask = itk.GetArrayFromImage(FOV_mask_img) FOV_mask_img = sitk.ReadImage('FOV_mask_resized.mha') patient_mask_img = sitk.ReadImage(patient_mask_path) patient_mask = sitk.GetArrayFromImage(patient_mask_img) if patient_mask_img.GetSize() != simucbct_img.GetSize( ): #patient_mask.shape != simucbct.shape: patient_mask_img = gt.applyTransformation( input=itk.imread(patient_mask_path), like=itk.imread(simucbct_path), force_resample=True, interpolation_mode='NN') #patient_mask_img = gt.applyTransformation(input=itk.imread(patient_mask_path), spacinglike= itk.imread(simucbct_path), force_resample=True,adaptive=True,interpolation_mode='NN') # newsize=simucbct_size, spacing itk.imwrite(patient_mask_img, 'patient_mask_resized.mha') patient_mask = itk.GetArrayFromImage(patient_mask_img) patient_mask_img = sitk.ReadImage('patient_mask_resized.mha') #mask_intersection = (sitk.GetArrayFromImage(FOV_mask) != 0) & (sitk.GetArrayFromImage(patient_mask) != 0) mask_intersection = (FOV_mask != 0) & (patient_mask != 0) #print(mask_intersection) maskImage_array = np.where(mask_intersection, 1, 0) #combined_mask_image = sitk.Cast(combined_mask, combined_mask.GetPixelID()) maskImage = sitk.GetImageFromArray(maskImage_array) maskImage.SetOrigin(simucbct_origin) maskImage.SetSpacing(simucbct_spacing) maskImage = sitk.Cast(maskImage, sitk.sitkUInt8) sitk.WriteImage(maskImage, f"mask_intersection_realCT.mha") simucbct_masked = np.ma.compressed( np.around(np.ma.masked_array(simucbct, ~mask_intersection))) if os.path.isfile('simuCBCT_correctedN4.mha'): simucbct_N4 = sitk.ReadImage('simuCBCT_correctedN4.mha') else: simucbct_N4 = apply_N4(simucbct, simucbct_size, simucbct_origin, simucbct_spacing, FOV_mask, patient_mask, "simuCBCT", shrinkFactor) #simucbct_N4 = sitk.ReadImage('simuCBCT_correctedN4.mha') simucbct_N4_array = sitk.GetArrayFromImage(simucbct_N4) simucbct_N4_masked = np.ma.compressed( np.around(np.ma.masked_array(simucbct_N4_array, ~mask_intersection))) #simu_swn_masked = np.ma.compressed(np.around(np.ma.masked_array(simu_swn,~mask_intersection))) # apply the patient mask to draw the histograms realcbct_masked = np.ma.compressed( np.around(np.ma.masked_array(realcbct, ~mask_intersection))) if os.path.isfile('realCBCT_correctedN4.mha'): realcbct_N4 = sitk.ReadImage('realCBCT_correctedN4.mha') else: realcbct_N4 = apply_N4(realcbct, simucbct_size, simucbct_origin, simucbct_spacing, FOV_mask, patient_mask, "realCBCT", shrinkFactor) #realcbct_N4 = sitk.ReadImage('realCBCT_correctedN4.mha') realcbct_N4_array = sitk.GetArrayFromImage(realcbct_N4) realcbct_N4_masked = np.ma.compressed( np.around(np.ma.masked_array(realcbct_N4_array, ~mask_intersection))) # load real CT and resize CT_image = itk.imread(CT_path) CT_image_resized = gt.applyTransformation(input=CT_image, like=itk.imread(simucbct_path), force_resample=True, pad=-1024) itk.imwrite(CT_image_resized, 'CT_image_resized.mha') #resizedCT_origin = np.array(CT_image_resized.GetOrigin()) #resizedCT_spacing = np.array(CT_image_resized.GetSpacing()) realct = itk.GetArrayFromImage(CT_image_resized) realct_masked = np.ma.compressed( np.around(np.ma.masked_array(realct, ~mask_intersection))) #realct_img = sitk.GetImageFromArray(realct) #realct_img.SetOrigin(resizedCT_origin) #realct_img.SetSpacing(resizedCT_spacing) if os.path.isfile('realCT_correctedN4.mha'): realct_N4 = sitk.ReadImage('realCT_correctedN4.mha') else: realct_N4 = apply_N4(realct, simucbct_size, simucbct_origin, simucbct_spacing, FOV_mask, patient_mask, "realCT", shrinkFactor) #realct_N4 = sitk.ReadImage('realCT_correctedN4.mha') realct_N4_array = sitk.GetArrayFromImage(realct_N4) realct_N4_masked = np.ma.compressed( np.around(np.ma.masked_array(realct_N4_array, ~mask_intersection))) draw_histograms(realcbct_masked, realcbct_N4_masked, simucbct_masked, simucbct_N4_masked, realct_masked, realct_N4_masked, 'N4 corrected') plot_profiles_all(realcbct_N4_array, 'real cbct', simucbct_N4_array, 'simu cbct', realct_N4_array, 'real ct', 'N4corrected')
def apply_SWN_cbct(realcbct_path, FOV_mask_path, patient_mask_path): # load images and mask and resize realcbct_image = itk.imread(realcbct_path) realcbct_origin = realcbct_image.GetOrigin() realcbct_spacing = realcbct_image.GetSpacing() realcbct = itk.GetArrayFromImage(realcbct_image) FOV_mask_image = itk.imread(FOV_mask_path) if itk.size(FOV_mask_image) == itk.size(realcbct_image): FOV_mask = itk.GetArrayFromImage(FOV_mask_image) else: #FOV_mask = itk.GetArrayFromImage(gt.applyTransformation(input=FOV_mask_image, like=realcbct_image, force_resample=True,adaptive=True)) #FOV_mask_img = gt.applyTransformation(input=FOV_mask_image, like=realcbct_image, force_resample=True,interpolation_mode='NN') FOV_mask_img = gt.applyTransformation(input=FOV_mask_image, newsize=itk.size(realcbct_image), force_resample=True, adaptive=True, interpolation_mode='NN') itk.imwrite(FOV_mask_img, 'FOV_mask_resized.mha') FOV_mask = itk.GetArrayFromImage(FOV_mask_img) patient_mask_image = itk.imread(patient_mask_path) if itk.size(patient_mask_image) == itk.size(realcbct_image): patient_mask = itk.GetArrayFromImage(patient_mask_image) else: #patient_mask = itk.GetArrayFromImage(gt.applyTransformation(input=patient_mask_image, like=realcbct_image, force_resample=True,adaptive=True)) patient_mask_img = gt.applyTransformation(input=patient_mask_image, like=realcbct_image, force_resample=True, interpolation_mode='NN') itk.imwrite(patient_mask_img, 'patient_mask_resized.mha') patient_mask = itk.GetArrayFromImage(patient_mask_img) # apply the masks, setting values outside the patient to 0 mask_intersection = (FOV_mask != 0) & (patient_mask != 0) #mask_intersection_img = itk.GetImageFromArray(np.where(mask_intersection,1.0,0)) #mask_intersection_img.SetOrigin(realcbct_origin) #itk.imwrite(mask_intersection_img, 'mask_intersection.mha') # apply the patient mask to draw the histograms realcbct_masked = np.around( np.ma.masked_array(realcbct, ~mask_intersection)) #realcbct_masked_img = itk.GetImageFromArray(np.where(mask_intersection,realcbct_masked,0)) #realcbct_masked_img.SetOrigin(realcbct_origin) #itk.imwrite(realcbct_masked_img, 'realcbct_masked_image.mha') name_ext = f'swn_normalized' # apply swn normalization on reat cbct # intensity range between 0 and 255 realcbct_normalized_masked = swn_norm(realcbct_masked) realcbct_normalized = np.where(mask_intersection, realcbct_normalized_masked, 0) # convert to images and save realcbct_normalized_img = itk.GetImageFromArray(realcbct_normalized) realcbct_normalized_img.SetOrigin(realcbct_origin) realcbct_normalized_img.SetSpacing(realcbct_spacing) itk.imwrite(realcbct_normalized_img, f'realCBCT_{name_ext}.mha') draw_histograms_cbct(realcbct_masked, realcbct_normalized_masked, 'SWN normalized') plot_profiles_cbct(realcbct, 'real cbct', realcbct_normalized, 'real cbct after normalizaton', 'SWNnormalized')