Example #1
0
    def register(self, img_obj: ImageClass, apply_to_self=True):
        """Register roi with image
        Do not apply threshold until after interpolation"""

        if apply_to_self is False:
            roi_copy = self.copy()
            roi_copy.register(img_obj=img_obj, apply_to_self=True)
            return roi_copy

        from mirp.imageProcess import interpolate_to_new_grid

        # Skip if image and/or is missing
        if img_obj is None or self.roi is None:
            return

        # Check whether registration is required
        registration_required = False

        # Mismatch in grid dimension
        if np.any(
            [np.abs(np.array(self.roi.size) - np.array(img_obj.size)) > 0.0]):
            registration_required = True

        # Mismatch in origin
        if np.any([np.abs(self.roi.origin - img_obj.origin) > 0.0]):
            registration_required = True

        # Mismatch in spacing
        if np.any([np.abs(self.roi.spacing - img_obj.spacing) > 0.0]):
            registration_required = True

        if not np.allclose(self.roi.orientation, img_obj.orientation):
            raise ValueError(
                "Cannot register segmentation and image object due to different alignments. "
                "Please use an external programme to transfer segmentation to the image."
            )

        if registration_required:
            # Register roi to image; this transforms the roi grid into
            self.roi.size, sample_spacing, voxel_grid, grid_origin = \
                interpolate_to_new_grid(orig_dim=self.roi.size,
                                        orig_spacing=self.roi.spacing,
                                        orig_vox=self.roi.get_voxel_grid(),
                                        sample_dim=img_obj.size,
                                        sample_spacing=img_obj.spacing,
                                        grid_origin=np.dot(self.roi.m_affine_inv, np.transpose(img_obj.origin - self.roi.origin)),
                                        order=1,
                                        mode="nearest",
                                        align_to_center=False)

            # Update origin before spacing, because computing the origin requires the original affine matrix.
            self.roi.origin = self.roi.origin + np.dot(
                self.roi.m_affine, np.transpose(grid_origin))

            # Update spacing and affine matrix.
            self.roi.set_spacing(sample_spacing)

            # Update voxel grid
            self.roi.set_voxel_grid(voxel_grid=voxel_grid)
Example #2
0
    def register(self, img_obj, apply_to_self=True):
        """Register roi with image
        Do not apply threshold until after interpolation"""

        if apply_to_self is False:
            roi_copy = self.copy()
            roi_copy.register(img_obj=img_obj, apply_to_self=True)
            return roi_copy

        from mirp.imageProcess import interpolate_to_new_grid

        # Skip if image and/or is missing
        if img_obj is None or self.roi is None:
            return

        # Check whether registration is required
        registration_required = False

        # Mismatch in grid dimension
        if np.any(
            [np.abs(np.array(self.roi.size) - np.array(img_obj.size)) > 0.0]):
            registration_required = True

        # Mismatch in origin
        if np.any([np.abs(self.roi.origin - img_obj.origin) > 0.0]):
            registration_required = True

        # Mismatch in spacing
        if np.any([np.abs(self.roi.spacing - img_obj.spacing) > 0.0]):
            registration_required = True

        if registration_required:
            # Register roi to image; this transforms the roi grid into
            self.roi.size, self.roi.origin, self.roi.spacing, voxel_grid = \
                interpolate_to_new_grid(orig_dim=self.roi.size, orig_origin=self.roi.origin, orig_spacing=self.roi.spacing, orig_vox=self.roi.get_voxel_grid(),
                                        sample_dim=img_obj.size, sample_origin=img_obj.origin, sample_spacing=img_obj.spacing,
                                        order=1, mode="nearest", align_to_center=False)

            # Update slice position
            self.roi.slice_z_pos = self.roi.origin[0] + np.arange(
                self.roi.size[0]) * self.roi.spacing[0]

            # Update voxel grid
            self.roi.set_voxel_grid(voxel_grid=voxel_grid)
Example #3
0
    def translate(self, t_x=0.0, t_y=0.0, t_z=0.0):
        """Translate image volume"""
        from mirp.imageProcess import interpolate_to_new_grid

        # Skip for missing images
        if self.is_missing:
            return

        # Calculate the new sample origin after translation
        sample_origin = np.array(self.origin)
        sample_origin[0] += t_z * self.spacing[0]
        sample_origin[1] += t_y * self.spacing[1]
        sample_origin[2] += t_x * self.spacing[2]

        # Interpolate at shift points
        self.size, self.origin, self.spacing, upd_voxel_grid = \
            interpolate_to_new_grid(orig_dim=self.size, orig_origin=self.origin, orig_spacing=self.spacing, orig_vox=self.get_voxel_grid(),
                                    sample_dim=self.size, sample_origin=sample_origin, sample_spacing=self.spacing, order=1, mode="nearest")

        # Update voxel grid
        self.set_voxel_grid(voxel_grid=upd_voxel_grid)
Example #4
0
    def interpolate(self, by_slice, settings):
        """Performs interpolation of the image volume"""
        from mirp.imageProcess import interpolate_to_new_grid, gaussian_preprocess_filter

        # Skip for missing images
        if self.is_missing:
            return

        # Local interpolation constants
        if None not in settings.img_interpolate.new_spacing:
            iso_spacing = settings.img_interpolate.new_spacing[0]
            new_spacing = np.array([iso_spacing, iso_spacing, iso_spacing])  # Desired spacing in mm
        elif type(settings.img_interpolate.new_non_iso_spacing) in [list, tuple]:
            if None not in settings.img_interpolate.new_non_iso_spacing:
                non_iso_spacing = settings.img_interpolate.new_non_iso_spacing
                new_spacing = np.array(non_iso_spacing)
            else:
                new_spacing = self.spacing
        else:
            new_spacing = self.spacing

        # Read additional details
        order            = settings.img_interpolate.spline_order   # Order of multidimensional spline filter (0=nearest neighbours, 1=linear, 3=cubic)
        interpolate_flag = settings.img_interpolate.interpolate    # Whether to interpolate or not

        # Set spacing for interpolation across slices to the original spacing in case interpolation is only conducted within the slice
        if by_slice:    new_spacing[0] = self.spacing[0]

        # Image translation
        translate_z = settings.vol_adapt.translate_z[0]
        translate_y = settings.vol_adapt.translate_y[0]
        translate_x = settings.vol_adapt.translate_x[0]

        # Convert to [0.0, 1.0] range
        translate_x = translate_x - np.floor(translate_x)
        translate_y = translate_y - np.floor(translate_y)
        translate_z = translate_z - np.floor(translate_z)
        trans_vec = np.array([translate_z, translate_y, translate_x])

        # Add translation fractions
        self.transl_fraction_x = translate_x
        self.transl_fraction_y = translate_y
        self.transl_fraction_z = translate_z

        # Skip if translation in both directions is 0.0
        if translate_x == 0.0 and translate_y == 0.0 and translate_z == 0.0  and not interpolate_flag: return None

        # Check if pre-processing is required
        if settings.img_interpolate.anti_aliasing:
            self.set_voxel_grid(voxel_grid=gaussian_preprocess_filter(orig_vox=self.get_voxel_grid(),
                                                                      orig_spacing=self.spacing,
                                                                      sample_spacing=new_spacing,
                                                                      param_beta=settings.img_interpolate.smoothing_beta,
                                                                      mode="nearest",
                                                                      by_slice=by_slice))

        # Interpolate image and positioning
        self.size, sample_spacing, upd_voxel_grid, grid_origin = \
            interpolate_to_new_grid(orig_dim=self.size,
                                    orig_spacing=self.spacing,
                                    orig_vox=self.get_voxel_grid(),
                                    sample_spacing=new_spacing,
                                    translation=trans_vec,
                                    order=order,
                                    mode="nearest",
                                    align_to_center=True)

        # Update origin before spacing, because computing the origin requires the original affine matrix.
        self.origin = self.origin + np.dot(self.m_affine, np.transpose(grid_origin))

        # Update spacing and affine matrix.
        self.set_spacing(sample_spacing)

        # Round intensities in case of modalities with inherently discretised intensities
        if (self.modality == "CT") and (self.spat_transform == "base"):
            upd_voxel_grid = np.round(upd_voxel_grid)
        elif (self.modality == "PT") and (self.spat_transform == "base"):
            upd_voxel_grid[upd_voxel_grid < 0.0] = 0.0

        # Set interpolation
        self.interpolated = True

        # Set interpolation algorithm
        if order == 0:
            self.interpolation_algorithm = "nnb"
        elif order == 1:
            self.interpolation_algorithm = "lin"
        elif order > 1:
            self.interpolation_algorithm = "si" + str(order)

        # Set voxel grid
        self.set_voxel_grid(voxel_grid=upd_voxel_grid)