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
示例#2
0
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)
示例#3
0
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")