def main(): path_to_neutral = Path( '/Users/lls/Documents/face/data/headpose/Angle/neutral0/') path_to_smile = Path( '/Users/lls/Documents/face/data/headpose/Angle/down30') path_to_source = Path('/Users/lls/Documents/face/data/trump/trump') # PDM shape neutral = PDMModel(path_to_neutral, 20)[0].model.mean() smile = PDMModel(path_to_smile, 20)[0].model.mean() source_shape, source_img = PDMModel(path_to_source, 20) p_smile = project(smile, source_shape) p_neutral = project(neutral, source_shape) delta = (p_smile - p_neutral) * 1.5 ptsPath = '/Users/lls/Documents/face/data/trump/trump/trump_13.pts' trumpShape = mio.import_landmark_file(ptsPath).lms p_i = project(trumpShape, source_shape) new_p_i = p_i + delta reconstructed_img_i = source_shape.model.instance(new_p_i) trans_reconstructed_img_i = AlignmentAffine(reconstructed_img_i, trumpShape) reconstructed_img_i_pc = trans_reconstructed_img_i.apply( reconstructed_img_i) plt.subplot(241) reconstructed_img_i_pc.view() plt.gca().set_title('reconstructed_img_i_pc') plt.subplot(242) trumpShape.view() plt.gca().set_title('trumpShape') plt.show() '''
def Projection(trumpShapeModel, headMeanShape): '''ALIGN HEADSHAPE TO TRUMP''' transform = AlignmentAffine(headMeanShape, trumpShapeModel.model.mean()) normalized_shape = transform.apply(headMeanShape) '''HEAD P''' headWeights = trumpShapeModel.model.project(normalized_shape) return headWeights
def reconstructByPca(path_to_images): shape_model = pca(path_to_images) # Import shape shape = mio.import_builtin_asset.einstein_pts().lms # Find the affine transform that normalizes the shape # with respect to the mean shape transform = AlignmentAffine(shape, shape_model.model.mean()) # Normalize shape and project it normalized_shape = transform.apply(shape) weights = shape_model.model.project(normalized_shape) print("Weights: {}".format(weights)) # Reconstruct the normalized shape reconstructed_normalized_shape = shape_model.model.instance(weights) # Apply the pseudoinverse of the affine tansform reconstructed_shape = transform.pseudoinverse().apply( reconstructed_normalized_shape) # Visualize plt.subplot(121) shape.view(render_axes=False, axes_x_limits=0.05, axes_y_limits=0.05) plt.gca().set_title('Original shape') plt.subplot(122) reconstructed_shape.view(render_axes=False, axes_x_limits=0.05, axes_y_limits=0.05) plt.gca().set_title('Reconstructed shape')
def Reconstruction(trumpShapeModel, deltaWeights, trumpShape): transform = AlignmentAffine(trumpShape, trumpShapeModel.model.mean()) trumpWeights = trumpShapeModel.model.project(trumpShape) trumpWeights = trumpWeights + deltaWeights reconstructed_normalized_shape = trumpShapeModel.model.instance( trumpWeights) reconstructed_shape = transform.pseudoinverse().apply( reconstructed_normalized_shape) return reconstructed_shape
def ProjectionAndReconstruction(trumpShapeModel, headMeanShape): '''ALIGN HEADSHAPE TO TRUMP''' transform = AlignmentAffine(headMeanShape, trumpShapeModel.model.mean()) normalized_shape = transform.apply(headMeanShape) '''HEAD P''' headWeights = trumpShapeModel.model.project(normalized_shape) '''RECONSTRUCTION''' reconstructed_normalized_shape = trumpShapeModel.model.instance( headWeights) reconstructed_shape = transform.pseudoinverse().apply( reconstructed_normalized_shape) return reconstructed_shape, headWeights
def Reconstruction(trumpShapeModel, deltaWeights, trumpShape): trumpWeights, transform = Projection(trumpShapeModel, trumpShape) trumpWeights = trumpWeights + deltaWeights # print trumpWeights reconstructed_normalized_shape = trumpShapeModel.model.instance( trumpWeights) # reconstructed_shape = transform.pseudoinverse().apply( # reconstructed_normalized_shape) trans_reconstructed_shape = AlignmentAffine(reconstructed_normalized_shape, trumpShape) reconstructed_img_shape = trans_reconstructed_shape.apply( reconstructed_normalized_shape) return reconstructed_img_shape
def test_align_2d_affine_compose_target(): source = PointCloud(np.array([[0, 1], [1, 1], [-1, -5], [3, -5]])) target = UniformScale(2.0, n_dims=2).apply(source) original_estimate = AlignmentAffine(source, target) new_estimate = original_estimate.copy() new_estimate.compose_after_from_vector_inplace( np.array([0, 0, 0, 0, 1, 1.])) estimate_target = new_estimate.target correct_target = original_estimate.compose_after(Translation( [1, 1.])).apply(source) assert_allclose(estimate_target.points, correct_target.points)
def test_align_2d_affine_set_target(): linear_component = np.array([[1, -6], [-3, 2]]) translation_component = np.array([7, -8]) h_matrix = np.eye(3, 3) h_matrix[:-1, :-1] = linear_component h_matrix[:-1, -1] = translation_component affine = Affine(h_matrix) source = PointCloud(np.array([[0, 1], [1, 1], [-1, -5], [3, -5]])) target = affine.apply(source) # estimate the transform from source and source estimate = AlignmentAffine(source, source) # and set the target estimate.set_target(target) # check the estimates is correct assert_allclose(affine.h_matrix, estimate.h_matrix)
def test_align_2d_affine_set_h_matrix(): linear_component = np.array([[1, -6], [-3, 2]]) translation_component = np.array([7, -8]) h_matrix = np.eye(3, 3) h_matrix[:-1, :-1] = linear_component h_matrix[:-1, -1] = translation_component affine = Affine(h_matrix) source = PointCloud(np.array([[0, 1], [1, 1], [-1, -5], [3, -5]])) target = affine.apply(source) # estimate the transform from source and source estimate = AlignmentAffine(source, source) # and set the h_matrix estimate.set_h_matrix(affine.h_matrix) # check the estimates is correct assert_allclose(target.points, estimate.target.points)
def fit_from_bb(self, image, bounding_box, max_iters=20, gt_shape=None, crop_image=None, **kwargs): # generate the list of images to be fitted images, bounding_boxes, gt_shapes = self._prepare_image( image, bounding_box, gt_shape=gt_shape, crop_image=crop_image) # work out the affine transform between the initial shape of the # highest pyramidal level and the initial shape of the original image affine_correction = AlignmentAffine(bounding_boxes[-1], bounding_box) # run multilevel fitting algorithm_results = self._fit(images, bounding_boxes[0], max_iters=max_iters, gt_shapes=gt_shapes, **kwargs) # build multilevel fitting result fitter_result = self._fitter_result(image, algorithm_results, affine_correction, gt_shape=gt_shape) return fitter_result
def test_align_2d_affine_compose_target(): source = PointCloud(np.array([[0, 1], [1, 1], [-1, -5], [3, -5]])) target = UniformScale(2.0, n_dims=2).apply(source) original_estimate = AlignmentAffine(source, target) new_estimate = original_estimate.copy() new_estimate.compose_after_from_vector_inplace( np.array([0, 0, 0, 0, 1, 1.])) estimate_target = new_estimate.target correct_target = original_estimate.compose_after( Translation([1, 1.])).apply(source) assert_allclose(estimate_target.points, correct_target.points)
def fit(self, image, initial_shape, max_iters=50, gt_shape=None, **kwargs): r""" Fits the multilevel fitter to an image. Parameters ----------- image: :map:`Image` or subclass The image to be fitted. initial_shape: :map:`PointCloud` The initial shape estimate from which the fitting procedure will start. max_iters: `int` or `list` of `int`, optional The maximum number of iterations. If `int`, specifies the overall maximum number of iterations. If `list` of `int`, specifies the maximum number of iterations per level. gt_shape: :map:`PointCloud` The ground truth shape associated to the image. **kwargs: Additional keyword arguments that can be passed to specific implementations of ``_fit`` method. Returns ------- multi_fitting_result: :map:`MultilevelFittingResult` The multilevel fitting result containing the result of fitting procedure. """ # generate the list of images to be fitted images, initial_shapes, gt_shapes = self._prepare_image( image, initial_shape, gt_shape=gt_shape) # detach added landmarks from image del image.landmarks['initial_shape'] if gt_shape: del image.landmarks['gt_shape'] # work out the affine transform between the initial shape of the # highest pyramidal level and the initial shape of the original image affine_correction = AlignmentAffine(initial_shapes[-1], initial_shape) # run multilevel fitting fitting_results = self._fit(images, initial_shapes[0], max_iters=max_iters, gt_shapes=gt_shapes, **kwargs) # build multilevel fitting result multi_fitting_result = self._create_fitting_result( image, fitting_results, affine_correction, gt_shape=gt_shape) return multi_fitting_result
def _prepare_image(self, image, initial_shape): r""" Function the performs pre-processing on the image to be fitted. This involves the following steps: 1. Rescale image so that the provided initial_shape has the specified diagonal. 2. Compute features 3. Estimate the affine transform introduced by the rescale to diagonal and features extraction Parameters ---------- image : `menpo.image.Image` or subclass The image to be fitted. initial_shape : `menpo.shape.PointCloud` The initial shape estimate from which the fitting procedure will start. Returns ------- image : `menpo.image.Image` The feature-based image. initial_shape : `menpo.shape.PointCloud` The rescaled initial shape. affine_transform : `menpo.transform.Affine` The affine transform that is the inverse of the transformations introduced by the rescale wrt diagonal as well as the feature extraction. """ # Attach landmarks to the image, in order to make transforms easier image.landmarks['__initial_shape'] = initial_shape if self.diagonal is not None: # Rescale image so that initial_shape matches the provided diagonal tmp_image = image.rescale_landmarks_to_diagonal_range( self.diagonal, group='__initial_shape') else: tmp_image = image # Extract features feature_image = self.holistic_features(tmp_image) # Get final transformed landmarks new_initial_shape = feature_image.landmarks['__initial_shape'] # Now we have introduced an affine transform that consists of the image # rescaled based on the diagonal, as well as potential rescale # (down-sampling) caused by features. We need to store this transform # (estimated by AlignmentAffine) in order to be able to revert it at # the final fitting result. affine_transform = AlignmentAffine(new_initial_shape, initial_shape) # Detach added landmarks from image del image.landmarks['__initial_shape'] return feature_image, new_initial_shape, affine_transform
def fit(self, image, initial_shape, max_iters=50, gt_shape=None, error_type='me_norm', verbose=False, view=False, **kwargs): r""" Fits a single image. Parameters ----------- image: :class:`menpo.image.masked.MaskedImage` The image to be fitted. initial_shape: :class:`menpo.shape.PointCloud` The initial shape estimate from which the fitting procedure will start. max_iters: int or list, optional The maximum number of iterations. If int, then this will be the overall maximum number of iterations for all the pyramidal levels. If list, then a maximum number of iterations is specified for each pyramidal level. Default: 50 gt_shape: PointCloud The groundtruth shape of the image. Default: None error_type: 'me_norm', 'me' or 'rmse', optional. Specifies the way in which the error between the fitted and ground truth shapes is to be computed. Default: 'me_norm' verbose: boolean, optional If True, it prints information related to the fitting results (such as: final error, convergence, ...). Default: False view: boolean, optional If True, the final fitting result will be visualized. Default: False **kwargs: Returns ------- fitting_list: :map:`FittingResultList` A fitting result object. """ # copy image image = image.copy() # generate image pyramid images = self._prepare_image(image, initial_shape, gt_shape=gt_shape) # get ground truth shape per level if gt_shape: gt_shapes = [i.landmarks['gt_shape'].lms for i in images] else: gt_shapes = None # get initial shape per level initial_shapes = [i.landmarks['initial_shape'].lms for i in images] affine_correction = AlignmentAffine(initial_shapes[-1], initial_shape) # execute multilevel fitting fitting_results = self._fit(images, initial_shapes[0], max_iters=max_iters, gt_shapes=gt_shapes, **kwargs) # store result multilevel_fitting_result = self._create_fitting_result( image, fitting_results, affine_correction, gt_shape=gt_shape, error_type=error_type) if verbose: print(multilevel_fitting_result) if view: multilevel_fitting_result.view_final_fitting(new_figure=True) return multilevel_fitting_result
def _prepare_image(self, image, initial_shape, gt_shape=None): r""" Function the performs pre-processing on the image to be fitted. This involves the following steps: 1. Rescale image wrt the scale factor between the reference_shape and the initial_shape. 2. For each scale: 3. Compute features 4. Estimate the affine transform introduced by the rescale to reference shape and features extraction 5. Rescale image 6. Save affine transform, scale transform and final image Parameters ---------- image : `menpo.image.Image` or subclass The image to be fitted. initial_shape : `menpo.shape.PointCloud` The initial shape estimate from which the fitting procedure will start. gt_shape : `menpo.shape.PointCloud`, optional The ground truth shape associated to the image. Returns ------- images : `list` of `menpo.image.Image` The list of images per scale. initial_shapes : `list` of `menpo.shape.PointCloud` The list of initial shapes per scale. gt_shapes : `list` of `menpo.shape.PointCloud` The list of ground truth shapes per scale. affine_transforms : `list` of `menpo.transform.Affine` The list of affine transforms per scale that are the inverses of the transformations introduced by the rescale wrt the reference shape as well as the feature extraction. scale_transforms : `list` of `menpo.shape.Scale` The list of inverse scaling transforms per scale. """ # Attach landmarks to the image, in order to make transforms easier image.landmarks['__initial_shape'] = initial_shape if gt_shape: image.landmarks['__gt_shape'] = gt_shape # Rescale image wrt the scale factor between reference_shape and # initial_shape #tmp_image = image.rescale_to_pointcloud(self.reference_shape, # group='__initial_shape') tmp_image = image.rescale_to_pointcloud(gt_shape, group='__gt_shape') #tmp_image = image # For each scale: # 1. Compute features # 2. Estimate the affine transform introduced by the rescale to # reference shape and features extraction # 2. Rescale image # 3. Save affine transform, scale transform and final image images = [] affine_transforms = [] scale_transforms = [] for i in range(self.n_scales): # Extract features if (i == 0 or self.holistic_features[i] != self.holistic_features[i - 1]): # Compute features only if this is the first pass through # the loop or the features at this scale are different from # the features at the previous scale feature_image = self.holistic_features[i](tmp_image) # Until now, we have introduced an affine transform that # consists of the image rescale to the reference shape, # as well as potential rescale (down-sampling) caused by # features. We need to store this transform (estimated by # AlignmentAffine) in order to be able to revert it at the # final fitting result. affine_transforms.append( AlignmentAffine( feature_image.landmarks['__initial_shape'].lms, initial_shape)) else: # If features are not extracted, then the affine transform # should be identical with the one of the first (lowest) level. affine_transforms.append(affine_transforms[0]) # Rescale images according to scales if self.scales[i] != 1: # Scale feature images only if scale is different than 1 scaled_image, scale_transform = feature_image.rescale( self.scales[i], return_transform=True) else: # Otherwise the image remains the same and the transform is the # identity matrix. scaled_image = feature_image scale_transform = Scale(1., initial_shape.n_dims) # rewrite response map data # scaled_image.rspmap_data = scipy.ndimage.zoom(image.rspmap_data, zoom=[1, 1, float(scaled_image.height) / image.rspmap_data.shape[-2], # float(scaled_image.width) / image.rspmap_data.shape[-1]], order=1) # mode = 'nearest' scaled_image.rspmap_data = image.rspmap_data # Add scale transform to list scale_transforms.append(scale_transform) scaled_image.path = image.path # Add scaled image to list images.append(scaled_image) # Get initial shapes per level initial_shapes = [i.landmarks['__initial_shape'].lms for i in images] # Get ground truth shapes per level if gt_shape: gt_shapes = [i.landmarks['__gt_shape'].lms for i in images] else: gt_shapes = None # Detach added landmarks from image del image.landmarks['__initial_shape'] if gt_shape: del image.landmarks['__gt_shape'] return (images, initial_shapes, gt_shapes, affine_transforms, scale_transforms)
def fit(self, image, initial_shape, max_iters=50, gt_shape=None, crop_image=None, **kwargs): r""" Fits the multilevel algorithm to an image. Parameters ----------- image: :map:`Image` or subclass The image to be fitted. initial_shape: :map:`PointCloud` The initial shape estimate from which the fitting procedure will start. max_iters: `int` or `list` of `int`, optional The maximum number of iterations. If `int`, specifies the overall maximum number of iterations. If `list` of `int`, specifies the maximum number of iterations per level. gt_shape: :map:`PointCloud` The ground truth shape associated to the image. crop_image: `None` or float`, optional If `float`, it specifies the proportion of the border wrt the initial shape to which the image will be internally cropped around the initial shape range. If `None`, no cropping is performed. This will limit the fitting algorithm search region but is likely to speed up its running time, specially when the modeled object occupies a small portion of the image. **kwargs: Additional keyword arguments that can be passed to specific implementations of ``_fit`` method. Returns ------- multi_fitting_result: :map:`MultilevelFittingResult` The multilevel fitting result containing the result of fitting procedure. """ # generate the list of images to be fitted images, initial_shapes, gt_shapes = self._prepare_image( image, initial_shape, gt_shape=gt_shape, crop_image=crop_image) # detach added landmarks from image del image.landmarks['initial_shape'] if gt_shape: del image.landmarks['gt_shape'] # work out the affine transform between the initial shape of the # highest pyramidal level and the initial shape of the original image affine_correction = AlignmentAffine(initial_shapes[-1], initial_shape) # run multilevel fitting algorithm_results = self._fit(images, initial_shapes[0], max_iters=max_iters, gt_shapes=gt_shapes, **kwargs) # build multilevel fitting result fitter_result = self._fitter_result(image, algorithm_results, affine_correction, gt_shape=gt_shape) return fitter_result
def fit(self, image, group=None, label='all', initialization='from_gt_shape', noise_std=0.0, rotation=False, max_iters=50, verbose=True, view=False, error_type='me_norm', **kwargs): r""" Fits a single image. Parameters ----------- image: :class:`pybug.image.masked.MaskedImage` The image to be fitted. group: string, Optional The key of the landmark set that should be used. If None, and if there is only one set of landmarks, this set will be used. Default: None label: string, Optional The label of of the landmark manager that you wish to use. If no label is passed, the convex hull of all landmarks is used. Default: 'all' initialization: 'from_gt_shape' or 'detection', optional The type of initialization to be used for fitting the image. Default: 'from_gt_shape' noise_std: float The std of the gaussian noise used to produce the initial shape. Default: 0.0 rotation: boolean Specifies whether in-plane rotation is to be used to produce the initial shape. Default: False max_iters: int or list, optional The maximum number of iterations. If int, then this will be the overall maximum number of iterations for all the pyramidal levels. If list, then a maximum number of iterations is specified for each pyramidal level. Default: 50 verbose: boolean Whether or not to print information related to the fitting results (such as: final error, convergence, ...). Default: True view: boolean Whether or not the fitting results are to be displayed. Default: False error_type: 'me_norm', 'me' or 'rmse', optional. Specifies the way in which the error between the fitted and ground truth shapes is to be computed. Default: 'me_norm' Returns ------- FittingList: :class:`pybug.aam.fitting.FittingList` A fitting list object containing the fitting objects associated to each run. """ image = deepcopy(image) if isinstance(image.landmarks[group][label], LandmarkGroup): gt_shape = image.landmarks[group][label].lms else: if group or label is not 'all': raise ValueError('The specified group {} and/or ' 'label {} do not exist'.format(group, label)) elif initialization is not 'detection': raise ValueError('Initialization method {} cannot ' 'be used because the image is not ' 'landmarked'.format(initialization)) gt_shape = None if initialization is 'from_gt_shape': initial_shape = self._noisy_align_from_gt_shape( gt_shape, noise_std=noise_std, rotation=rotation) elif type is 'detection': initial_shape = self._detect_shape(noise_std=noise_std, rotation=rotation) else: raise ValueError('Unknown initialization string selected. ' 'Valid options are: "from_gt_shape", ' '"detection"') images = self._prepare_image(image, initial_shape, gt_shape=gt_shape) if gt_shape: gt_shapes = [i.landmarks['gt_shape'].lms for i in images] else: gt_shapes = None initial_shapes = [i.landmarks['initial_shape'].lms for i in images] affine_correction = AlignmentAffine(initial_shapes[-1], initial_shape) fittings = self._fit(images, initial_shapes[0], max_iters=max_iters, gt_shapes=gt_shapes, **kwargs) multiple_fitting = self._create_fitting(image, fittings, affine_correction, gt_shape=gt_shape, error_type=error_type) if verbose: multiple_fitting.print_fitting_info() if view: multiple_fitting.view_final_fitting(new_figure=True) return multiple_fitting
def affine_test(path_to_images): # create pca model based on training set shape_model = pca(path_to_images) # create test image # testImage = mio.import_builtin_asset.takeo_ppm() testImage = mio.import_image( '/home/sean/workplace/221/py-R-FCN-test/data/DB/face/300-w_face/otherDB/aflw-full/testset/0_image00002_1.jpg' ) # Find the affine transform that normalizes the shape # with respect to the mean shape # shape = testImage.landmarks['PTS'] # transform = AlignmentAffine(shape, shape_model.model.mean()) # image change size to adapt the scale of kp to that of target_kp tmp_image = testImage.rescale_to_pointcloud(shape_model.model.mean(), group='PTS') transform = AlignmentAffine(testImage.landmarks['PTS'], tmp_image.landmarks['PTS']) new_shape = transform.apply( testImage.landmarks['PTS']) # equal to kp of tmp # warp image # new_image = testImage.warp_to_shape(tmp_image.shape, transform.pseudoinverse(), # warp_landmarks=True, order=1, # mode='nearest', # return_transform=False) # # plt.subplot(131) # testImage.view_landmarks(marker_face_colour='white', marker_edge_colour='black', # marker_size=4, render_axes=True) # plt.gca().set_title('Original image') # plt.subplot(132) # new_image.view_landmarks(marker_face_colour='white', marker_edge_colour='black', # marker_size=4, render_axes=True) # plt.gca().set_title('Rescale image') # plt.subplot(133) # tmp_image.view_landmarks(marker_face_colour='white', marker_edge_colour='black', # marker_size=4, render_axes=True) # plt.gca().set_title('Template image') # create a noise shape # noisy_shape = noisy_shape_from_shape(testImage.landmarks['PTS'], testImage.landmarks['PTS'], # noise_percentage=0.2, # allow_alignment_rotation=True) # transform = AlignmentAffine(testImage.landmarks['PTS'], noisy_shape) # similarity = AlignmentSimilarity(testImage.landmarks['PTS'], # testImage.landmarks['PTS'], # rotation=True) s = compositions.scale_about_centre(testImage.landmarks['PTS'], 1) r = compositions.rotate_ccw_about_centre(testImage, 90) t = compositions.Translation([0, 0], testImage.n_dims) # transform = similarity.compose_after(t.compose_after(s.compose_after(r))) transform = t.compose_after(s.compose_after(r)) # new_shape = transform.apply(testImage.landmarks['PTS']) # warp image new_image = testImage.warp_to_shape(testImage.shape, transform.pseudoinverse(), warp_landmarks=True, order=1, mode='nearest', return_transform=False) plt.subplot(121) testImage.view_landmarks(marker_face_colour='white', marker_edge_colour='black', marker_size=4, render_axes=True) plt.gca().set_title('Original image') plt.subplot(122) new_image.view_landmarks(marker_face_colour='white', marker_edge_colour='black', marker_size=4, render_axes=True) plt.gca().set_title('Rescale image') plt.close('all')
def project(target, source_model): # align the source and target face transform = AlignmentAffine(target, source_model.model.mean()) normalized_target = transform.apply(target) weights = source_model.model.project(normalized_target) return weights
def affine_enhance(path_to_images, save_dir=None, scales=[1], rotations=[0], translations=[[0, 0]], mean_shape=1): if save_dir is not None: mk_dir(save_dir, 0) # load training images train_images = [] for path_to_image in path_to_images: for img in print_progress( mio.import_images(path_to_image, verbose=True)): train_images.append(img) print 'sum of training data: %d' % len(train_images) # create pca model based on training set # shape_model = pca(path_train_images) shape_model = pca_image(train_images) excepted_num = len(scales) * len(rotations) * len(translations) * len( train_images) completed_num = 0 for train_img in train_images: if mean_shape: transform = AlignmentAffine(train_img.landmarks['PTS'], shape_model.model.mean()) [r1, s, r2, t] = transform.decompose() # transform = r2.compose_after(s.compose_after(r1)) transform = r2.compose_after(r1) rotation_shape = transform.apply(train_img.landmarks['PTS']) offset = train_img.landmarks['PTS'].centre( ) - rotation_shape.centre() t = compositions.Translation(offset, train_img.n_dims) transform = t.compose_after(r2.compose_after(r1)) normal_image = train_img.warp_to_shape(train_img.shape, transform.pseudoinverse(), warp_landmarks=True, order=1, mode='nearest', return_transform=False) else: normal_image = train_img for scale in scales: for rotation in rotations: for translation in translations: s = compositions.scale_about_centre( normal_image.landmarks['PTS'], scale) r = compositions.rotate_ccw_about_centre( normal_image, rotation) t = compositions.Translation(translation, normal_image.n_dims) transform = t.compose_after(s.compose_after(r)) # warp image new_image = normal_image.warp_to_shape( normal_image.shape, transform.pseudoinverse(), warp_landmarks=True, order=1, mode='nearest', return_transform=False) # plt.subplot(121) # normal_image.view_landmarks(marker_face_colour='white', marker_edge_colour='black', # marker_size=4, render_axes=True) # plt.gca().set_title('Original image') # plt.subplot(122) # new_image.view_landmarks(marker_face_colour='white', marker_edge_colour='black', # marker_size=4, render_axes=True) # plt.gca().set_title('Rescale image') # plt.close('all') # save enhanced image with lable img_suffix = new_image.path.suffix lb_suffix = '.pts' dataType = filter(lambda x: x in str(new_image.path), support_types)[0] new_image_name = '%s_' % dataType + new_image.path.name.split( '.')[0] + '_s%s_r%s_x%s_y%s' % ( str(scale), str(rotation), str( translation[0]), str(translation[1])) img_path = os.path.join(save_dir, new_image_name + img_suffix) lb_path = os.path.join(save_dir, new_image_name + lb_suffix) mio.export_image(new_image, img_path, overwrite=True) mio.export_landmark_file(new_image.landmarks['PTS'], lb_path, overwrite=True) # plt.subplot(121) # new_image.view_landmarks(marker_face_colour='white', marker_edge_colour='black', # marker_size=4, render_axes=True) # plt.gca().set_title('new image') # save_image = mio.import_image(img_path) # plt.subplot(122) # save_image.view_landmarks(marker_face_colour='white', marker_edge_colour='black', # marker_size=4, render_axes=True) # plt.gca().set_title('saved image') # plt.close('all') completed_num = completed_num + 1 print 'completed: %d/%d' % (completed_num, excepted_num)