def test_basic_2d_rotation_axis_angle(): rotation_matrix = np.array([[0, 1], [-1, 0]]) rotation = Rotation(rotation_matrix) axis, angle = rotation.axis_and_angle_of_rotation() assert_allclose(axis, np.array([0, 0, 1])) assert_allclose((90 * np.pi)/180, angle)
def test_align_2d_rotation_set_h_matrix_raises_notimplemented_error(): rotation_matrix = np.array([[0, 1], [-1, 0]]) rotation = Rotation(rotation_matrix) source = PointCloud(np.array([[0, 1], [1, 1], [-1, -5], [3, -5]])) target = rotation.apply(source) # estimate the transform from source and source estimate = AlignmentRotation(source, source) # and set the target estimate.set_h_matrix(rotation.h_matrix)
def test_rotation_compose_before_homog(): # can't do this inplace - so should just give transform chain rotation = Rotation(np.array([[1, 0], [0, 1]])) homog = Homogeneous(np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1]])) res = rotation.compose_before(homog) assert(type(res) == Homogeneous)
def test_3d_rotation_as_vector(): a = np.sqrt(3.0) / 2.0 b = 0.5 # this is a rotation of -30 degrees about the x axis rotation_matrix = np.array([[1, 0, 0], [0, a, b], [0, -b, a]]) rotation = Rotation(rotation_matrix) assert_allclose(np.round(rotation.as_vector()[2:]), np.array([0., 0.]))
def test_align_2d_rotation(): rotation_matrix = np.array([[0, 1], [-1, 0]]) rotation = Rotation(rotation_matrix) source = PointCloud(np.array([[0, 1], [1, 1], [-1, -5], [3, -5]])) target = rotation.apply(source) # estimate the transform from source and target estimate = AlignmentRotation(source, target) # check the estimates is correct assert_allclose(rotation.h_matrix, estimate.h_matrix, atol=1e-14)
def test_3d_rotation_inverse_eye(): a = np.sqrt(3.0)/2.0 b = 0.5 # this is a rotation of -30 degrees about the x axis rotation_matrix = np.array([[1, 0, 0], [0, a, b], [0, -b, a]]) rotation = Rotation(rotation_matrix) transformed = rotation.compose_before(rotation.pseudoinverse()) assert_allclose(np.eye(4), transformed.h_matrix, atol=1e-15)
def test_basic_3d_rotation_axis_angle(): a = np.sqrt(3.0)/2.0 b = 0.5 # this is a rotation of -30 degrees about the x axis rotation_matrix = np.array([[1, 0, 0], [0, a, b], [0, -b, a]]) rotation = Rotation(rotation_matrix) axis, angle = rotation.axis_and_angle_of_rotation() assert_allclose(axis, np.array([1, 0, 0])) assert_allclose((-30 * np.pi)/180, angle)
def test_basic_3d_rotation(): a = np.sqrt(3.0)/2.0 b = 0.5 # this is a rotation of -30 degrees about the x axis rotation_matrix = np.array([[1, 0, 0], [0, a, b], [0, -b, a]]) rotation = Rotation(rotation_matrix) starting_vector = np.array([0, 1, 0]) transformed = rotation.apply(starting_vector) assert_allclose(np.array([0, a, -b]), transformed)
def test_transform_about_centre(): pixels_16 = np.arange(16, dtype=np.float) image = Image(pixels_16.reshape(4, 4)) transform = Rotation.init_from_2d_ccw_angle(180).compose_before( UniformScale(2, n_dims=2)) # rotate 90 + scale degrees transformed_img = image.transform_about_centre(transform, order=0) expected_pixels = np.rot90(np.repeat(np.repeat(pixels_16, 2).reshape(4, -1), 2, axis=0)[1:, 1:], k=2) assert transformed_img.shape == (7, 7) assert_allclose(transformed_img.pixels[0], expected_pixels)
def fit_from_camera(self, image, camera, instance=None, gt_mesh=None, max_iters=50, camera_update=False, focal_length_update=False, shape_prior_weight=1., texture_prior_weight=1., return_costs=False): # Execute multi-scale fitting algorithm_results = self._fit( image, camera, instance=instance, gt_mesh=gt_mesh, max_iters=max_iters, camera_update=camera_update, focal_length_update=focal_length_update, reconstruction_weight=1., shape_prior_weight=shape_prior_weight, texture_prior_weight=texture_prior_weight, landmarks_prior_weight=None, landmarks=None, return_costs=return_costs) # Return multi-scale fitting result return self._fitter_result( image=image, algorithm_results=algorithm_results, affine_transform=Rotation.init_identity(n_dims=2), gt_mesh=gt_mesh)
def test_basic_2d_rotation_axis_angle(): rotation_matrix = np.array([[0, 1], [-1, 0]]) rotation = Rotation(rotation_matrix) axis, angle = rotation.axis_and_angle_of_rotation() assert_allclose(axis, np.array([0, 0, 1])) assert_allclose((90 * np.pi) / 180, angle)
def rotation_compose_before_homog_test(): # can't do this inplace - so should just give transform chain rotation = Rotation(np.array([[1, 0], [0, 1]])) homog = Homogeneous(np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1]])) res = rotation.compose_before(homog) assert (type(res) == Homogeneous)
def test_rotation2d_from_vector_raises_notimplementederror(): Rotation.init_identity(2).from_vector(0)
def test_rotation2d_identity(): assert_allclose(Rotation.init_identity(2).h_matrix, np.eye(3))
def test_init_3d_from_quaternion(): q = np.array([1., 0., 0.27, 0.]) r = Rotation.init_3d_from_quaternion(q) axis, angle = r.axis_and_angle_of_rotation() assert_allclose(r.axis_and_angle_of_rotation()[0], np.array([0., 1., 0.])) assert np.round(angle * 180 / np.pi) == 30.
def align_mesh_to_template(source, target, scale_corrective=1.2): scale = Scale((target.norm() / source.norm()) * scale_corrective, n_dims=target.n_dims) translation = Translation(target.centre() - source.centre()) rotation = Rotation.init_from_3d_ccw_angle_around_x(-45) return rotation.compose_before(translation.compose_before(scale))
def augment_face_image(img, image_size=256, crop_size=248, angle_range=30, flip=True, warp_mode='constant'): """basic image augmentation: random crop, rotation and horizontal flip""" #from menpo def round_image_shape(shape, round): if round not in ['ceil', 'round', 'floor']: raise ValueError('round must be either ceil, round or floor') # Ensure that the '+' operator means concatenate tuples return tuple(getattr(np, round)(shape).astype(np.int)) # taken from MDM def mirror_landmarks_68(lms, im_size): return PointCloud(abs(np.array([0, im_size[1]]) - lms.as_vector( ).reshape(-1, 2))[mirrored_parts_68]) # taken from MDM def mirror_image(im): im = im.copy() im.pixels = im.pixels[..., ::-1].copy() for group in im.landmarks: lms = im.landmarks[group] if lms.points.shape[0] == 68: im.landmarks[group] = mirror_landmarks_68(lms, im.shape) return im flip_rand = np.random.random() > 0.5 # rot_rand = np.random.random() > 0.5 # crop_rand = np.random.random() > 0.5 rot_rand = True # like ECT crop_rand = True # like ECT if crop_rand: lim = image_size - crop_size min_crop_inds = np.random.randint(0, lim, 2) max_crop_inds = min_crop_inds + crop_size img = img.crop(min_crop_inds, max_crop_inds) if flip and flip_rand: img = mirror_image(img) if rot_rand: rot_angle = 2 * angle_range * np.random.random_sample() - angle_range # img = img.rotate_ccw_about_centre(rot_angle) # Get image's bounding box coordinates bbox = bounding_box((0, 0), [img.shape[0] - 1, img.shape[1] - 1]) # Translate to origin and rotate counter-clockwise trans = Translation(-img.centre(), skip_checks=True).compose_before( Rotation.init_from_2d_ccw_angle(rot_angle, degrees=True)) rotated_bbox = trans.apply(bbox) # Create new translation so that min bbox values go to 0 t = Translation(-rotated_bbox.bounds()[0]) trans.compose_before_inplace(t) rotated_bbox = trans.apply(bbox) # Output image's shape is the range of the rotated bounding box # while respecting the users rounding preference. shape = round_image_shape(rotated_bbox.range() + 1, 'round') img = img.warp_to_shape( shape, trans.pseudoinverse(), warp_landmarks=True, mode=warp_mode) img = img.resize([image_size, image_size]) return img
def init_from_image_shape_and_vector(cls, image_shape, vector): r = Rotation.init_identity(n_dims=3) t = Translation.init_identity(n_dims=3) p = PerspectiveProjection(focal_length=1, image_shape=image_shape) return cls(r, t, p).from_vector(vector)
def test_rotation3d_identity(): assert_allclose(Rotation.identity(3).h_matrix, np.eye(4))
def test_rotation_set_h_matrix_raises_notimplementederror(): r = Rotation(np.array([[1, 0], [0, 1]])) r.set_h_matrix(r.h_matrix)
def test_rotation3d_from_vector_raises_notimplementederror(): Rotation.identity(3).from_vector(0)
def test_3d_rotation_n_parameters(): assert Rotation.init_identity(3).n_parameters == 4
def test_rotation3d_as_vector_raises_notimplementederror(): Rotation.identity(3).as_vector()
def test_basic_2d_rotation(): rotation_matrix = np.array([[0, 1], [-1, 0]]) rotation = Rotation(rotation_matrix) assert_allclose(np.array([0, -1]), rotation.apply(np.array([1, 0])))
def solve_pnp( points_2d, points_3d, intrinsic_matrix, distortion_coefficients=None, pnp_method=SOLVEPNP_ITERATIVE, n_iterations=100, reprojection_error=8.0, initial_transform=None, ): """ Use OpenCV to solve the Perspective-N-Point problem (PnP). Uses Ransac PnP as this typically provides better results. The image and mesh must both have the same landmark group name attached. Note the intrinsic matrix (if given) must be in "OpenCV" space and thus has the "x" and "y" axes flipped w.r.t the menpo norm. E.g. the intrinsic matrix is defined as follows: [fx, 0, cx, 0] [ 0, fy, cy, 0] [ 0, 0, 1, 0] [ 0, 0, 0, 1] Parameters ---------- points_2d : :map`Pointcloud` or subclass The 2D points in the image to solve the PnP problem with. points_3d : :map`Pointcloud` or subclass The 3D points to solve the PnP problem with group : str, optional The name of the landmark group intrinsic_matrix : :map`Homogeneous` The intrinsic matrix - if the intrinsic matrix is unknow please see usage of pinhole_intrinsic_matrix() distortion_coefficients : ``(D,)`` `ndarray` The distortion coefficients (if not given assumes 0 coefficients). See the OpenCV documentation for the distortion coefficient types that are supported. pnp_method : int The OpenCV PNP method e.g. cv2.SOLVEPNP_ITERATIVE or otherwise n_iterations : int The number of iterations to perform reprojection_error : float The maximum reprojection error to allow for a point to be considered an inlier. initial_transform : :map`Homogeneous` The initialization for the cv2.SOLVEPNP_ITERATIVE method. Compatible with the returned model transformation returned by this method. Returns ------- model_view_t : :map`Homogeneous` The combined ModelView transform. Can be used to place the 3D points in "eye space". proj_t : :map`Homogeneous` A transform that can be used to project the input 3D points back into the image """ import cv2 if distortion_coefficients is None: distortion_coefficients = np.zeros(4) r_vec = t_vec = None if initial_transform is not None: if pnp_method != cv2.SOLVEPNP_ITERATIVE: raise ValueError( "Initial estimates can only be given to SOLVEPNP_ITERATIVE") else: r_vec = cv2.Rodrigues(initial_transform.h_matrix[:3, :3])[0] t_vec = initial_transform.h_matrix[:3, -1].ravel() converged, r_vec, t_vec, _ = cv2.solvePnPRansac( points_3d.points, points_2d.points[:, ::-1], intrinsic_matrix.h_matrix[:3, :3], distortion_coefficients, flags=pnp_method, iterationsCount=n_iterations, reprojectionError=reprojection_error, useExtrinsicGuess=r_vec is not None, rvec=r_vec, tvec=t_vec, ) if not converged: raise ValueError("cv2.solvePnPRansac failed to converge") rotation = Rotation(cv2.Rodrigues(r_vec)[0]) translation = Translation(t_vec.ravel()) model_view_t = rotation.compose_before(translation) proj_t = intrinsic_matrix.compose_before( flip_xy_yx()).compose_before(_drop_h) return model_view_t, proj_t
def test_rotation3d_as_vector_raises_notimplementederror(): Rotation.init_identity(3).as_vector()
def test_rotation3d_init_from_3d_ccw_angle_around_z(): assert_allclose( Rotation.init_from_3d_ccw_angle_around_z(90).apply(np.array([0, 1, 0])), np.array([-1, 0, 0]), atol=1e-6)
def test_rotation2d_as_vector_raises_notimplementederror(): with raises(NotImplementedError): Rotation.init_identity(2).as_vector()
def test_rotation2d_n_parameters_raises_notimplementederror(): rot_matrix = np.eye(2) t = Rotation(rot_matrix) with raises(NotImplementedError): t.n_parameters
def test_rotation3d_n_parameters_raises_notimplementederror(): rot_matrix = np.eye(3) t = Rotation(rot_matrix) # Throws exception t.n_parameters