ocrd_cis/ocropy/common.py
def hmerge_line_seeds(binary, seeds, scale, threshold=0.8):
    """Relabel line seeds such that regions of coherent vertical
    intervals get the same label, and join them morphologically."""
    # merge labels horizontally to avoid splitting lines at long whitespace
    # (to prevent corners from becoming the largest label when spreading
    #  into the background; and make contiguous contours possible), but
    # ignore conflicts which affect only small fractions of either line
    # (avoiding merges for small vertical overlap):
    relabel = np.unique(seeds)
    labels = relabel[relabel > 0] # without background
    objects = [(0,0)] + measurements.find_objects(seeds)
    centers = [(0,0)] + measurements.center_of_mass(binary, seeds, labels)
    for label in labels:
        seed = seeds == label
        DSAVE('hmerge1_seed', seed)
        # close to fill holes from underestimated scale
        seed = morph.rb_closing(seed, (scale, scale))
        DSAVE('hmerge2_closed', seed)
        # open horizontally to remove extruding ascenders/descenders
        seed = morph.rb_opening(seed, (1, 3*scale))
        DSAVE('hmerge3_h-opened', seed)
        # close horizontally to overlap with possible neighbors
        seed = morph.rb_closing(seed, (1, 2*seeds.shape[1]))
        DSAVE('hmerge4_h-closed', seed)
        # get overlaps
        neighbors, counts = np.unique(seeds * seed, return_counts=True)
        for candidate, count in zip(neighbors, counts):
            if candidate in [0, label]:
                continue
            total = np.count_nonzero(seeds == candidate)
            if count < threshold * total:
                LOG.debug('ignoring h-overlap between %d and %d (only %d of %d)', label, candidate, count, total)
                continue
            label_center = centers[label]
            label_box = objects[label]
            candidate_center = centers[candidate]
            candidate_box = objects[candidate]
            if not (candidate_box[0].start < label_center[0] < candidate_box[0].stop):
                LOG.debug('ignoring h-overlap between %d and %d (y center not within other)', label, candidate)
                continue
            if not (label_box[0].start < candidate_center[0] < label_box[0].stop):
                LOG.debug('ignoring h-overlap between %d and %d (does not contain other y center)', label, candidate)
                continue
            if (candidate_box[1].start < label_center[1] < candidate_box[1].stop):
                LOG.debug('ignoring h-overlap between %d and %d (x center within other)', label, candidate)
                continue
            if (label_box[1].start < candidate_center[1] < label_box[1].stop):
                LOG.debug('ignoring h-overlap between %d and %d (contains other x center)', label, candidate)
                continue
            LOG.debug('hmerging %d with %d', candidate, label)
            # the new label could have been relabelled already:
            new_label = relabel[label]
            # assign candidate to (new assignment for) label:
            relabel[candidate] = new_label
            # re-assign labels already relabelled to candidate:
            relabel[relabel == candidate] = new_label
            # fill the horizontal background between both regions:
            candidate_y, candidate_x = np.where(seeds == candidate)
            new_label_y, new_label_x = np.where(seeds == new_label)
            for y in np.intersect1d(candidate_y, new_label_y):
                can_x_min = candidate_x[candidate_y == y][0]
                can_x_max = candidate_x[candidate_y == y][-1]
                new_x_min = new_label_x[new_label_y == y][0]
                new_x_max = new_label_x[new_label_y == y][-1]
                if can_x_max < new_x_min:
                    seeds[y, can_x_max:new_x_min] = new_label
                if new_x_max < can_x_min:
                    seeds[y, new_x_max:can_x_min] = new_label
    # apply re-assignments:
    seeds = relabel[seeds]
    DSAVE("hmerge5_connected", seeds)
    return seeds
Relabel line seeds such that regions of coherent vertical
    intervals get the same label, and join them morphologically.
Relabel line seeds such that regions of coherent vertical
intervals get the same label, and join them morphologically.
Relabel line seeds such that regions of coherent vertical intervals get the same label and join them morphologically .
def hmerge_line_seeds(binary, seeds, scale, threshold=0.8):
    relabel = np.unique(seeds)
    labels = relabel[relabel > 0] 
    objects = [(0,0)] + measurements.find_objects(seeds)
    centers = [(0,0)] + measurements.center_of_mass(binary, seeds, labels)
    for label in labels:
        seed = seeds == label
        DSAVE('hmerge1_seed', seed)
        seed = morph.rb_closing(seed, (scale, scale))
        DSAVE('hmerge2_closed', seed)
        seed = morph.rb_opening(seed, (1, 3*scale))
        DSAVE('hmerge3_h-opened', seed)
        seed = morph.rb_closing(seed, (1, 2*seeds.shape[1]))
        DSAVE('hmerge4_h-closed', seed)
        neighbors, counts = np.unique(seeds * seed, return_counts=True)
        for candidate, count in zip(neighbors, counts):
            if candidate in [0, label]:
                continue
            total = np.count_nonzero(seeds == candidate)
            if count < threshold * total:
                LOG.debug('ignoring h-overlap between %d and %d (only %d of %d)', label, candidate, count, total)
                continue
            label_center = centers[label]
            label_box = objects[label]
            candidate_center = centers[candidate]
            candidate_box = objects[candidate]
            if not (candidate_box[0].start < label_center[0] < candidate_box[0].stop):
                LOG.debug('ignoring h-overlap between %d and %d (y center not within other)', label, candidate)
                continue
            if not (label_box[0].start < candidate_center[0] < label_box[0].stop):
                LOG.debug('ignoring h-overlap between %d and %d (does not contain other y center)', label, candidate)
                continue
            if (candidate_box[1].start < label_center[1] < candidate_box[1].stop):
                LOG.debug('ignoring h-overlap between %d and %d (x center within other)', label, candidate)
                continue
            if (label_box[1].start < candidate_center[1] < label_box[1].stop):
                LOG.debug('ignoring h-overlap between %d and %d (contains other x center)', label, candidate)
                continue
            LOG.debug('hmerging %d with %d', candidate, label)
            new_label = relabel[label]
            relabel[candidate] = new_label
            relabel[relabel == candidate] = new_label
            candidate_y, candidate_x = np.where(seeds == candidate)
            new_label_y, new_label_x = np.where(seeds == new_label)
            for y in np.intersect1d(candidate_y, new_label_y):
                can_x_min = candidate_x[candidate_y == y][0]
                can_x_max = candidate_x[candidate_y == y][-1]
                new_x_min = new_label_x[new_label_y == y][0]
                new_x_max = new_label_x[new_label_y == y][-1]
                if can_x_max < new_x_min:
                    seeds[y, can_x_max:new_x_min] = new_label
                if new_x_max < can_x_min:
                    seeds[y, new_x_max:can_x_min] = new_label
    seeds = relabel[seeds]
    DSAVE("hmerge5_connected", seeds)
    return seeds
def hmerge_line_seeds ( binary , seeds , scale , threshold = 0.8 ) : relabel = np . unique ( seeds ) labels = relabel [ relabel > 0 ] objects = [ ( 0 , 0 ) ] + measurements . find_objects ( seeds ) centers = [ ( 0 , 0 ) ] + measurements . center_of_mass ( binary , seeds , labels ) for label in labels : seed = seeds == label DSAVE ( 'hmerge1_seed' , seed ) seed = morph . rb_closing ( seed , ( scale , scale ) ) DSAVE ( 'hmerge2_closed' , seed ) seed = morph . rb_opening ( seed , ( 1 , 3 * scale ) ) DSAVE ( 'hmerge3_h-opened' , seed ) seed = morph . rb_closing ( seed , ( 1 , 2 * seeds . shape [ 1 ] ) ) DSAVE ( 'hmerge4_h-closed' , seed ) neighbors , counts = np . unique ( seeds * seed , return_counts = True ) for candidate , count in zip ( neighbors , counts ) : if candidate in [ 0 , label ] : continue total = np . count_nonzero ( seeds == candidate ) if count < threshold * total : LOG . debug ( 'ignoring h-overlap between %d and %d (only %d of %d)' , label , candidate , count , total ) continue label_center = centers [ label ] label_box = objects [ label ] candidate_center = centers [ candidate ] candidate_box = objects [ candidate ] if not ( candidate_box [ 0 ] . start < label_center [ 0 ] < candidate_box [ 0 ] . stop ) : LOG . debug ( 'ignoring h-overlap between %d and %d (y center not within other)' , label , candidate ) continue if not ( label_box [ 0 ] . start < candidate_center [ 0 ] < label_box [ 0 ] . stop ) : LOG . debug ( 'ignoring h-overlap between %d and %d (does not contain other y center)' , label , candidate ) continue if ( candidate_box [ 1 ] . start < label_center [ 1 ] < candidate_box [ 1 ] . stop ) : LOG . debug ( 'ignoring h-overlap between %d and %d (x center within other)' , label , candidate ) continue if ( label_box [ 1 ] . start < candidate_center [ 1 ] < label_box [ 1 ] . stop ) : LOG . debug ( 'ignoring h-overlap between %d and %d (contains other x center)' , label , candidate ) continue LOG . debug ( 'hmerging %d with %d' , candidate , label ) new_label = relabel [ label ] relabel [ candidate ] = new_label relabel [ relabel == candidate ] = new_label candidate_y , candidate_x = np . where ( seeds == candidate ) new_label_y , new_label_x = np . where ( seeds == new_label ) for y in np . intersect1d ( candidate_y , new_label_y ) : can_x_min = candidate_x [ candidate_y == y ] [ 0 ] can_x_max = candidate_x [ candidate_y == y ] [ - 1 ] new_x_min = new_label_x [ new_label_y == y ] [ 0 ] new_x_max = new_label_x [ new_label_y == y ] [ - 1 ] if can_x_max < new_x_min : seeds [ y , can_x_max : new_x_min ] = new_label if new_x_max < can_x_min : seeds [ y , new_x_max : can_x_min ] = new_label seeds = relabel [ seeds ] DSAVE ( "hmerge5_connected" , seeds ) return seeds
Relabel line seeds such that regions of coherent vertical
intervals get the same label, and join them morphologically.
Relabel line seeds such that regions of coherent vertical intervals get the same label and join them morphologically .
"""Relabel line seeds such that regions of coherent vertical
    intervals get the same label, and join them morphologically.""" # merge labels horizontally to avoid splitting lines at long whitespace # (to prevent corners from becoming the largest label when spreading #  into the background; and make contiguous contours possible), but # ignore conflicts which affect only small fractions of either line # (avoiding merges for small vertical overlap): # without background # close to fill holes from underestimated scale # open horizontally to remove extruding ascenders/descenders # close horizontally to overlap with possible neighbors # get overlaps # the new label could have been relabelled already: # assign candidate to (new assignment for) label: # re-assign labels already relabelled to candidate: # fill the horizontal background between both regions: # apply re-assignments:
binary
seeds
scale
threshold