コード例 #1
0
def test_make_correspondence():
    import hasi.align

    # Load meshes
    atlas_mesh = itk.meshread(OUTPUT_DIRECTORY + MESH_DIRECTORY + 'atlas.vtk')

    meshes = list()
    for idx in range(len(IMAGE_FILES)):
        mesh_file = IMAGE_FILES[idx].replace('.nrrd', '.vtk')
        meshes.append(
            itk.meshread(OUTPUT_DIRECTORY + MESH_DIRECTORY + mesh_file, itk.F))

    # Get mesh correspondence
    for idx in range(len(meshes)):
        mesh = meshes[idx]
        registered_atlas = hasi.align.register_template_to_sample(
            template_mesh=atlas_mesh, sample_mesh=mesh, max_iterations=500)
        mesh = hasi.align.resample_template_from_target(
            template_mesh=registered_atlas, target_mesh=mesh)
        meshes[idx] = mesh

    # Write out for shape analysis
    for idx in range(len(IMAGE_FILES)):
        mesh = meshes[idx]
        mesh_file = IMAGE_FILES[idx].replace('.nrrd', '.vtk')
        itk.meshwrite(mesh,
                      OUTPUT_DIRECTORY + CORRESPONDENCE_DIRECTORY + mesh_file)
コード例 #2
0
def test_create_atlas():
    import hasi.align

    # Read in images
    images = list()
    for image_file in IMAGE_FILES:
        image_name = str(Path(image_file).stem)
        cid = DATA_INDEX[image_name]
        store = IPFS_FS.get_mapper(f'ipfs://{cid}')
        image_ds = xr.open_zarr(store)
        image_da = image_ds[image_name]
        image = itk.image_from_xarray(image_da)
        images.append(image)

    # Paste into standard space
    images = hasi.align.paste_to_common_space(images)

    # Downsample template image
    TEMPLATE_IDX = 0
    SPARSE_DOWNSAMPLE_RATIO = 14
    template_image = \
        hasi.align.downsample_images([images[TEMPLATE_IDX]],SPARSE_DOWNSAMPLE_RATIO)[0]

    # Downsample dense images
    DENSE_DOWNSAMPLE_RATIO = 2
    images = hasi.align.downsample_images(images, DENSE_DOWNSAMPLE_RATIO)

    # Generate initial template mesh
    FEMUR_OBJECT_PIXEL_VALUE = 1
    template_mesh = hasi.align.binary_image_list_to_meshes(
        [template_image], object_pixel_value=FEMUR_OBJECT_PIXEL_VALUE)[0]

    # Generate meshes
    meshes = hasi.align.binary_image_list_to_meshes(
        images, object_pixel_value=FEMUR_OBJECT_PIXEL_VALUE)

    # Write out sample meshes for later shape analysis
    for idx in range(len(IMAGE_FILES)):
        mesh_file = IMAGE_FILES[idx].replace('.nrrd', '.vtk')
        mesh = meshes[idx]
        itk.meshwrite(mesh, OUTPUT_DIRECTORY + MESH_DIRECTORY + mesh_file)

    # Iteratively refine atlas
    NUM_ITERATIONS = 3
    for iteration in range(NUM_ITERATIONS):
        updated_mesh = hasi.align.refine_template_from_population(
            template_mesh=template_mesh,
            target_meshes=meshes,
            registration_iterations=200)
        distance = hasi.align.get_pairwise_hausdorff_distance(
            updated_mesh, template_mesh)
        template_mesh = updated_mesh

    # Verify final alignment distance
    assert 0.1 < distance < 0.5

    itk.meshwrite(updated_mesh,
                  OUTPUT_DIRECTORY + MESH_DIRECTORY + 'atlas.vtk')
コード例 #3
0
ファイル: diffeoregistrar.py プロジェクト: thewtex/HASI
    def register(self,
                 template_mesh: MeshType,
                 target_mesh: MeshType,
                 filepath: str = None,
                 verbose=False,
                 max_iterations=MAX_ITERATIONS) -> (TransformType, MeshType):
        template_image = self.mesh_to_image(template_mesh)
        target_image = self.mesh_to_image(target_mesh, template_image)

        self.filter.SetFixedImage(template_image)
        self.filter.SetMovingImage(target_image)

        self.filter.SetNumberOfIterations(max_iterations)

        def print_iteration():
            metric = self.filter.GetMetric()
            print(f'{metric}')

        if (verbose):
            self.filter.AddObserver(itk.ProgressEvent(), print_iteration)

        # Run registration
        self.filter.Update()

        # Update template mesh to match target
        transform = self.TransformType.New()
        transform.SetDisplacementField(self.filter.GetOutput())

        # TODO pythonic style
        TransformFilterType = \
            itk.TransformMeshFilter[self.MeshType,
                                    self.MeshType,
                                    itk.Transform[itk.F,self.Dimension,self.Dimension]]
        transform_filter = TransformFilterType.New(Input=template_mesh,
                                                   Transform=transform)
        transform_filter.Update()

        if filepath is not None:
            itk.meshwrite(transform_filter.GetOutput(), filepath)
            if (verbose):
                print(f'Wrote resulting mesh to {filepath}')

        return (transform, transform_filter.GetOutput())
コード例 #4
0
    raise Exception("`itk.imread()` fallback_only should have failed")
except Exception as e:
    if str(e) == "pixel_type must be set when using the fallback_only option":
        pass
    else:
        raise e

# test mesh read / write
mesh = itk.meshread(mesh_filename)
assert type(mesh) == itk.Mesh[itk.F, 3]
mesh = itk.meshread(mesh_filename, itk.UC)
assert type(mesh) == itk.Mesh[itk.UC, 3]
mesh = itk.meshread(mesh_filename, itk.UC, fallback_only=True)
assert type(mesh) == itk.Mesh[itk.F, 3]

itk.meshwrite(mesh, sys.argv[4])
itk.meshwrite(mesh, sys.argv[4], compression=True)

# test search
res = itk.search("Index")
assert res[0] == "Index"
assert res[1] == "index"
assert "ContinuousIndex" in res

res = itk.search("index", True)
assert "Index" not in res

# test down_cast
obj = itk.Object.cast(reader)
# be sure that the reader is casted to itk::Object
assert obj.__class__ == itk.Object
コード例 #5
0
    def register(self,
                 template_mesh: MeshType,
                 target_mesh: MeshType,
                 filepath: str = None,
                 verbose=False,
                 num_iterations=MAX_ITERATIONS) -> (TransformType, MeshType):

        template_image = self.mesh_to_image(template_mesh)
        target_image = self.mesh_to_image(target_mesh, template_image)

        ImageType = type(template_image)
        Dimension = template_image.GetImageDimension()

        metric = itk.MeanSquaresImageToImageMetricv4[ImageType,
                                                     ImageType].New()

        # Set physical dimensions for transform
        fixed_physical_dimensions = list()
        fixed_origin = list(template_image.GetOrigin())

        for i in range(0, Dimension):
            fixed_physical_dimensions.append(template_image.GetSpacing()[i] * \
                (template_image.GetLargestPossibleRegion().GetSize()[i] - 1))

        transform = self.TransformType.New(
            TransformDomainOrigin=fixed_origin,
            TransformDomainPhysicalDimensions=fixed_physical_dimensions,
            TransformDomainDirection=template_image.GetDirection())
        transform.SetTransformDomainMeshSize(
            [self.GRID_NODES_IN_ONE_DIMENSION - self.V_SPLINE_ORDER] *
            Dimension)

        # Transform parameters unbounded for typical registration problem
        number_of_parameters = transform.GetNumberOfParameters()
        self.optimizer.SetBoundSelection([0] * number_of_parameters)
        self.optimizer.SetUpperBound([0] * number_of_parameters)
        self.optimizer.SetLowerBound([0] * number_of_parameters)

        # Monitor optimization via observer
        def print_iteration():
            iteration = self.optimizer.GetCurrentIteration()
            metric = self.optimizer.GetCurrentMetricValue()
            infnorm = self.optimizer.GetInfinityNormOfProjectedGradient()
            print(f'{iteration} {metric} {infnorm}')

        if (verbose):
            self.optimizer.AddObserver(itk.IterationEvent(), print_iteration)

        self.optimizer.SetNumberOfIterations(num_iterations)

        # Define object to handle image registration
        RegistrationType = \
            itk.ImageRegistrationMethodv4[ImageType,ImageType]
        registration = RegistrationType.New(
            InitialTransform=transform,
            FixedImage=template_image,
            MovingImage=target_image,
            Metric=metric,
            Optimizer=self.optimizer,
            NumberOfLevels=self.NUMBER_OF_LEVELS,
            ShrinkFactorsPerLevel=self.SHRINK_FACTORS_PER_LEVEL)
        registration.SetSmoothingSigmasPerLevel(
            self.SMOOTHING_SIGMAS_PER_LEVEL)
        registration.InPlaceOn()

        # Run registration
        # NOTE ignore warning: "LBFGSBOptimizer does not support
        #     scaling, all scales set to one"
        #     Registration likely attempts to set scales by default,
        #     no observed impact on performance from this warning
        registration.Update()

        # TODO functional interface
        # image_registration_method()

        # Report results
        if (verbose):
            print('Solution = ' + str(list(transform.GetParameters())))

        # Update fixed image
        # TODO try inverting moving transform and compare results

        transformed_mesh = itk.transform_mesh_filter(template_mesh,
                                                     transform=transform)

        # Write out
        if filepath is not None:
            itk.meshwrite(transformed_mesh, filepath)
            if (verbose):
                print(f'Wrote resulting mesh to {filepath}')

        return (transform, transformed_mesh)