def detect(detector_callable, image, greyscale=True, image_diagonal=None, group_prefix="object", channels_at_back=True): r""" Apply the general detection framework. This involves converting the image to greyscale if necessary, rescaling the image to a given diagonal, performing the detection, and attaching the scaled landmarks back onto the original image. uint8 images cannot be converted to greyscale by this framework, so must already be greyscale or ``greyscale=False``. Parameters ---------- detector_callable : `callable` or `function` A callable object that will perform detection given a single parameter, a `uint8` numpy array with either no channels, or channels as the *last* axis. image : `menpo.image.Image` A Menpo image to detect. The bounding boxes of the detected objects will be attached to this image. greyscale : `bool`, optional Convert the image to greyscale or not. image_diagonal : `int`, optional The total size of the diagonal of the image that should be used for detection. This is useful for scaling images up and down for detection. group_prefix : `str`, optional The prefix string to be appended to each each landmark group that is stored on the image. Each detection will be stored as group_prefix_# where # is a count starting from 0. channels_at_back : `bool`, optional If ``True``, the image channels are placed onto the last axis (the back) as is common in many imaging packages. This is contrary to the Menpo default where channels are the first axis (at the front). Returns ------- bounding_boxes : `list` of `menpo.shape.PointDirectedGraph` A list of bounding boxes representing the detections found. """ d_image = image if greyscale: d_image = _greyscale(d_image) if image_diagonal is not None: scale_factor = image_diagonal / image.diagonal() d_image = d_image.rescale(scale_factor) pcs = detector_callable(menpo_image_to_uint8(d_image, channels_at_back=channels_at_back)) if image_diagonal is not None: s = UniformScale(1 / scale_factor, n_dims=2) pcs = [s.apply(pc) for pc in pcs] padding_magnitude = len(str(len(pcs))) for i, pc in enumerate(pcs): key = "{prefix}_{num:0{mag}d}".format(mag=padding_magnitude, prefix=group_prefix, num=i) image.landmarks[key] = pc return pcs
def test_uniformscale_2d_pseudoinverse(): scale = 0.5 h**o = np.array([[scale, 0, 0], [0, scale, 0], [0, 0, 1]]) tr = UniformScale(2, 2) assert_almost_equal(tr.pseudoinverse().h_matrix, h**o)
def test_align_2d_uniform_scale(): scale = UniformScale(2.5, 2) source = PointCloud(np.array([[0, 1], [1, 1], [-1, -5], [3, -5]])) target = scale.apply(source) # estimate the transform from source and target estimate = AlignmentUniformScale(source, target) # check the estimates is correct assert_allclose(scale.h_matrix, estimate.h_matrix)
def test_uniformscale2d_update_from_vector(): # make a uniform scale of 1, 2 dimensional uniform_scale = UniformScale(1, 2) new_scale = 2 h**o = np.array([[new_scale, 0, 0], [0, new_scale, 0], [0, 0, 1]]) uniform_scale._from_vector_inplace(new_scale) assert_equal(uniform_scale.h_matrix, h**o)
def test_align_2d_uniform_scale_set_h_matrix_raises_notimplemented_error(): scale = UniformScale(2.5, 2) source = PointCloud(np.array([[0, 1], [1, 1], [-1, -5], [3, -5]])) target = scale.apply(source) # estimate the transform from source and source estimate = AlignmentUniformScale(source, source) # and set the target estimate.set_h_matrix(scale.h_matrix)
def test_uniformscale3d_from_vector(): scale = 2 h**o = np.array([[scale, 0, 0, 0], [0, scale, 0, 0], [0, 0, scale, 0], [0, 0, 0, 1]]) uniform_scale = UniformScale(1, 3) tr = uniform_scale.from_vector(scale) assert_equal(tr.h_matrix, h**o)
def homog_compose_before_alignment_nonuniformscale_test(): homog = Homogeneous(np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1]])) scale = UniformScale(2.5, 2) source = PointCloud(np.array([[0, 1], [1, 1], [-1, -5], [3, -5]])) target = scale.apply(source) # estimate the transform from source and target s = AlignmentUniformScale(source, target) res = homog.compose_before(s) assert (type(res) == Homogeneous)
def test_homog_compose_before_alignment_nonuniformscale(): homog = Homogeneous(np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1]])) scale = UniformScale(2.5, 2) source = PointCloud(np.array([[0, 1], [1, 1], [-1, -5], [3, -5]])) target = scale.apply(source) # estimate the transform from source and target s = AlignmentUniformScale(source, target) res = homog.compose_before(s) assert(type(res) == Homogeneous)
def _recursive_procrustes(self): r""" Recursively calculates a procrustes alignment. """ from menpo.shape import mean_pointcloud from menpo.transform import Similarity if self.n_iterations > self.max_iterations: return False new_tgt = mean_pointcloud( [t.aligned_source.points for t in self.transforms]) # rescale the new_target to be the same size as the original about # it's centre rescale = Similarity.identity(new_tgt.n_dims) s = UniformScale(self.initial_target_scale / new_tgt.norm(), self.n_dims, skip_checks=True) t = Translation(-new_tgt.centre, skip_checks=True) rescale.compose_before_inplace(t) rescale.compose_before_inplace(s) rescale.compose_before_inplace(t.pseudoinverse) rescale.apply_inplace(new_tgt) # check to see if we have converged yet delta_target = np.linalg.norm(self.target.points - new_tgt.points) if delta_target < 1e-6: return True else: self.n_iterations += 1 for t in self.transforms: t.set_target(new_tgt) self.target = new_tgt return self._recursive_procrustes()
def _recursive_procrustes(self): """ Recursively calculates a Procrustes alignment """ if self.n_iterations > self.max_iterations: return False av_aligned_source = sum(t.aligned_source.points for t in self.transforms) / self.n_sources new_target = PointCloud(av_aligned_source) # rescale the new_target to be the same size as the original about # it's centre rescale = UniformScale(self.initial_target_scale / new_target.norm(), self.n_dims) centre = Translation(-new_target.centre) rescale_about_centre = centre.compose_before(rescale).compose_before( centre.pseudoinverse) rescale_about_centre.apply_inplace(new_target) # check to see if we have converged yet delta_target = np.linalg.norm(self.target.points - new_target.points) if delta_target < 1e-6: return True else: self.n_iterations += 1 for t in self.transforms: t.set_target(new_target) self.target = new_target return self._recursive_procrustes()
def test_uniformscale_build_2d(): scale = 2 h**o = np.array([[scale, 0, 0], [0, scale, 0], [0, 0, 1]]) tr = UniformScale(scale, 2) assert_equal(tr.h_matrix, h**o)
def detect(detector_callable, image, greyscale=True, image_diagonal=None, group_prefix='object'): r""" Apply the general detection framework. This involves converting the image to greyscale if necessary, rescaling the image to a given diagonal, performing the detection, and attaching the scaled landmarks back onto the original image. Parameters ---------- detector_callable : callable or function A callable object that will perform detection given a single parameter, a uint8 numpy array. image : menpo.image.Image A Menpo image to detect. The bounding boxes of the detected objects will be attached to this image. greyscale : bool, optional Convert the image to greyscale or not. image_diagonal : int, optional The total size of the diagonal of the image that should be used for detection. This is useful for scaling images up and down for detection. group_prefix : str, optional The prefix string to be appended to each each landmark group that is stored on the image. Each detection will be stored as group_prefix_# where # is a count starting from 0. Returns ------- bounding_boxes : menpo.shape.PointDirectedGraph A list of bounding boxes representing the detections found. """ d_image = image if greyscale: d_image = _greyscale(d_image) if image_diagonal is not None: scale_factor = image_diagonal / image.diagonal d_image = d_image.rescale(scale_factor) pcs = detector_callable(menpo_image_to_uint8(d_image)) if image_diagonal is not None: pcs = [ UniformScale(1 / scale_factor, n_dims=2).apply(pc) for pc in pcs ] padding_magnitude = len(str(len(pcs))) for i, pc in enumerate(pcs): key = '{prefix}_{num:0{mag}d}'.format(mag=padding_magnitude, prefix=group_prefix, num=i) image.landmarks[key] = pc return pcs
def test_uniformscale_build_3d(): scale = 2 h**o = np.array([[scale, 0, 0, 0], [0, scale, 0, 0], [0, 0, scale, 0], [0, 0, 0, 1]]) tr = UniformScale(scale, 3) assert (isinstance(tr, UniformScale)) assert_equal(tr.h_matrix, h**o)
def test_homog_compose_after_uniformscale(): homog = Homogeneous(np.array([[0, 1, 0], [1, 0, 0], [0, 0, 1]])) s = UniformScale(3, 2) res = homog.compose_after(s) assert(type(res) == Homogeneous) assert_allclose(res.h_matrix, np.array([[0, 3, 0], [3, 0, 0], [0, 0, 1]]))
def instance(self, model_type='bfm', alpha=None, beta=None, landmark_group='ibug68'): if alpha is None: alpha = np.zeros(len(self.shape_model.eigenvalues)) if beta is None: beta = np.zeros(len(self.texture_model.eigenvalues)) # Generate instance shape = self.shape_model.instance(alpha, normalized_weights=True) texture = self.texture_model.instance(beta, normalized_weights=True) if model_type == 'bfm': tex_scale = UniformScale(1. / 255, 3) lms_scale = UniformScale(1e-5, 3) texture = tex_scale.apply(texture.reshape([-1, 3])) landmarks = lms_scale.apply(self.landmarks) elif model_type == 'lsfm': pass trimesh = ColouredTriMesh(shape.points, trilist=shape.trilist, colours=texture) trimesh.landmarks[landmark_group] = landmarks return trimesh
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_transform_about_centre(method): 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 180 + scale degrees transformed_img = image.transform_about_centre(transform, mode="nearest", order=1) expected_pixels = np.concatenate( [np.linspace(15 - 2 * i, 12 - 2 * i, num=7)[None] for i in range(7)] ) assert transformed_img.shape == (7, 7) assert_allclose(transformed_img.pixels[0], expected_pixels, rtol=1e-8, atol=1e-8)
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 rescale(mesh, center, var): """ Rescale mesh according to given variances. Parameters: mesh (menpo.shape.mesh.base.TriMesh): mesh to be rescaled center (numpy.array of 3 floats): center on 3 dimensions var (numpy.array of 3 floats): variance on 3 dimensions Returns: mesh (menpo.shape.mesh.base.TriMesh): rescaled source """ tr = Translation(center) sc = UniformScale(np.mean(var / mesh.range()), 3) prepare = tr.compose_after(sc) return prepare.apply(mesh)
def test_uniformscale_set_h_matrix_raises_notimplementederror(): s = UniformScale(2, 3) s.set_h_matrix(s.h_matrix)
def test_uniformscale_identity_2d(): assert_allclose(UniformScale.identity(2).h_matrix, np.eye(3))
def test_uniformscale3d_n_parameters(): scale = 2 t = UniformScale(scale, 3) assert(t.n_parameters == 1)
def test_translation_compose_after_uniformscale(): t = Translation([3, 4]) s = UniformScale(2, 2) res = t.compose_after(s) assert(type(res) == Similarity)
def test_uniformscale_compose_after_translation(): t = Translation([3, 4]) s = UniformScale(2, 2) res = s.compose_after(t) assert(type(res) == Similarity)
def mesh_in_unit_sphere(mesh): scale = UniformScale(1 / mesh.norm(), mesh.n_dims) translation = Translation(-scale.apply(mesh).centre()) return translation.compose_after(scale)
def non_rigid_icp_generator( source, target, eps=1e-3, stiffness_weights=None, data_weights=None, landmark_group=None, landmark_weights=None, v_i_update_func=None, verbose=False, ): r""" Deforms the source trimesh to align with to optimally the target. """ # If landmarks are provided, we should always start with a simple # AlignmentSimilarity between the landmarks to initialize optimally. if landmark_group is not None: if verbose: print("'{}' landmarks will be used as " "a landmark constraint.".format(landmark_group)) print("performing similarity alignment using landmarks") lm_align = AlignmentSimilarity( source.landmarks[landmark_group], target.landmarks[landmark_group]).as_non_alignment() source = lm_align.apply(source) # Scale factors completely change the behavior of the algorithm - always # rescale the source down to a sensible size (so it fits inside box of # diagonal 1) and is centred on the origin. We'll undo this after the fit # so the user can use whatever scale they prefer. tr = Translation(-1 * source.centre()) sc = UniformScale(1.0 / np.sqrt(np.sum(source.range()**2)), 3) prepare = tr.compose_before(sc) source = prepare.apply(source) target = prepare.apply(target) # store how to undo the similarity transform restore = prepare.pseudoinverse() n_dims = source.n_dims # Homogeneous dimension (1 extra for translation effects) h_dims = n_dims + 1 points, trilist = source.points, source.trilist n = points.shape[0] # record number of points edge_tris = source.boundary_tri_index() M_s, unique_edge_pairs = node_arc_incidence_matrix(source) # weight matrix G = np.identity(n_dims + 1) M_kron_G_s = sp.kron(M_s, G) # build octree for finding closest points on target. target_vtk = trimesh_to_vtk(target) closest_points_on_target = VTKClosestPointLocator(target_vtk) # save out the target normals. We need them for the weight matrix. target_tri_normals = target.tri_normals() # init transformation X_prev = np.tile(np.zeros((n_dims, h_dims)), n).T v_i = points if stiffness_weights is not None: if verbose: print("using user-defined stiffness_weights") validate_weights("stiffness_weights", stiffness_weights, source.n_points, verbose=verbose) else: # these values have been empirically found to perform well for well # rigidly aligned facial meshes stiffness_weights = [50, 20, 5, 2, 0.8, 0.5, 0.35, 0.2] if verbose: print("using default " "stiffness_weights: {}".format(stiffness_weights)) n_iterations = len(stiffness_weights) if landmark_weights is not None: if verbose: print("using user defined " "landmark_weights: {}".format(landmark_weights)) elif landmark_group is not None: # these values have been empirically found to perform well for well # rigidly aligned facial meshes landmark_weights = [5, 2, 0.5, 0, 0, 0, 0, 0] if verbose: print("using default " "landmark_weights: {}".format(landmark_weights)) else: # no landmark_weights provided - no landmark_group in use. We still # need a landmark group for the iterator landmark_weights = [None] * n_iterations # We should definitely have some landmark weights set now - check the # number is correct. # Note we say verbose=False, as we have done custom reporting above, and # per-vertex landmarks are not supported. validate_weights( "landmark_weights", landmark_weights, source.n_points, n_iterations=n_iterations, verbose=False, ) if data_weights is not None: if verbose: print("using user-defined data_weights") validate_weights( "data_weights", data_weights, source.n_points, n_iterations=n_iterations, verbose=verbose, ) else: data_weights = [None] * n_iterations if verbose: print("Not customising data_weights") # we need to prepare some indices for efficient construction of the D # sparse matrix. row = np.hstack((np.repeat(np.arange(n)[:, None], n_dims, axis=1).ravel(), np.arange(n))) x = np.arange(n * h_dims).reshape((n, h_dims)) col = np.hstack((x[:, :n_dims].ravel(), x[:, n_dims])) o = np.ones(n) if landmark_group is not None: source_lm_index = source.distance_to( source.landmarks[landmark_group]).argmin(axis=0) target_lms = target.landmarks[landmark_group] U_L = target_lms.points n_landmarks = target_lms.n_points lm_mask = np.in1d(row, source_lm_index) col_lm = col[lm_mask] # pull out the rows for the lms - but the values are # all wrong! need to map them back to the order of the landmarks row_lm_to_fix = row[lm_mask] source_lm_index_l = list(source_lm_index) row_lm = np.array([source_lm_index_l.index(r) for r in row_lm_to_fix]) for i, (alpha, beta, gamma) in enumerate( zip(stiffness_weights, landmark_weights, data_weights), 1): alpha_is_per_vertex = isinstance(alpha, np.ndarray) if alpha_is_per_vertex: # stiffness is provided per-vertex if alpha.shape[0] != source.n_points: raise ValueError() alpha_per_edge = alpha[unique_edge_pairs].mean(axis=1) alpha_M_s = sp.diags(alpha_per_edge).dot(M_s) alpha_M_kron_G_s = sp.kron(alpha_M_s, G) else: # stiffness is global - just a scalar multiply. Note that here # we don't have to recalculate M_kron_G_s alpha_M_kron_G_s = alpha * M_kron_G_s if verbose: a_str = (alpha if not alpha_is_per_vertex else "min: {:.2f}, max: {:.2f}".format( alpha.min(), alpha.max())) i_str = "{}/{}: stiffness: {}".format(i, len(stiffness_weights), a_str) if landmark_group is not None: i_str += " lm_weight: {}".format(beta) print(i_str) j = 0 while True: # iterate until convergence j += 1 # track the iterations for this alpha/landmark weight # find nearest neighbour and the normals U, tri_indices = closest_points_on_target(v_i) # ---- WEIGHTS ---- # 1. Edges # Are any of the corresponding tris on the edge of the target? # Where they are we return a false weight (we *don't* want to # include these points in the solve) w_i_e = np.in1d(tri_indices, edge_tris, invert=True) # 2. Normals # Calculate the normals of the current v_i v_i_tm = TriMesh(v_i, trilist=trilist, copy=False) v_i_n = v_i_tm.vertex_normals() # Extract the corresponding normals from the target u_i_n = target_tri_normals[tri_indices] # If the dot of the normals is lt 0.9 don't contrib to deformation w_i_n = (u_i_n * v_i_n).sum(axis=1) > 0.9 # 3. Self-intersection # This adds approximately 12% to the running cost and doesn't seem # to be very critical in helping mesh fitting performance so for # now it's removed. Revisit later. # # Build an intersector for the current deformed target # intersect = build_intersector(to_vtk(v_i_tm)) # # budge the source points 1% closer to the target # source = v_i + ((U - v_i) * 0.5) # # if the vector from source to target intersects the deformed # # template we don't want to include it in the optimisation. # problematic = [i for i, (s, t) in enumerate(zip(source, U)) # if len(intersect(s, t)[0]) > 0] # print(len(problematic) * 1.0 / n) # w_i_i = np.ones(v_i_tm.n_points, dtype=np.bool) # w_i_i[problematic] = False # Form the overall w_i from the normals, edge case # for now disable the edge constraint (it was noisy anyway) w_i = w_i_n # w_i = np.logical_and(w_i_n, w_i_e).astype(np.float) # we could add self intersection at a later date too... # w_i = np.logical_and(np.logical_and(w_i_n, # w_i_e, # w_i_i).astype(np.float) prop_w_i = (n - w_i.sum() * 1.0) / n prop_w_i_n = (n - w_i_n.sum() * 1.0) / n prop_w_i_e = (n - w_i_e.sum() * 1.0) / n if gamma is not None: w_i = w_i * gamma # Build the sparse diagonal weight matrix W_s = sp.diags(w_i.astype(np.float)[None, :], [0]) data = np.hstack((v_i.ravel(), o)) D_s = sp.coo_matrix((data, (row, col))) to_stack_A = [alpha_M_kron_G_s, W_s.dot(D_s)] to_stack_B = [ np.zeros((alpha_M_kron_G_s.shape[0], n_dims)), U * w_i[:, None], ] # nullify nearest points by w_i if landmark_group is not None: D_L = sp.coo_matrix((data[lm_mask], (row_lm, col_lm)), shape=(n_landmarks, D_s.shape[1])) to_stack_A.append(beta * D_L) to_stack_B.append(beta * U_L) A_s = sp.vstack(to_stack_A).tocsr() B_s = sp.vstack(to_stack_B).tocsr() X = spsolve(A_s, B_s) # deform template v_i_prev = v_i v_i = D_s.dot(X) delta_v_i = v_i - v_i_prev if v_i_update_func: # custom logic is provided to update the current template # deformation. This is typically used by Active NICP. # take the v_i points matrix and convert back to a TriMesh in # the original space def_template = restore.apply(source.from_vector(v_i.ravel())) # perform the update updated_def_template = v_i_update_func(def_template) # convert back to points in the NICP space v_i = prepare.apply(updated_def_template.points) err = np.linalg.norm(X_prev - X, ord="fro") stop_criterion = err / np.sqrt(np.size(X_prev)) if landmark_group is not None: src_lms = v_i[source_lm_index] lm_err = np.sqrt((src_lms - U_L)**2).sum(axis=1).mean() if verbose: v_str = (" - {} stop crit: {:.3f} " "total: {:.0%} norms: {:.0%} " "edges: {:.0%}".format(j, stop_criterion, prop_w_i, prop_w_i_n, prop_w_i_e)) if landmark_group is not None: v_str += " lm_err: {:.4f}".format(lm_err) print(v_str) X_prev = X # track the progress of the algorithm per-iteration info_dict = { "alpha": alpha, "iteration": j, "prop_omitted": prop_w_i, "prop_omitted_norms": prop_w_i_n, "prop_omitted_edges": prop_w_i_e, "delta": err, "mask_normals": w_i_n, "mask_edges": w_i_e, "mask_all": w_i, "nearest_points": restore.apply(U), "deformation_per_step": delta_v_i, } current_instance = source.copy() current_instance.points = v_i.copy() if landmark_group: info_dict["beta"] = beta info_dict["lm_err"] = lm_err current_instance.landmarks[landmark_group] = PointCloud( src_lms) yield restore.apply(current_instance), info_dict if stop_criterion < eps: break
def test_uniformscale_build_4d_raise_dimensionalityerror(): UniformScale(1, 4)
def gaussian_pyramid(self, n_levels=3, downscale=2, sigma=None, order=1, mode='reflect', cval=0): r""" Return the gaussian pyramid of this image. The first image of the pyramid will be the original, unmodified, image. Parameters ---------- n_levels : int Number of levels in the pyramid. When set to -1 the maximum number of levels will be build. Default: 3 downscale : float, optional Downscale factor. Default: 2 sigma : float, optional Sigma for gaussian filter. Default is `2 * downscale / 6.0` which corresponds to a filter mask twice the size of the scale factor that covers more than 99% of the gaussian distribution. Default: None order : int, optional Order of splines used in interpolation of downsampling. See `scipy.ndimage.map_coordinates` for detail. Default: 1 mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional The mode parameter determines how the array borders are handled, where cval is the value when mode is equal to 'constant'. Default: 'reflect' cval : float, optional Value to fill past edges of input if mode is 'constant'. Default: 0 Returns ------- image_pyramid: Generator yielding pyramid layers as menpo image objects. """ max_layer = n_levels - 1 pyramid = pyramid_gaussian(self.pixels, max_layer=max_layer, downscale=downscale, sigma=sigma, order=order, mode=mode, cval=cval) for j, image_data in enumerate(pyramid): image = self.__class__(image_data) # rescale and reassign existent landmark image.landmarks = self.landmarks transform = UniformScale(downscale**j, self.n_dims) transform.pseudoinverse.apply_inplace(image.landmarks) yield image
def test_uniformscale3d_as_vector(): scale = 2 vec = UniformScale(scale, 3).as_vector() assert_allclose(vec, scale)
def test_uniformscale_identity_3d(): assert_allclose(UniformScale.init_identity(3).h_matrix, np.eye(4))
def test_uniformscale_build_4d_raise_dimensionalityerror(): with raises(ValueError): UniformScale(1, 4)
def test_warp_to_mask_preserves_path(): bb = menpo.io.import_builtin_asset.breakingbad_jpg() no_op = UniformScale(1.0, n_dims=2) bb2 = bb.warp_to_mask(BooleanImage.init_blank((10, 10)), no_op) assert hasattr(bb2, "path") assert bb2.path == bb.path
def render_patches( patches, patch_centers, patches_indices, offset_index, renderer, background, render_patches, channels, glyph_enabled, glyph_block_size, glyph_use_negative, sum_enabled, interpolation, cmap_name, alpha, render_patches_bboxes, bboxes_line_colour, bboxes_line_style, bboxes_line_width, render_centers, render_lines, line_colour, line_style, line_width, render_markers, marker_style, marker_size, marker_face_colour, marker_edge_colour, marker_edge_width, render_numbering, numbers_horizontal_align, numbers_vertical_align, numbers_font_name, numbers_font_size, numbers_font_style, numbers_font_weight, numbers_font_colour, render_axes, axes_font_name, axes_font_size, axes_font_style, axes_font_weight, axes_x_limits, axes_y_limits, axes_x_ticks, axes_y_ticks, figure_size): from menpo.transform import UniformScale from menpo.visualize import view_patches if glyph_enabled and render_patches: # compute glyph size glyph_patch0 = glyph(patches[0, offset_index, ...], vectors_block_size=glyph_block_size, use_negative=glyph_use_negative) # compute glyph of each patch glyph_patches = np.zeros( (patches.shape[0], 1, 1, glyph_patch0.shape[1], glyph_patch0.shape[2])) glyph_patches[0, 0, ...] = glyph_patch0 for i in range(1, patches.shape[0]): glyph_patches[i, 0, ...] = glyph(patches[i, offset_index, ...], vectors_block_size=glyph_block_size, use_negative=glyph_use_negative) # correct patch centers glyph_patch_centers = UniformScale(glyph_block_size, 2).apply(patch_centers) # visualize glyph patches renderer = view_patches( glyph_patches, glyph_patch_centers, patches_indices=patches_indices, offset_index=0, figure_id=renderer.figure_id, new_figure=False, background=background, render_patches=render_patches, channels=0, interpolation=interpolation, cmap_name=cmap_name, alpha=alpha, render_patches_bboxes=render_patches_bboxes, bboxes_line_colour=bboxes_line_colour, bboxes_line_style=bboxes_line_style, bboxes_line_width=bboxes_line_width, render_centers=render_centers, render_lines=render_lines, line_colour=line_colour, line_style=line_style, line_width=line_width, render_markers=render_markers, marker_style=marker_style, marker_size=marker_size, marker_face_colour=marker_face_colour, marker_edge_colour=marker_edge_colour, marker_edge_width=marker_edge_width, render_numbering=render_numbering, numbers_horizontal_align=numbers_horizontal_align, numbers_vertical_align=numbers_vertical_align, numbers_font_name=numbers_font_name, numbers_font_size=numbers_font_size, numbers_font_style=numbers_font_style, numbers_font_weight=numbers_font_weight, numbers_font_colour=numbers_font_colour, render_axes=render_axes, axes_font_name=axes_font_name, axes_font_size=axes_font_size, axes_font_style=axes_font_style, axes_font_weight=axes_font_weight, axes_x_limits=axes_x_limits, axes_y_limits=axes_y_limits, axes_x_ticks=axes_x_ticks, axes_y_ticks=axes_y_ticks, figure_size=figure_size) elif sum_enabled and render_patches: # compute sum of each patch sum_patches = np.zeros( (patches.shape[0], 1, 1, patches.shape[3], patches.shape[4])) for i in patches_indices: sum_patches[i, 0, ...] = sum_channels(patches[i, offset_index, ...], channels=channels) # visualize sum patches renderer = view_patches( sum_patches, patch_centers, patches_indices=patches_indices, offset_index=0, figure_id=renderer.figure_id, new_figure=False, background=background, render_patches=render_patches, channels=0, interpolation=interpolation, cmap_name=cmap_name, alpha=alpha, render_patches_bboxes=render_patches_bboxes, bboxes_line_colour=bboxes_line_colour, bboxes_line_style=bboxes_line_style, bboxes_line_width=bboxes_line_width, render_centers=render_centers, render_lines=render_lines, line_colour=line_colour, line_style=line_style, line_width=line_width, render_markers=render_markers, marker_style=marker_style, marker_size=marker_size, marker_face_colour=marker_face_colour, marker_edge_colour=marker_edge_colour, marker_edge_width=marker_edge_width, render_numbering=render_numbering, numbers_horizontal_align=numbers_horizontal_align, numbers_vertical_align=numbers_vertical_align, numbers_font_name=numbers_font_name, numbers_font_size=numbers_font_size, numbers_font_style=numbers_font_style, numbers_font_weight=numbers_font_weight, numbers_font_colour=numbers_font_colour, render_axes=render_axes, axes_font_name=axes_font_name, axes_font_size=axes_font_size, axes_font_style=axes_font_style, axes_font_weight=axes_font_weight, axes_x_limits=axes_x_limits, axes_y_limits=axes_y_limits, axes_x_ticks=axes_x_ticks, axes_y_ticks=axes_y_ticks, figure_size=figure_size) else: renderer = view_patches( patches, patch_centers, patches_indices=patches_indices, offset_index=offset_index, figure_id=renderer.figure_id, new_figure=False, background=background, render_patches=render_patches, channels=channels, interpolation=interpolation, cmap_name=cmap_name, alpha=alpha, render_patches_bboxes=render_patches_bboxes, bboxes_line_colour=bboxes_line_colour, bboxes_line_style=bboxes_line_style, bboxes_line_width=bboxes_line_width, render_centers=render_centers, render_lines=render_lines, line_colour=line_colour, line_style=line_style, line_width=line_width, render_markers=render_markers, marker_style=marker_style, marker_size=marker_size, marker_face_colour=marker_face_colour, marker_edge_colour=marker_edge_colour, marker_edge_width=marker_edge_width, render_numbering=render_numbering, numbers_horizontal_align=numbers_horizontal_align, numbers_vertical_align=numbers_vertical_align, numbers_font_name=numbers_font_name, numbers_font_size=numbers_font_size, numbers_font_style=numbers_font_style, numbers_font_weight=numbers_font_weight, numbers_font_colour=numbers_font_colour, render_axes=render_axes, axes_font_name=axes_font_name, axes_font_size=axes_font_size, axes_font_style=axes_font_style, axes_font_weight=axes_font_weight, axes_x_limits=axes_x_limits, axes_y_limits=axes_y_limits, axes_x_ticks=axes_x_ticks, axes_y_ticks=axes_y_ticks, figure_size=figure_size) # show plot plt.show() return renderer