def shift(data, transforms): """ Resamples all the images in an ArrayDetectorData structure with the supplied transforms, and saves the result in a new ArrayDetectorData structure :param data: ArrayDetectorData object with images :param transforms: A list of transforms (Simple ITK), one for each image :return: ArrayDetectorDAta object with shifted images """ assert isinstance(transforms, list) and len(transforms) == data.ndetectors shifted = ArrayDetectorData(data.ndetectors, data.ngates) reference = Image(np.zeros(data[0, 0].shape, dtype=np.float64), data[0, 0].spacing) for gate in range(data.ngates): for i in range(data.ndetectors): image = itk.resample_image( itk.convert_to_itk_image(data[gate, i]), transforms[i], reference=itk.convert_to_itk_image(reference)) shifted[gate, i] = itk.convert_from_itk_image(image) return shifted
def end_plot(fixed, moving, transform): global metric_values plt.subplots(1, 2, figsize=(10, 8)) # Plot metric values plt.subplot(1, 2, 1) plt.plot(metric_values, 'r') plt.title("Metric values") plt.xlabel('Iteration Number', fontsize=12) plt.ylabel('Metric Value', fontsize=12) # Plot image overlay resampled = ops_itk.resample_image(moving, transform, reference=fixed) if fixed.GetDimension() == 3: fixed = sitk.MaximumProjection(fixed, 2)[:, :, 0] resampled = sitk.MaximumProjection(resampled, 2)[:, :, 0] fixed = sitk.Cast(fixed, sitk.sitkUInt8) resampled = sitk.Cast(resampled, sitk.sitkUInt8) fixed = sitk.RescaleIntensity(fixed, 0, 255) resampled = sitk.RescaleIntensity(resampled, 0, 255) plt.subplot(1, 2, 2) plt.title("Overlay") show.display_2d_image_overlay(fixed, resampled) del metric_values
def copy_registration_result(self, from_scale, to_scale): """ With this function it is possible to migrate the registration results from one scale to another. With very large images it is sometimes easier and faster to perform image registration with downsampled versions of the original images. The accuracy of the registration result is often very good, even with 60 percent downsampled images. Parameters ---------- :item from_scale The scale for which there is an existing registration result. :item to_scale The scale for which the new registration results should be calculated. Returns ------- """ # Check that the registration result for the specified scale # exists. assert from_scale in self.get_scales("registered") print("Copying registration results from %i to %i percent scale" % ( from_scale, to_scale)) if to_scale not in self.get_scales("original"): self.create_rescaled_images("original", to_scale) for channel in range(self.channel_count): print("Resampling view 0") self.set_active_image(0, channel, to_scale, "original") self.add_registered_image(self.data[self.active_image][:], to_scale, 0, channel, 0, self.get_voxel_size()) self.set_active_image(0, channel, to_scale, "registered") reference = self.get_itk_image() for view in range(1, self.get_number_of_images("original")): print("Resampling view %i" % view) self.set_active_image(view, channel, from_scale, "registered") transform = self.get_transform() transform_params = self.get_transform_parameters() self.set_active_image(view, channel, to_scale, "original") image = self.get_itk_image() angle = self.get_rotation_angle(radians=False) spacing = self.get_voxel_size() result = itkutils.convert_from_itk_image( itkutils.resample_image(image, transform, reference=reference) )[0] self.add_registered_image(result, to_scale, view, channel, angle, spacing) self.add_transform(to_scale, view, channel, transform_params[0], transform_params[1], transform_params[2])
def shift_and_sum(data, transforms, photosensor=0, detectors=None, supersampling=1.0): """ Adaptive ISM pixel reassignment. Please use one of the functions above to figure out the shifts first, if you haven't already. :param supersampling: Insert a number != 1, if you want to rescale the result image to a different size. This might make sense, if you the original sampling has been sampled sparsely :param data: ArrayDetectorData object with all the individual images :param transforms: ITK spatial transformation that are to be used for the resampling :param photosensor: The photosensor index, if more than one :param detectors: a list of detectors to be included in the reconstruction. If None given (default), all the images will be used :return: reconstruction result Image """ assert isinstance(data, ArrayDetectorData) assert isinstance(transforms, list) and len(transforms) == data.ndetectors if supersampling != 1.0: new_shape = list( int(i * supersampling) for i in data[photosensor, 0].shape) new_spacing = list(i / supersampling for i in data[photosensor, 0].spacing) output = Image(np.zeros(new_shape, dtype=np.float64), new_spacing) else: output = Image(np.zeros(data[photosensor, 0].shape, dtype=np.float64), data[photosensor, 0].spacing) if detectors is None: detectors = list(range(data.ndetectors)) for i in detectors: image = itk.resample_image(itk.convert_to_itk_image(data[photosensor, i]), transforms[i], reference=itk.convert_to_itk_image(output)) output += itk.convert_from_itk_image(image) return output
def get_resampled_result(self): """ Returns ------- Get the registration result as a resampled image. """ self.data.set_active_image(self.fixed_index, self.options.channel, self.options.scale, "original") fixed_image = self.data.get_itk_image() self.data.set_active_image(self.moving_index, self.options.channel, self.options.scale, "original") moving_image = self.data.get_itk_image() return ops_itk.resample_image(moving_image, self.final_transform, fixed_image)
def main(): options = miplib_entry_point_options.get_import_script_options(sys.argv[1:]) directory = options.data_dir_path # Create a new HDF5 file. If a file exists, new data will be appended. file_name = input("Give a name for the HDF5 file: ") file_name += ".hdf5" data_path = os.path.join(directory, file_name) data = image_data.ImageData(data_path) # Add image files that have been named according to the correct format for image_name in os.listdir(directory): full_path = os.path.join(directory, image_name) if full_path.endswith((".tiff", ".tif", ".mhd", ".mha")): images = read.get_image(full_path) spacing = images.spacing else: continue if options.normalize_inputs: images = (images * (255.0/images.max())).astype(numpy.uint8) if not all(x in image_name for x in params_c) or not any(x in image_name for x in image_types_c): print("Unrecognized image name %s. Skipping it." % image_name) continue image_type = image_name.split("_scale")[0] scale = image_name.split("scale_")[-1].split("_index")[0] index = image_name.split("index_")[-1].split("_channel")[0] channel = image_name.split("channel_")[-1].split("_angle")[0] angle = image_name.split("angle_")[-1].split(".")[0] assert all(x.isdigit() for x in (scale, index, channel, angle)) # data, angle, spacing, index, scale, channel, chunk_size=None if image_type == "original": data.add_original_image(images, scale, index, channel, angle, spacing) elif image_type == "registered": data.add_registered_image(images, scale, index, channel, angle, spacing) elif image_type == "psf": data.add_psf(images, scale, index, channel, angle, spacing) # Calculate resampled images if options.scales is not None: for scale in options.scales: print("Creating %s percent downsampled versions of the original images" % scale) data.create_rescaled_images("original", scale) # Add transforms for registered images. for transform_name in os.listdir(directory): if not transform_name.endswith(".txt"): continue if not all(x in transform_name for x in params_c) or not "transform" in transform_name: print("Unrecognized transform name %s. Skipping it." % transform_name) continue scale = transform_name.split("scale_")[-1].split("_index")[0] index = transform_name.split("index_")[-1].split("_channel")[0] channel = transform_name.split("channel_")[-1].split("_angle")[0] angle = transform_name.split("angle_")[-1].split(".")[0] full_path = os.path.join(directory, transform_name) # First calculate registered image if not in the data structure if not data.check_if_exists("registered", index, channel, scale): print("Resampling registered image for image nr. ", index) data.set_active_image(0, channel, scale, "original") reference = data.get_itk_image() data.set_active_image(index, channel, scale, "original") moving = data.get_itk_image() transform = read.__itk_transform(full_path, return_itk=True) registered = itkutils.resample_image(moving, transform, reference=reference) registered = itkutils.convert_from_itk_image(registered) spacing = registered.spacing data.add_registered_image(registered, scale, index, channel, angle, spacing) # The add it's transform transform_type, params, fixed_params = read.__itk_transform(full_path) data.add_transform(scale, index, channel, params, fixed_params, transform_type) # Calculate missing PSFs if options.calculate_psfs: data.calculate_missing_psfs() if options.copy_registration_result != -1: from_scale = options.copy_registration_result[0] to_scale = options.copy_registration_result[1] data.copy_registration_result(from_scale, to_scale) data.close()
def execute(self): """ Run image registration. All the views are registered one by one. The image at index 0 is used as a reference. """ # Get reference image. self.data.set_active_image(self.fixed_index, self.options.channel, self.options.scale, "original") fixed_image = self.data.get_itk_image() # Get moving image self.data.set_active_image(self.moving_index, self.options.channel, self.options.scale, "original") moving_image = self.data.get_itk_image() # INITIALIZATION # -------------- # Start by rotating the moving image with the known rotation angle. print('Initializing registration') manual_transform = sitk.Euler3DTransform() # Rotate around the physical center of the image. rotation_center = moving_image.TransformContinuousIndexToPhysicalPoint( [(index - 1) / 2.0 for index in moving_image.GetSize()]) manual_transform.SetCenter(rotation_center) # Rotation initial_rotation = self.data.get_rotation_angle(radians=True) if self.options.rot_axis == 0: manual_transform.SetRotation(initial_rotation, 0, 0) elif self.options.rot_axis == 1: manual_transform.SetRotation(0, initial_rotation, 0) else: manual_transform.SetRotation(0, 0, initial_rotation) # Translation manual_transform.SetTranslation([ self.options.y_offset, self.options.x_offset, self.options.z_offset ]) modified_moving_image = ops_itk.resample_image(moving_image, manual_transform) # 2. Run Automatic initialization transform = sitk.CenteredTransformInitializer( fixed_image, modified_moving_image, sitk.AffineTransform(3), sitk.CenteredTransformInitializerFilter.MOMENTS) # print "The initial transform is:" # print transform # Set initial transform self.registration.SetInitialTransform(transform) # SPATIAL MASK # ===================================================================== # The registration metric works more reliably when it knows where # non-zero # voxels are located. thd = self.options.mask_threshold fixed_mask = sitk.BinaryDilate( sitk.BinaryThreshold(fixed_image, 0, thd, 0, 1)) moving_mask = sitk.BinaryDilate( sitk.BinaryThreshold(modified_moving_image, 0, thd, 0, 1)) self.registration.SetMetricFixedMask(fixed_mask) self.registration.SetMetricMovingMask(moving_mask) # START # ====================================================================== if self.options.reg_enable_observers: # OBSERVERS self.registration.AddCommand(sitk.sitkStartEvent, registration.start_plot) self.registration.AddCommand( sitk.sitkIterationEvent, lambda: registration.plot_values(self.registration)) print("Starting registration of views " \ "%i (fixed) & %i (moving)" % (self.fixed_index, self.moving_index)) result = self.registration.Execute( sitk.Cast(fixed_image, sitk.sitkFloat32), sitk.Cast(modified_moving_image, sitk.sitkFloat32)) result = sitk.AffineTransform(result) # RESULTS # ===================================================================== # Combine two partial transforms into one. # self.final_transform = sitk.Transform(manual_transform) # self.final_transform.AddTransform(result) # The two resulting transforms are combined into one here, because # it is easier to save a single transform into a HDF5 file. A0 = numpy.asarray(manual_transform.GetMatrix()).reshape(3, 3) c0 = numpy.asarray(manual_transform.GetCenter()) t0 = numpy.asarray(manual_transform.GetTranslation()) A1 = numpy.asarray(result.GetMatrix()).reshape(3, 3) c1 = numpy.asarray(result.GetCenter()) t1 = numpy.asarray(result.GetTranslation()) combined_mat = numpy.dot(A0, A1) combined_center = c1 combined_translation = numpy.dot(A0, t1 + c1 - c0) + t0 + c0 - c1 self.final_transform = sitk.AffineTransform(combined_mat.flatten(), combined_translation, combined_center) # Print final metric value and stopping condition print(('Final metric value: {0}'.format( self.registration.GetMetricValue()))) print(('Optimizer\'s stopping condition, {0}'.format( self.registration.GetOptimizerStopConditionDescription()))) print(self.final_transform) if self.options.reg_enable_observers: registration.end_plot(fixed_image, moving_image, self.final_transform)
def main(): options = supertomo_options.get_transform_script_options(sys.argv[1:]) fixed_image = None moving_image = None transform = None if options.hdf: raise NotImplementedError("Only single image files are supported " "currently") else: # CHECK FILES # Check that the fixed image exists fixed_image_path = os.path.join( options.working_directory, options.fixed_image ) if not os.path.isfile(fixed_image_path): raise ValueError('No such file: %s' % options.fixed_image) # Check that the EM image exists moving_image_path = os.path.join( options.working_directory, options.moving_image) if not os.path.isfile(moving_image_path): raise ValueError('No such file: %s' % options.moving_image) transform_path = os.path.join( options.working_directory, options.transform) if not os.path.isfile(transform_path): raise ValueError('No such file: %s' % options.transform) # READ FILES fixed_image = ioutils.get_image(fixed_image_path, return_itk=True) moving_image = ioutils.get_image(moving_image_path, return_itk=True) transform = ioutils.__itk_transform(transform_path, return_itk=True) transformed_image = itkutils.resample_image(moving_image, transform, fixed_image) # OUTPUT ########################################################################## output_dir = datetime.datetime.now().strftime("%Y-%m-%d") + '_supertomo_out' output_dir = os.path.join(options.working_directory, output_dir) if not os.path.exists(output_dir): os.makedirs(output_dir) # Files are named according to current time (the date will be # in the folder name) date_now = datetime.datetime.now().strftime("%H-%M-%S") file_name = date_now + '_transformed.mha' rgb_image = itkutils.make_composite_rgb_image(fixed_image, transformed_image) image_path = os.path.join(output_dir, file_name) sitk.WriteImage(rgb_image, image_path)
def main(): options = miplib_entry_point_options.get_correlate_tem_script_options( sys.argv[1:]) # SETUP ########################################################################## # Check that the STED image exists options.sted_image_path = os.path.join(options.working_directory, options.sted_image_path) if not os.path.isfile(options.sted_image_path): print('No such file: %s' % options.sted_image_path) sys.exit(1) # Check that the EM image exists options.em_image_path = os.path.join(options.working_directory, options.em_image_path) if not os.path.isfile(options.em_image_path): print('No such file: %s' % options.em_image_path) sys.exit(1) # Load input images sted_image = sitk.ReadImage(options.sted_image_path) em_image = sitk.ReadImage(options.em_image_path) # PRE-PROCESSING ########################################################################## # Save originals for possible later use sted_original = sted_image em_original = em_image if options.dilation_size != 0: print('Degrading input images with Dilation filter') sted_image = itkutils.grayscale_dilate_filter(sted_image, options.dilation_size) em_image = itkutils.grayscale_dilate_filter(em_image, options.dilation_size) if options.gaussian_variance != 0.0: print('Degrading the EM image with Gaussian blur filter') em_image = itkutils.gaussian_blurring_filter(em_image, options.gaussian_variance) if options.mean_kernel != 0: sted_image = itkutils.mean_filter(sted_image, options.mean_kernel) em_image = itkutils.mean_filter(em_image, options.mean_kernel) #todo: convert the pixel type into a PixelID enum if options.use_internal_type: sted_image = itkutils.type_cast(sted_image, options.image_type) em_image = itkutils.type_cast(em_image, options.image_type) # # if options.threshold > 0: # sted_image = itkutils.threshold_image_filter( # sted_image, # options.threshold # ) # # em_image = itkutils.threshold_image_filter( # em_image, # options.threshold # ) if options.normalize: print('Normalizing images') # Normalize sted_image = itkutils.normalize_image_filter(sted_image) em_image = itkutils.normalize_image_filter(em_image) if options.rescale_to_full_range: sted_image = itkutils.rescale_intensity(sted_image) em_image = itkutils.rescale_intensity(em_image) # REGISTRATION ########################################################################## if options.tfm_type == "rigid": final_transform = registration.itk_registration_rigid_2d( sted_image, em_image, options) elif options.tfm_type == "similarity": final_transform = registration.itk_registration_similarity_2d( sted_image, em_image, options) else: raise ValueError(options.tfm_type) em_image = itkutils.resample_image(em_original, final_transform, reference=sted_image) # OUTPUT ########################################################################## while True: keep = input("Do you want to keep the results (yes/no)? ") if keep in ('y', 'Y', 'yes', 'YES'): # Files are named according to current time (the date will be # in the folder name) # Output directory name will be automatically formatted according # to current date and time; e.g. 2014-02-18_supertomo_output output_dir = datetime.datetime.now().strftime( "%Y-%m-%d") + '_clem_output' output_dir = os.path.join(options.working_directory, output_dir) if not os.path.exists(output_dir): os.makedirs(output_dir) date_now = datetime.datetime.now().strftime("%H-%M-%S") file_name = date_now + \ '-clem_registration-' + \ options.registration_method + \ '.tiff' file_path = os.path.join(output_dir, file_name) tfm_name = date_now + '_transform' + '.txt' tfm_path = os.path.join(output_dir, tfm_name) sitk.WriteTransform(final_transform, tfm_path) rgb_image = itkutils.make_composite_rgb_image( sted_original, em_image) sitk.WriteImage(rgb_image, file_path) print("The image was saved to %s and the transform to %s in " \ "the output directory %s" % (file_name, tfm_name, output_dir)) break elif keep in ('n', 'N', 'no', 'No'): print("Exiting without saving results.") break else: print("Unkown command. Please state yes or no")