def compute_table_coordinates(self, xthresh=8., ythresh=8.): """ Sorts all clusters into spreadsheet-like x/y coordinates. Set self.cell_table_coord of shape (0, n) """ center_x = self.cell_centers[:, 0] center_y = self.cell_centers[:, 1] # Compute adjacency list hgroup_adjlist, vgroup_adjlist = {}, {} for i in range(center_x.shape[0]): hgroup_adjlist[i] = np.nonzero( np.abs(center_x - center_x[i]) < xthresh)[0] vgroup_adjlist[i] = np.nonzero( np.abs(center_y - center_y[i]) < ythresh)[0] # Compute transitive closures so we get ALL grouped cells for each group, # not just the ones that are similar to the first node. hgroups, hgroup_lut = transitive_closure(hgroup_adjlist) vgroups, vgroup_lut = transitive_closure(vgroup_adjlist) #### # Reorder groups by x/y #### # Compute mean X/Y coords for each hgroup/vgroup hgroup_mean_centers = np.zeros(len(hgroups)) vgroup_mean_centers = np.zeros(len(vgroups)) for i, st in enumerate(hgroups): hgroup_mean_centers[i] = np.mean(self.cell_centers[list(st)][:, 0]) for i, st in enumerate(vgroups): vgroup_mean_centers[i] = np.mean(self.cell_centers[list(st)][:, 1]) # Find the sorted ordering (like in a spreadsheet) for both x and y coords hgroup_sort_order = np.argsort(hgroup_mean_centers) vgroup_sort_order = np.argsort(vgroup_mean_centers) # Output of argsort: Input => new index ; output => old index # BUT WE NEED: Input oldplace, output newplace hgroup_sort_order = invert_bijection(hgroup_sort_order) vgroup_sort_order = invert_bijection(vgroup_sort_order) # Reorder everything based on the new order hgroups = multiselect(hgroups, hgroup_sort_order) vgroups = multiselect(vgroups, vgroup_sort_order) # Convert LUTs hgroup_lut = hgroup_sort_order[hgroup_lut] vgroup_lut = vgroup_sort_order[vgroup_lut] # Build a (n, (tx,ty)) table coordinate LUT for all nodes self.cell_table_coord = np.dstack([hgroup_lut, vgroup_lut])[0] # Build index of table coordinates to node ID self.table_coords_to_node = {} for i, (x, y) in enumerate(self.cell_table_coord): self.table_coords_to_node[(x, y)] = i
def compute_table_coordinates(self, xthresh=8., ythresh=8.): """ Sorts all clusters into spreadsheet-like x/y coordinates. Set self.cell_table_coord of shape (0, n) """ center_x = self.cell_centers[:, 0] center_y = self.cell_centers[:, 1] # Compute adjacency list hgroup_adjlist, vgroup_adjlist = {}, {} for i in range(center_x.shape[0]): hgroup_adjlist[i] = np.nonzero(np.abs(center_x - center_x[i]) < xthresh)[0] vgroup_adjlist[i] = np.nonzero(np.abs(center_y - center_y[i]) < ythresh)[0] # Compute transitive closures so we get ALL grouped cells for each group, # not just the ones that are similar to the first node. hgroups, hgroup_lut = transitive_closure(hgroup_adjlist) vgroups, vgroup_lut = transitive_closure(vgroup_adjlist) #### # Reorder groups by x/y #### # Compute mean X/Y coords for each hgroup/vgroup hgroup_mean_centers = np.zeros(len(hgroups)) vgroup_mean_centers = np.zeros(len(vgroups)) for i, st in enumerate(hgroups): hgroup_mean_centers[i] = np.mean(self.cell_centers[list(st)][:, 0]) for i, st in enumerate(vgroups): vgroup_mean_centers[i] = np.mean(self.cell_centers[list(st)][:, 1]) # Find the sorted ordering (like in a spreadsheet) for both x and y coords hgroup_sort_order = np.argsort(hgroup_mean_centers) vgroup_sort_order = np.argsort(vgroup_mean_centers) # Output of argsort: Input => new index ; output => old index # BUT WE NEED: Input oldplace, output newplace hgroup_sort_order = invert_bijection(hgroup_sort_order) vgroup_sort_order = invert_bijection(vgroup_sort_order) # Reorder everything based on the new order hgroups = multiselect(hgroups, hgroup_sort_order) vgroups = multiselect(vgroups, vgroup_sort_order) # Convert LUTs hgroup_lut = hgroup_sort_order[hgroup_lut] vgroup_lut = vgroup_sort_order[vgroup_lut] # Build a (n, (tx,ty)) table coordinate LUT for all nodes self.cell_table_coord = np.dstack([hgroup_lut, vgroup_lut])[0] # Build index of table coordinates to node ID self.table_coords_to_node = {} for i, (x, y) in enumerate(self.cell_table_coord): self.table_coords_to_node[(x, y)] = i
def compute_cell_polygons(self): """ Compute a list of cell polygons from the contours and the associated corner clusters. Generates a list of cells, with a cell being a list of cluster IDs. This list is stored in self.cell_polygons """ cell_polygons = [] for i in range(len(self.contours)): # Skip invalidated contours if self.contours[i] is None: continue bbox = self.contours_bbox[i] # Guaranteed to have 4 nodes by design (it's a bounding box)! # bbox == corner1, ..., corner4 bclust = multiselect(self.cluster_coords_to_node_id, bbox, convert=tuple) cell_polygons.append(bclust) self.cell_polygons = cell_polygons
def filter_shapes_by_total_area_threshold(points, pivots, threshold=.005): """ Split a given point list by a pivot list to obtain a list of polygons. then filter out polygons that have less than the given fraction of the total area. """ parts = list(split_by_pivot(points, pivots)) partareas = np.zeros(len(parts)) # Compute all part areas for i, part in enumerate(parts): partareas[i] = polygon_area(part) total_area = np.sum(partareas) # Find areas below the threshold idxs = np.where(partareas > threshold * total_area)[0] # Select from parts list return multiselect(parts, idxs)