def __call__(lineccs): # utilities for Gamera's graph API from gamera import graph from gamera import graph_util class SegForGraph: def __init__(self, seg): self.segment = seg self.label = 0 # # build directed graph of all lines # G = graph.Graph(graph.FLAG_DAG) seg_data = [SegForGraph(s) for s in lineccs] # sort by y-position for row over column preference in ambiguities seg_data.sort(lambda s, t: s.segment.offset_y - t.segment.offset_y) G.add_nodes(seg_data) for s in seg_data: for t in seg_data: if s.segment.offset_x <= t.segment.offset_x + t.segment.ncols and \ s.segment.offset_x + s.segment.ncols >= t.segment.offset_x: if s.segment.offset_y < t.segment.offset_y: G.add_edge(s, t) elif s.segment.offset_x < t.segment.offset_x: G.add_edge(s, t) # # compute topoligical sorting by depth-first-search # segs_sorted = [] # topologically sorted list def dfs_visit(node): node.data.label = 1 for nextnode in node.nodes: if nextnode.data.label == 0: dfs_visit(nextnode) segs_sorted.append(node.data.segment) for node in G.get_nodes(): if node.data.label == 0: dfs_visit(node) segs_sorted.reverse() # correct that we always appended to the back return segs_sorted
def merge_boxes(bboxes): from gamera import graph bboxes.sort(lambda b1, b2: b1.rect.ul_y - b2.rect.ul_y) g = graph.Graph(graph.UNDIRECTED) # build graph where edge means overlap of two boxes for i in range(len(bboxes)): g.add_node(i) for i in range(len(bboxes)): for j in range(i + 1, len(bboxes)): if bboxes[j].rect.ul_y > bboxes[i].rect.lr_y: break if bboxes[i].rect.intersects(bboxes[j].rect): if not g.has_edge(i, j): g.add_edge(i, j) new_bboxes = [] for sg in g.get_subgraph_roots(): seg = [n() for n in g.BFS(sg)] bbox = bboxes[seg[0]] for i in range(1, len(seg)): bbox.merge(bboxes[seg[i]]) new_bboxes.append(bbox) return new_bboxes
def __call__(self, Ta=40.0, fr=0.34): # compute neighborship graph from gamera.plugins.geometry import delaunay_from_points ccs = self.cc_analysis() i = 0 points = [] labels = [] labels2ccs = {} for cc in ccs: p = cc.contour_samplepoints(15, 1) cc.points = p points += p labels += [cc.label] * len(p) labels2ccs[cc.label] = cc neighbors = delaunay_from_points(points, range(len(points))) # compute edge properties class Edge(object): def __init__(self, cc1, cc2, d2): self.cc1 = cc1 self.cc2 = cc2 self.d = d2 a = [cc1.black_area()[0], cc2.black_area()[0]] self.ar = max(a) / min(a) labelneighbors = {} for pair in neighbors: if (labels[pair[0]] < labels[pair[1]]): label1 = labels[pair[0]] label2 = labels[pair[1]] else: label1 = labels[pair[1]] label2 = labels[pair[0]] if label1 == label2: continue p1 = points[pair[0]] p2 = points[pair[1]] d2 = (p1.x - p2.x)**2 + (p1.y - p2.y)**2 key = "%i;%i" % (label1, label2) if not labelneighbors.has_key(key): labelneighbors[key] = Edge(labels2ccs[label1], labels2ccs[label2], d2) else: e = labelneighbors[key] if e.d > d2: e.d = d2 for e in labelneighbors.itervalues(): e.d = sqrt(e.d) # determine thresholds Td1 and Td2 from distance statistics distances = [e.d for e in labelneighbors.itervalues()] distances.sort() if len(distances) > 50: distances = distances[len(distances) / 20:(len(distances) - len(distances) / 20)] x = [float(i * max(distances)) / 512.0 for i in range(512)] density = kernel_density(distances, x, kernel=2) local_maxima_i = [] local_maxima_d = [] for i in range(1, len(density) - 1): if density[i] > density[i - 1] and density[i] > density[i + 1]: local_maxima_i.append(i) local_maxima_d.append(density[i]) m1 = argmax(local_maxima_d) i1 = local_maxima_i[m1] local_maxima_i = [ local_maxima_i[i] for i in range(len(local_maxima_i)) if i != m1 ] local_maxima_d = [ local_maxima_d[i] for i in range(len(local_maxima_d)) if i != m1 ] i2 = local_maxima_i[argmax(local_maxima_d)] if i2 < i1: tmp = i2 i2 = i1 i1 = tmp dmax = density[i2] i2 += 1 while i2 < len(x) - 1: if density[i2] < fr * dmax: break i2 += 1 Td1 = x[i1] Td2 = x[i2] #print "Td1 =", Td1, "Td2 =", Td2, "(plugin)" # build graph from gamera import graph g = graph.Graph(graph.UNDIRECTED) rgb = self.to_rgb() for e in labelneighbors.itervalues(): if not g.has_node(e.cc1.label): g.add_node(e.cc1.label) if not g.has_node(e.cc2.label): g.add_node(e.cc2.label) if (e.d / Td1 <= 1.0) or (e.d / Td2 + e.ar / Ta <= 1): g.add_edge(e.cc1.label, e.cc2.label) else: pass # split graph into connected subgraphs from gamera.core import MlCc seglabels = [] for i, sg in enumerate(g.get_subgraph_roots()): seg = [n() for n in g.BFS(sg)] seglabels.append(seg) segments = [] for lbs in seglabels: mlcc = MlCc([labels2ccs[lb] for lb in lbs]) segments.append(mlcc.convert_to_cc()) return segments