def register(metric_name, static, moving, static_grid2space, moving_grid2space): if metric_name == "LCC": from dipy.align.imaffine import LocalCCMetric radius = 4 metric = LocalCCMetric(radius) elif metric_name == "MI": nbins = 32 sampling_prop = None metric = MattesMIMetric(nbins, sampling_prop) else: raise ValueError("Unknown metric " + metric_name) align_centers = True # schedule = ['TRANSLATION', 'RIGID', 'AFFINE'] schedule = ["TRANSLATION", "RIGID"] if True: level_iters = [100, 100, 100] sigmas = [3.0, 1.0, 0.0] factors = [4, 2, 1] else: level_iters = [100] sigmas = [0.0] factors = [1] affreg = AffineRegistration(metric=metric, level_iters=level_iters, sigmas=sigmas, factors=factors) out = np.eye(4) if align_centers: print("Aligning centers of mass") c_static = ndimage.measurements.center_of_mass(np.array(static)) c_static = static_grid2space.dot(c_static + (1,)) original_static = static_grid2space.copy() static_grid2space = static_grid2space.copy() static_grid2space[:3, 3] -= c_static[:3] out = align_centers_of_mass(static, static_grid2space, moving, moving_grid2space) for step in schedule: print("Optimizing: %s" % (step,)) transform = regtransforms[(step, 3)] params0 = None out = affreg.optimize( static, moving, transform, params0, static_grid2space, moving_grid2space, starting_affine=out ) if align_centers: print("Updating center-of-mass reference") T = np.eye(4) T[:3, 3] = -1 * c_static[:3] out = out.dot(T) return out
def test_align_centers_of_mass_3d(): np.random.seed(1246592) shape = (64, 64, 64) rm = 8 sp = vf.create_sphere(shape[0]//2, shape[1]//2, shape[2]//2, rm) moving = np.zeros(shape) # The center of mass will be (16, 16, 16), in image coordinates moving[:shape[0]//2, :shape[1]//2, :shape[2]//2] = sp[...] rs = 16 # The center of mass will be (32, 32, 32), in image coordinates static = vf.create_sphere(shape[0], shape[1], shape[2], rs) # Create arbitrary image-to-space transforms axis = np.array([.5, 2.0, 1.5]) t = 0.15 #translation factor trans = np.array([[1, 0, 0, -t*shape[0]], [0, 1, 0, -t*shape[1]], [0, 0, 1, -t*shape[2]], [0, 0, 0, 1]]) trans_inv = np.linalg.inv(trans) for rotation_angle in [-1 * np.pi/6.0, 0.0, np.pi/5.0]: for scale_factor in [0.83, 1.3, 2.07]: #scale rot = np.zeros(shape=(4,4)) rot[:3, :3] = geometry.rodrigues_axis_rotation(axis, rotation_angle) rot[3,3] = 1.0 scale = np.array([[1 * scale_factor, 0, 0, 0], [0, 1 * scale_factor, 0, 0], [0, 0, 1 * scale_factor, 0], [0, 0, 0, 1]]) static_grid2world = trans_inv.dot(scale.dot(rot.dot(trans))) moving_grid2world = np.linalg.inv(static_grid2world) # Expected translation c_static = static_grid2world.dot((32, 32, 32, 1))[:3] c_moving = moving_grid2world.dot((16, 16, 16, 1))[:3] expected = np.eye(4); expected[:3, 3] = c_moving - c_static # Implementation under test actual = imaffine.align_centers_of_mass(static, static_grid2world, moving, moving_grid2world) assert_array_almost_equal(actual.affine, expected)
def test_align_centers_of_mass_3d(): np.random.seed(1246592) shape = (64, 64, 64) rm = 8 sp = vf.create_sphere(shape[0] // 2, shape[1] // 2, shape[2] // 2, rm) moving = np.zeros(shape) # The center of mass will be (16, 16, 16), in image coordinates moving[:shape[0] // 2, :shape[1] // 2, :shape[2] // 2] = sp[...] rs = 16 # The center of mass will be (32, 32, 32), in image coordinates static = vf.create_sphere(shape[0], shape[1], shape[2], rs) # Create arbitrary image-to-space transforms axis = np.array([.5, 2.0, 1.5]) t = 0.15 #translation factor trans = np.array([[1, 0, 0, -t * shape[0]], [0, 1, 0, -t * shape[1]], [0, 0, 1, -t * shape[2]], [0, 0, 0, 1]]) trans_inv = np.linalg.inv(trans) for rotation_angle in [-1 * np.pi / 6.0, 0.0, np.pi / 5.0]: for scale_factor in [0.83, 1.3, 2.07]: #scale rot = np.zeros(shape=(4, 4)) rot[:3, :3] = geometry.rodrigues_axis_rotation( axis, rotation_angle) rot[3, 3] = 1.0 scale = np.array([[1 * scale_factor, 0, 0, 0], [0, 1 * scale_factor, 0, 0], [0, 0, 1 * scale_factor, 0], [0, 0, 0, 1]]) static_grid2world = trans_inv.dot(scale.dot(rot.dot(trans))) moving_grid2world = np.linalg.inv(static_grid2world) # Expected translation c_static = static_grid2world.dot((32, 32, 32, 1))[:3] c_moving = moving_grid2world.dot((16, 16, 16, 1))[:3] expected = np.eye(4) expected[:3, 3] = c_moving - c_static # Implementation under test actual = imaffine.align_centers_of_mass(static, static_grid2world, moving, moving_grid2world) assert_array_almost_equal(actual.affine, expected)
#c_static = ndimage.measurements.center_of_mass(np.array(static)) c_static = tuple(0.5 * np.array(static.shape, dtype=np.float64)) c_static = aff_static.dot(c_static+(1,)) correction_static = np.eye(4, dtype=np.float64) correction_static[:3,3] = -1 * c_static[:3] #c_moving = ndimage.measurements.center_of_mass(np.array(moving)) c_moving = tuple(0.5 * np.array(moving.shape, dtype=np.float64)) c_moving = aff_static.dot(c_moving+(1,)) correction_moving = np.eye(4, dtype=np.float64) correction_moving[:3,3] = -1 * c_moving[:3] new_aff_static = correction_static.dot(aff_static) new_aff_moving = correction_moving.dot(aff_moving) com = align_centers_of_mass(static, new_aff_static, moving, new_aff_moving) warped = com.transform(moving) rt.overlay_slices(static, warped, slice_type=2) # Create the metric nbins = 32 sampling_prop = None metric = MattesMIMetric(nbins, sampling_prop) # Create the optimizer level_iters = [10000, 1000, 100] sigmas = [3.0, 1.0, 0.0] factors = [4, 2, 1] affreg = AffineRegistration(metric=metric, level_iters=level_iters, sigmas=sigmas,
.. figure:: resampled_0.png :align: center .. figure:: resampled_1.png :align: center .. figure:: resampled_2.png :align: center **Input images before alignment**. """ """ We can obtain a very rough (and fast) registration by just aligning the centers of mass of the two images """ c_of_mass = align_centers_of_mass(static, static_grid2world, moving, moving_grid2world) """ We can now transform the moving image and draw it on top of the static image, registration is not likely to be good, but at least they will occupy roughly the same space """ transformed = c_of_mass.transform(moving) regtools.overlay_slices(static, transformed, None, 0, "Static", "Transformed", "transformed_com_0.png") regtools.overlay_slices(static, transformed, None, 1, "Static", "Transformed", "transformed_com_1.png") regtools.overlay_slices(static, transformed, None, 2, "Static", "Transformed", "transformed_com_2.png")