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_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.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.affine 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_identity_3d(): assert_allclose(NonUniformScale.identity(3).h_matrix, np.eye(4))
def rescale(self, scale, interpolator='scipy', round='ceil', **kwargs): r""" Return a copy of this image, rescaled by a given factor. All image information (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' or 'c', 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. 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 # 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)