def test_nonuniformscale2d_update_from_vector(): scale = np.array([3, 4]) h**o = np.array([[scale[0], 0, 0], [0, scale[1], 0], [0, 0, 1]]) tr = NonUniformScale(np.array([1, 2])) tr._from_vector_inplace(scale) assert_equal(tr.h_matrix, h**o)
def test_scale_2d_pseudoinverse(): scale1 = 0.5 scale2 = 4.0 h**o = np.array([[scale1, 0, 0], [ 0, scale2, 0], [ 0, 0, 1]]) tr = NonUniformScale([1/scale1, 1/scale2]) assert_almost_equal(tr.pseudoinverse().h_matrix, h**o)
def test_nonuniformscale2d_from_vector(): scale = np.array([1, 2]) h**o = np.array([[scale[0], 0, 0], [0, scale[1], 0], [0, 0, 1]]) tr = NonUniformScale.init_identity(2).from_vector(scale) assert_equal(tr.h_matrix, h**o)
def glyph(self, vectors_block_size=10, use_negative=False, channels=None): r""" Create glyph of a feature image. If feature_data has negative values, the use_negative flag controls whether there will be created a glyph of both positive and negative values concatenated the one on top of the other. Parameters ---------- vectors_block_size: int Defines the size of each block with vectors of the glyph image. use_negative: bool Defines whether to take into account possible negative values of feature_data. """ # first, choose the appropriate channels if channels is None: pixels = self.pixels[..., :4] elif channels != 'all': pixels = self.pixels[..., channels] else: pixels = self.pixels # compute the glyph negative_weights = -pixels scale = np.maximum(pixels.max(), negative_weights.max()) pos = _create_feature_glyph(pixels, vectors_block_size) pos = pos * 255 / scale glyph_image = pos if use_negative and pixels.min() < 0: neg = _create_feature_glyph(negative_weights, vectors_block_size) neg = neg * 255 / scale glyph_image = np.concatenate((pos, neg)) glyph = Image(glyph_image) # correct landmarks from menpo.transform import NonUniformScale image_shape = np.array(self.shape, dtype=np.double) glyph_shape = np.array(glyph.shape, dtype=np.double) nus = NonUniformScale(glyph_shape / image_shape) glyph.landmarks = self.landmarks nus.apply_inplace(glyph.landmarks) return glyph
def test_nonuniformscale_set_h_matrix_raises_notimplementederror(): s = NonUniformScale([2, 3, 4]) s.set_h_matrix(s.h_matrix)
def rescale(self, scale, interpolator='scipy', round='ceil', **kwargs): r""" Return a copy of this image, rescaled by a given factor. Landmarks are rescaled appropriately. Parameters ---------- scale : float or tuple The scale factor. If a tuple, the scale to apply to each dimension. If a single float, the scale will be applied uniformly across each dimension. interpolator : 'scipy', optional The interpolator that should be used to perform the warp. Default: 'scipy' round: {'ceil', 'floor', 'round'} Rounding function to be applied to floating point shapes. Default: 'ceil' kwargs : dict Passed through to the interpolator. See `menpo.interpolation` for details. Note that mode is set to nearest to avoid numerical issues, and cannot be changed here by the user. Returns ------- rescaled_image : type(self) A copy of this image, rescaled. Raises ------ ValueError: If less scales than dimensions are provided. If any scale is less than or equal to 0. """ # Pythonic way of converting to list if we are passed a single float try: if len(scale) < self.n_dims: raise ValueError( 'Must provide a scale per dimension.' '{} scales were provided, {} were expected.'.format( len(scale), self.n_dims ) ) except TypeError: # Thrown when len() is called on a float scale = [scale] * self.n_dims # Make sure we have a numpy array scale = np.asarray(scale) for s in scale: if s <= 0: raise ValueError('Scales must be positive floats.') transform = NonUniformScale(scale) from menpo.image.boolean import BooleanImage # use the scale factor to make the template mask bigger template_mask = BooleanImage.blank(transform.apply(self.shape), round=round) # due to image indexing, we can't just apply the pseduoinverse # transform to achieve the scaling we want though! # Consider a 3x rescale on a 2x4 image. Looking at each dimension: # H 2 -> 6 so [0-1] -> [0-5] = 5/1 = 5x # W 4 -> 12 [0-3] -> [0-11] = 11/3 = 3.67x # => need to make the correct scale per dimension! shape = np.array(self.shape, dtype=np.float) # scale factors = max_index_after / current_max_index # (note that max_index = length - 1, as 0 based) scale_factors = (scale * shape - 1) / (shape - 1) inverse_transform = NonUniformScale(scale_factors).pseudoinverse # for rescaling we enforce that mode is nearest to avoid num. errors if 'mode' in kwargs: raise ValueError("Cannot set 'mode' kwarg on rescale - set to " "'nearest' to avoid numerical errors") kwargs['mode'] = 'nearest' # Note here we pass warp_mask to warp_to. In the case of # Images that aren't MaskedImages this kwarg will # harmlessly fall through so we are fine. return self.warp_to(template_mask, inverse_transform, warp_landmarks=True, interpolator=interpolator, **kwargs)
def test_nonuniformscale_identity_2d(): assert_allclose(NonUniformScale.identity(2).h_matrix, np.eye(3))
def test_nonuniformscale_identity_3d(): assert_allclose(NonUniformScale.init_identity(3).h_matrix, np.eye(4))
def test_affine_pseudoinverse(): s = NonUniformScale([4, 3]) inv_man = NonUniformScale([1. / 4, 1. / 3]) b = Affine(s.h_matrix) i = b.pseudoinverse() assert_allclose(i.h_matrix, inv_man.h_matrix)
def test_nonuniformscale_from_list(): u_a = NonUniformScale([3, 2, 3]) u_b = NonUniformScale(np.array([3, 2, 3])) assert (np.all(u_a.h_matrix == u_b.h_matrix))
def test_nonuniformscale_2d_n_parameters(): scale = np.array([1, 2]) t = NonUniformScale(scale) assert (t.n_parameters == 2)
def test_nonuniformscale2d_as_vector(): scale = np.array([1, 2]) vec = NonUniformScale(scale).as_vector() assert_allclose(vec, scale)
def normalize(gt): from menpo.transform import Translation, NonUniformScale t = Translation(gt.centre()).pseudoinverse() s = NonUniformScale(gt.range()).pseudoinverse() return t.compose_before(s)