# Reorient the displacement field according to its grid-to-space # transform dcopy = np.copy(d) vfu.reorient_vector_field_3d(dcopy, field_grid2world) extended_dcopy = np.zeros((ns + 2, nr + 2, nc + 2, 3), dtype=floating) extended_dcopy[1:ns + 1, 1:nr + 1, 1:nc + 1, :] = dcopy # Compute the warping coordinates (see warp_2d documentation) Y = np.apply_along_axis(A.dot, 0, X)[0:3, ...] Z = np.zeros_like(X) Z[0, ...] = map_coordinates(extended_dcopy[..., 0], Y + 1, order=1) Z[1, ...] = map_coordinates(extended_dcopy[..., 1], Y + 1, order=1) Z[2, ...] = map_coordinates(extended_dcopy[..., 2], Y + 1, order=1) Z[3, ...] = 0 Z = np.apply_along_axis(C.dot, 0, Z)[0:3, ...] T = np.apply_along_axis(B.dot, 0, X)[0:3, ...] W = T + Z # Test bilinear interpolation expected = map_coordinates(sphere, W, order=1) warped = vfu.warp_3d(sphere, dcopy, A, B, C, np.array(sh, dtype=np.int32)) # assert_array_almost_equal(warped, expected, decimal=5) np.save('sl_syn_warp_3d.npy', warped) # Test nearest neighbor interpolation # expected = map_coordinates(sphere, W, order=0) # warped = vfu.warp_3d_nn(sphere, dcopy, A, B, C, # np.array(sh, dtype=np.int32)) # assert_array_almost_equal(warped, expected, decimal=5)
def test_warp(shape): """Tests the cython implementation of the 3d warpings against scipy.""" ndim = len(shape) radius = shape[0] / 3 if ndim == 3: # Create an image of a sphere volume = vfu.create_sphere(*shape, radius) volume = np.array(volume, dtype=floating) # Create a displacement field for warping d, dinv = vfu.create_harmonic_fields_3d(*shape, 0.2, 8) else: # Create an image of a circle volume = vfu.create_circle(*shape, radius) volume = np.array(volume, dtype=floating) # Create a displacement field for warping d, dinv = vfu.create_harmonic_fields_2d(*shape, 0.2, 8) d = np.asarray(d).astype(floating) if ndim == 3: # Select an arbitrary rotation axis axis = np.array([0.5, 2.0, 1.5]) # Select an arbitrary translation matrix t = 0.1 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) theta = np.pi / 5 s = 1.1 rot = np.zeros(shape=(4, 4)) rot[:3, :3] = geometry.rodrigues_axis_rotation(axis, theta) rot[3, 3] = 1.0 scale = np.array([[1 * s, 0, 0, 0], [0, 1 * s, 0, 0], [0, 0, 1 * s, 0], [0, 0, 0, 1]]) elif ndim == 2: # Select an arbitrary translation matrix t = 0.1 trans = np.array([[1, 0, -t * shape[0]], [0, 1, -t * shape[1]], [0, 0, 1]]) trans_inv = np.linalg.inv(trans) theta = -1 * np.pi / 6.0 s = 0.42 ct = np.cos(theta) st = np.sin(theta) rot = np.array([[ct, -st, 0], [st, ct, 0], [0, 0, 1]]) scale = np.array([[1 * s, 0, 0], [0, 1 * s, 0], [0, 0, 1]]) aff = trans_inv.dot(scale.dot(rot.dot(trans))) # Select arbitrary (but different) grid-to-space transforms sampling_grid2world = scale field_grid2world = aff field_world2grid = np.linalg.inv(field_grid2world) image_grid2world = aff.dot(scale) image_world2grid = np.linalg.inv(image_grid2world) A = field_world2grid.dot(sampling_grid2world) B = image_world2grid.dot(sampling_grid2world) C = image_world2grid # Reorient the displacement field according to its grid-to-space # transform dcopy = np.copy(d) if ndim == 3: vfu.reorient_vector_field_3d(dcopy, field_grid2world) expected = vfu.warp_3d(volume, dcopy, A, B, C, np.array(shape, dtype=np.int32)) elif ndim == 2: vfu.reorient_vector_field_2d(dcopy, field_grid2world) expected = vfu.warp_2d(volume, dcopy, A, B, C, np.array(shape, dtype=np.int32)) dcopyg = cupy.asarray(dcopy) volumeg = cupy.asarray(volume) Ag = cupy.asarray(A) Bg = cupy.asarray(B) Cg = cupy.asarray(C) warped = warp(volumeg, dcopyg, Ag, Bg, Cg, order=1, mode="constant") cupy.testing.assert_array_almost_equal(warped, expected, decimal=4)