# ========================================================================== # # Copyright NumFOCUS # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0.txt # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # ==========================================================================*/ import sys import itk # # Check input parameters # INPUTS(fixedImage): {BrainProtonDensitySliceBorder20.png} # INPUTS(movingImage): {BrainProtonDensitySliceShifted13x17y.png} # if len(sys.argv) < 4: print("Missing Parameters") print( "Usage: ImageRegistration3.py fixed_image_file moving_image_file output_image_file" ) sys.exit(1) fixed_image_file = sys.argv[1] moving_image_file = sys.argv[2] output_image_file = sys.argv[3] # # Define data types # PixelType = itk.ctype('float') # # Read the fixed and moving images using filenames # from the command line arguments # fixed_image = itk.imread(fixed_image_file, PixelType) moving_image = itk.imread(moving_image_file, PixelType) Dimension = fixed_image.GetImageDimension() # # Create the spatial transform we will optimize. # initial_transform = itk.TranslationTransform[itk.D, Dimension].New() # # Create the matching metric we will use to compare the images during # optimization. matching_metric = itk.MeanSquaresImageToImageMetricv4[type(fixed_image), type(moving_image)].New() # # Create the optimizer we will use for optimization. # optimizer = itk.RegularStepGradientDescentOptimizerv4[itk.D].New() optimizer.SetLearningRate(4) optimizer.SetMinimumStepLength(0.001) optimizer.SetRelaxationFactor(0.5) optimizer.SetNumberOfIterations(100) # # Iteration Observer # def iteration_update(): metric_value = optimizer.GetValue() current_parameters = optimizer.GetCurrentPosition() parameter_list = [current_parameters[i] for i in range(len(current_parameters))] print(f"Metric: {metric_value:.8g} \tParameters: {parameter_list}") iteration_command = itk.PyCommand.New() iteration_command.SetCommandCallable(iteration_update) optimizer.AddObserver(itk.IterationEvent(), iteration_command) # # One level registration process without shrinking and smoothing. # registration = itk.ImageRegistrationMethodv4.New(fixed_image=fixed_image, moving_image=moving_image, optimizer=optimizer, metric=matching_metric, initial_transform=initial_transform,) registration.SetNumberOfLevels(1) registration.SetSmoothingSigmasPerLevel([0]) registration.SetShrinkFactorsPerLevel([1]) # # Execute the registration # registration.Update() # # Get the final parameters of the transformation # final_parameters = registration.GetOutput().Get().GetParameters() print("\nFinal Registration Parameters: ") print(f"Translation X = {final_parameters[0]:f}") print(f"Translation Y = {final_parameters[1]:f}") # # Now, we use the final transform for resampling the # moving image. # resampled_moving = itk.resample_image_filter(moving_image, transform=registration.GetTransform(), use_reference_image=True, reference_image=fixed_image, default_pixel_value=100) # # Cast to 8-bit unsigned integer pixels, supported by the PNG file format # OutputPixelType = itk.ctype('unsigned char') resampled_cast = resampled_moving.astype(OutputPixelType) # # Write the resampled image # itk.imwrite(resampled_cast, output_image_file)