예제 #1
0
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
예제 #2
0
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
예제 #3
0
    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])
예제 #4
0
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
예제 #5
0
    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)
예제 #6
0
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()
예제 #7
0
    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)
예제 #8
0
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)
예제 #9
0
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")