def main():
    np.random.seed(1000)
    
    if len(sys.argv) < 3:
        print('register_example.py: Too few parameters. Give the path to two gray-scale image files.')
        print('Example: python2 register_example.py reference_image floating_image')
        return False

    ref_im_path = sys.argv[1]
    flo_im_path = sys.argv[2]

    ref_im = scipy.misc.imread(ref_im_path, 'L')
    flo_im = scipy.misc.imread(flo_im_path, 'L')

    # Save copies of original images
    ref_im_orig = ref_im.copy()
    flo_im_orig = flo_im.copy()

    ref_im = filters.normalize(ref_im, 0.0, None)
    flo_im = filters.normalize(flo_im, 0.0, None)
    
    diag = 0.5 * (transforms.image_diagonal(ref_im, spacing) + transforms.image_diagonal(flo_im, spacing))

    weights1 = np.ones(ref_im.shape)
    mask1 = np.ones(ref_im.shape, 'bool')
    weights2 = np.ones(flo_im.shape)
    mask2 = np.ones(flo_im.shape, 'bool')

    # Initialize registration framework for 2d images
    reg = Register(2)

    reg.set_report_freq(param_report_freq)
    reg.set_alpha_levels(alpha_levels)

    reg.set_reference_image(ref_im)
    reg.set_reference_mask(mask1)
    reg.set_reference_weights(weights1)

    reg.set_floating_image(flo_im)
    reg.set_floating_mask(mask2)
    reg.set_floating_weights(weights2)

    # Setup the Gaussian pyramid resolution levels
    
    reg.add_pyramid_level(4, 5.0)
    reg.add_pyramid_level(2, 3.0)
    reg.add_pyramid_level(1, 0.0)

    # Learning-rate / Step lengths [[start1, end1], [start2, end2] ...] (for each pyramid level)
    step_lengths = np.array([[1.0 ,1.0], [1.0, 0.5], [0.5, 0.1]])

    # Create the transform and add it to the registration framework (switch between affine/rigid transforms by commenting/uncommenting)
    # Affine
    reg.add_initial_transform(AffineTransform(2), np.array([1.0/diag, 1.0/diag, 1.0/diag, 1.0/diag, 1.0, 1.0]))
    # Rigid 2D
    #reg.add_initial_transform(Rigid2DTransform(2), np.array([1.0/diag, 1.0, 1.0]))

    # Set the parameters
    reg.set_iterations(param_iterations)
    reg.set_gradient_magnitude_threshold(0.001)
    reg.set_sampling_fraction(param_sampling_fraction)
    reg.set_step_lengths(step_lengths)

    # Create output directory
    directory = os.path.dirname('./test_images/output/')
    if not os.path.exists(directory):
        os.makedirs(directory)

    # Start the pre-processing
    reg.initialize('./test_images/output/')
    
    # Control the formatting of numpy
    np.set_printoptions(suppress=True, linewidth=200)

    # Start the registration
    reg.run()

    (transform, value) = reg.get_output(0)

    ### Warp final image
    c = transforms.make_image_centered_transform(transform, ref_im, flo_im, spacing, spacing)

    # Print out transformation parameters
    print('Transformation parameters: %s.' % str(transform.get_params()))

    # Create the output image
    ref_im_warped = np.zeros(ref_im.shape)

    # Transform the floating image into the reference image space by applying transformation 'c'
    c.warp(In = flo_im_orig, Out = ref_im_warped, in_spacing=spacing, out_spacing=spacing, mode='spline', bg_value = 0.0)

    # Save the registered image
    scipy.misc.imsave('./test_images/output/registered.png', ref_im_warped)

    # Compute the absolute difference image between the reference and registered images
    D1 = np.abs(ref_im_orig-ref_im_warped)
    err = np.sum(D1)
    print("Err: %f" % err)

    scipy.misc.imsave('./test_images/output/diff.png', D1)

    return True
def main():
    np.random.seed(1000)

    if len(sys.argv) < 3:
        print(
            f'{sys.argv[0]}: Too few parameters. Give the path to two gray-scale image files.'
        )
        print(f'Example: python {sys.argv[0]} reference_image floating_image')
        return False

    ref_im_path = sys.argv[1]
    flo_im_path = sys.argv[2]

    ref_im = Image.open(ref_im_path).convert('L')
    flo_im = Image.open(flo_im_path).convert('L')
    ref_im = np.asarray(ref_im) / 255.
    flo_im = np.asarray(flo_im) / 255.

    # Make copies of original images
    ref_im_orig = ref_im.copy()
    flo_im_orig = flo_im.copy()

    # Preprocess images
    ref_im = filters.normalize(ref_im, 0.0, None)
    flo_im = filters.normalize(flo_im, 0.0, None)

    weights1 = np.ones(ref_im.shape)
    mask1 = np.ones(ref_im.shape, 'bool')
    weights2 = np.ones(flo_im.shape)
    mask2 = np.ones(flo_im.shape, 'bool')

    # Initialize registration framework for 2d images
    reg = Register(2)
    reg.set_image_data(ref_im, flo_im, mask1, mask2, weights1, weights2)

    # Choose a registration model
    reg.set_model('alphaAMD', alpha_levels=alpha_levels, \
                  symmetric_measure=symmetric_measure, \
                  squared_measure=squared_measure)

    # Setup the Gaussian pyramid resolution levels
    reg.add_pyramid_level(4, 5.0)
    reg.add_pyramid_level(2, 3.0)
    reg.add_pyramid_level(1, 0.0)

    # Choose an optimizer and set optimizer-specific parameters
    # For GD and adam, learning-rate / Step lengths given by [[start1, end1], [start2, end2] ...] (for each pyramid level)
    reg.set_optimizer('adam', \
                      gradient_magnitude_threshold=0.01, \
                      iterations=param_iterations
                      )
    #    reg.set_optimizer('gd', \
    #                      step_length=np.array([1., 0.5, 0.25]), \
    #                      end_step_length=np.array([0.4, 0.2, 0.01]), \
    #                      gradient_magnitude_threshold=0.01, \
    #                      iterations=param_iterations
    #                      )
    #    reg.set_optimizer('scipy', \
    #                      iterations=param_iterations, \
    #                      epsilon=0.001 \
    #                      )

    # Scale all transform parameters to approximately the same order of magnitude, based on sizes of images
    diag = 0.5 * (transforms.image_diagonal(ref_im, spacing) +
                  transforms.image_diagonal(flo_im, spacing))

    # Create the initial transform and add it to the registration framework
    # (switch between affine/rigid transforms by commenting/uncommenting)
    #    # Affine
    #    initial_transform = transforms.AffineTransform(2)
    #    param_scaling = np.array([1.0/diag, 1.0/diag, 1.0/diag, 1.0/diag, 1.0, 1.0])
    #    reg.add_initial_transform(initial_transform, param_scaling=param_scaling)
    #    # Rigid 2D
    #    initial_transform = transforms.Rigid2DTransform()
    #    param_scaling = np.array([1.0/diag, 1.0, 1.0])
    #    reg.add_initial_transform(initial_transform, param_scaling=param_scaling)
    # Composite scale + rigid
    param_scaling = np.array([1.0 / diag, 1.0 / diag, 1.0, 1.0])
    initial_transform = transforms.CompositeTransform(2, [transforms.ScalingTransform(2, uniform=True), \
                                                transforms.Rigid2DTransform()])
    reg.add_initial_transform(initial_transform, param_scaling=param_scaling)

    # Set up other registration framework parameters
    reg.set_report_freq(param_report_freq)
    reg.set_sampling_fraction(param_sampling_fraction)

    # Create output directory
    directory = os.path.dirname(outdir)
    if not os.path.exists(directory):
        os.makedirs(directory)

    # Start the pre-processing
    reg.initialize(outdir)

    # Control the formatting of numpy
    np.set_printoptions(suppress=True, linewidth=200)

    # Start the registration
    reg.run()

    (transform, value) = reg.get_output(0)

    ### Warp final image
    c = transforms.make_image_centered_transform(transform, ref_im, flo_im,
                                                 spacing, spacing)

    # Print out transformation parameters and status
    print('Starting from %s, optimizer terminated with message: %s'%(str(initial_transform.get_params()), \
                                                                    reg.get_output_messages()[0]))
    print('Final transformation parameters: %s.' % str(transform.get_params()))

    # Create the output image
    ref_im_warped = np.zeros(ref_im.shape)
    mask = np.ones(flo_im_orig.shape, dtype='bool')
    warped_mask = np.zeros(ref_im.shape, dtype='bool')

    # Transform the floating image into the reference image space by applying transformation 'c'
    c.warp(In=flo_im_orig,
           Out=ref_im_warped,
           in_spacing=spacing,
           out_spacing=spacing,
           mode='spline',
           bg_value=0.0)
    c.warp(In=mask,
           Out=warped_mask,
           in_spacing=spacing,
           out_spacing=spacing,
           mode='spline',
           bg_value=0.0)

    # Save the registered image
    Image.fromarray(ref_im_warped).convert('RGB').save(outdir +
                                                       'registered.png')

    # Compute the absolute difference image between the reference and registered images
    D1 = np.abs(ref_im_orig - ref_im_warped)
    err = np.mean(D1[warped_mask])
    print("Err: %f" % err)

    Image.fromarray(D1).convert('RGB').save(outdir + 'diff.png')

    return True