ocrd_cis/ocropy/resegment.py
def resegment(line_polygon, region_labels, region_bin, line_id,
              extend_margins=3,
              threshold_relative=0.8, threshold_absolute=50):
    """Reduce line polygon in a labelled region to the largest intersection.

    Given a Numpy array ``line_polygon`` of relative coordinates
    in a region given by a Numpy array ``region_labels`` of numbered
    segments and a Numpy array ``region_bin`` of foreground pixels,
    find the label of the largest segment that intersects the polygon.
    If the number of foreground pixels within that segment is larger
    than ``threshold_absolute`` and if the share of foreground pixels
    within the whole polygon is larger than ``threshold_relative``,
    then compute the contour of that intersection and return it
    as a new polygon. Otherwise, return None.

    If ``extend_margins`` is larger than zero, then extend ``line_polygon``
    by that amount of pixels horizontally and vertically before.
    """
    LOG = getLogger('processor.OcropyResegment')
    # height, width = region_labels.shape
    # mask from line polygon:
    line_mask = np.zeros_like(region_labels)
    line_mask[draw.polygon(line_polygon[:,1], line_polygon[:,0], line_mask.shape)] = 1
    line_mask[draw.polygon_perimeter(line_polygon[:,1], line_polygon[:,0], line_mask.shape)] = 1
    #DSAVE('line %s mask' % line_id, line_mask + 0.5 * region_bin)
    # pad line polygon (extend the mask):
    line_mask = filters.maximum_filter(line_mask, 1 + 2 * extend_margins)
    # intersect with region labels
    line_labels = region_labels * line_mask
    if not np.count_nonzero(line_labels):
        LOG.warning('Label mask is empty for line "%s"', line_id)
        return None
    # find the mask of the largest label (in the foreground):
    total_count = np.sum(region_bin * line_mask)
    line_labels_fg = region_bin * line_labels
    if not np.count_nonzero(line_labels_fg):
        LOG.warning('No foreground pixels within line mask for line "%s"', line_id)
        return None
    label_counts = np.bincount(line_labels_fg.flat)
    max_label = np.argmax(label_counts[1:]) + 1
    max_count = label_counts[max_label]
    if (max_count < threshold_absolute and
        max_count / total_count < threshold_relative):
        LOG.info('Largest label (%d) is too small (%d/%d) in line "%s"',
                 max_label, max_count, total_count, line_id)
        return None
    LOG.debug('Black pixels before/after resegment of line "%s" (nlabels=%d): %d/%d',
              line_id, len(label_counts.nonzero()[0]), total_count, max_count)
    line_mask = np.array(line_labels == max_label, np.uint8)
    #DSAVE('line %s mask tight' % line_id, line_mask + 0.5 * region_bin)
    # find outer contour (parts):
    contours, _ = cv2.findContours(line_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # determine largest part by area:
    contour_areas = [cv2.contourArea(contour) for contour in contours]
    max_contour = np.argmax(contour_areas)
    max_area = contour_areas[max_contour]
    total_area = cv2.contourArea(np.expand_dims(line_polygon, 1))
    if max_area / total_area < 0.5 * threshold_relative:
        # using a different, more conservative threshold here:
        # avoid being overly strict with cropping background,
        # just ensure the contours are not a split of the mask
        LOG.warning('Largest label (%d) largest contour (%d) is small (%d/%d) in line "%s"',
                    max_label, max_contour, max_area, total_area, line_id)
    contour = contours[max_contour]
    # simplify shape:
    # can produce invalid (self-intersecting) polygons:
    #polygon = cv2.approxPolyDP(contour, 2, False)[:, 0, ::] # already ordered x,y
    polygon = contour[:, 0, ::] # already ordered x,y
    polygon = Polygon(polygon).simplify(2).exterior.coords[:-1] # keep open
    if len(polygon) < 4:
        LOG.warning('found no contour of >=4 points for line "%s"', line_id)
        return None
    return polygon
Reduce line polygon in a labelled region to the largest intersection.

    Given a Numpy array ``line_polygon`` of relative coordinates
    in a region given by a Numpy array ``region_labels`` of numbered
    segments and a Numpy array ``region_bin`` of foreground pixels,
    find the label of the largest segment that intersects the polygon.
    If the number of foreground pixels within that segment is larger
    than ``threshold_absolute`` and if the share of foreground pixels
    within the whole polygon is larger than ``threshold_relative``,
    then compute the contour of that intersection and return it
    as a new polygon. Otherwise, return None.

    If ``extend_margins`` is larger than zero, then extend ``line_polygon``
    by that amount of pixels horizontally and vertically before.
    
Reduce line polygon in a labelled region to the largest intersection.


Reduce line polygon in a labelled region to the largest intersection .
def resegment(line_polygon, region_labels, region_bin, line_id,
              extend_margins=3,
              threshold_relative=0.8, threshold_absolute=50):
    LOG = getLogger('processor.OcropyResegment')
    line_mask = np.zeros_like(region_labels)
    line_mask[draw.polygon(line_polygon[:,1], line_polygon[:,0], line_mask.shape)] = 1
    line_mask[draw.polygon_perimeter(line_polygon[:,1], line_polygon[:,0], line_mask.shape)] = 1
    line_mask = filters.maximum_filter(line_mask, 1 + 2 * extend_margins)
    line_labels = region_labels * line_mask
    if not np.count_nonzero(line_labels):
        LOG.warning('Label mask is empty for line "%s"', line_id)
        return None
    total_count = np.sum(region_bin * line_mask)
    line_labels_fg = region_bin * line_labels
    if not np.count_nonzero(line_labels_fg):
        LOG.warning('No foreground pixels within line mask for line "%s"', line_id)
        return None
    label_counts = np.bincount(line_labels_fg.flat)
    max_label = np.argmax(label_counts[1:]) + 1
    max_count = label_counts[max_label]
    if (max_count < threshold_absolute and
        max_count / total_count < threshold_relative):
        LOG.info('Largest label (%d) is too small (%d/%d) in line "%s"',
                 max_label, max_count, total_count, line_id)
        return None
    LOG.debug('Black pixels before/after resegment of line "%s" (nlabels=%d): %d/%d',
              line_id, len(label_counts.nonzero()[0]), total_count, max_count)
    line_mask = np.array(line_labels == max_label, np.uint8)
    contours, _ = cv2.findContours(line_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contour_areas = [cv2.contourArea(contour) for contour in contours]
    max_contour = np.argmax(contour_areas)
    max_area = contour_areas[max_contour]
    total_area = cv2.contourArea(np.expand_dims(line_polygon, 1))
    if max_area / total_area < 0.5 * threshold_relative:
        LOG.warning('Largest label (%d) largest contour (%d) is small (%d/%d) in line "%s"',
                    max_label, max_contour, max_area, total_area, line_id)
    contour = contours[max_contour]
    polygon = contour[:, 0, ::] 
    polygon = Polygon(polygon).simplify(2).exterior.coords[:-1] 
    if len(polygon) < 4:
        LOG.warning('found no contour of >=4 points for line "%s"', line_id)
        return None
    return polygon
def resegment ( line_polygon , region_labels , region_bin , line_id , extend_margins = 3 , threshold_relative = 0.8 , threshold_absolute = 50 ) : LOG = getLogger ( 'processor.OcropyResegment' ) line_mask = np . zeros_like ( region_labels ) line_mask [ draw . polygon ( line_polygon [ : , 1 ] , line_polygon [ : , 0 ] , line_mask . shape ) ] = 1 line_mask [ draw . polygon_perimeter ( line_polygon [ : , 1 ] , line_polygon [ : , 0 ] , line_mask . shape ) ] = 1 line_mask = filters . maximum_filter ( line_mask , 1 + 2 * extend_margins ) line_labels = region_labels * line_mask if not np . count_nonzero ( line_labels ) : LOG . warning ( 'Label mask is empty for line "%s"' , line_id ) return None total_count = np . sum ( region_bin * line_mask ) line_labels_fg = region_bin * line_labels if not np . count_nonzero ( line_labels_fg ) : LOG . warning ( 'No foreground pixels within line mask for line "%s"' , line_id ) return None label_counts = np . bincount ( line_labels_fg . flat ) max_label = np . argmax ( label_counts [ 1 : ] ) + 1 max_count = label_counts [ max_label ] if ( max_count < threshold_absolute and max_count / total_count < threshold_relative ) : LOG . info ( 'Largest label (%d) is too small (%d/%d) in line "%s"' , max_label , max_count , total_count , line_id ) return None LOG . debug ( 'Black pixels before/after resegment of line "%s" (nlabels=%d): %d/%d' , line_id , len ( label_counts . nonzero ( ) [ 0 ] ) , total_count , max_count ) line_mask = np . array ( line_labels == max_label , np . uint8 ) contours , _ = cv2 . findContours ( line_mask , cv2 . RETR_EXTERNAL , cv2 . CHAIN_APPROX_SIMPLE ) contour_areas = [ cv2 . contourArea ( contour ) for contour in contours ] max_contour = np . argmax ( contour_areas ) max_area = contour_areas [ max_contour ] total_area = cv2 . contourArea ( np . expand_dims ( line_polygon , 1 ) ) if max_area / total_area < 0.5 * threshold_relative : LOG . warning ( 'Largest label (%d) largest contour (%d) is small (%d/%d) in line "%s"' , max_label , max_contour , max_area , total_area , line_id ) contour = contours [ max_contour ] polygon = contour [ : , 0 , : : ] polygon = Polygon ( polygon ) . simplify ( 2 ) . exterior . coords [ : - 1 ] if len ( polygon ) < 4 : LOG . warning ( 'found no contour of >=4 points for line "%s"' , line_id ) return None return polygon
Reduce line polygon in a labelled region to the largest intersection.
Reduce line polygon in a labelled region to the largest intersection .
"""Reduce line polygon in a labelled region to the largest intersection.

    Given a Numpy array ``line_polygon`` of relative coordinates
    in a region given by a Numpy array ``region_labels`` of numbered
    segments and a Numpy array ``region_bin`` of foreground pixels,
    find the label of the largest segment that intersects the polygon.
    If the number of foreground pixels within that segment is larger
    than ``threshold_absolute`` and if the share of foreground pixels
    within the whole polygon is larger than ``threshold_relative``,
    then compute the contour of that intersection and return it
    as a new polygon. Otherwise, return None.

    If ``extend_margins`` is larger than zero, then extend ``line_polygon``
    by that amount of pixels horizontally and vertically before.
    """ # height, width = region_labels.shape # mask from line polygon: #DSAVE('line %s mask' % line_id, line_mask + 0.5 * region_bin) # pad line polygon (extend the mask): # intersect with region labels # find the mask of the largest label (in the foreground): #DSAVE('line %s mask tight' % line_id, line_mask + 0.5 * region_bin) # find outer contour (parts): # determine largest part by area: # using a different, more conservative threshold here: # avoid being overly strict with cropping background, # just ensure the contours are not a split of the mask # simplify shape: # can produce invalid (self-intersecting) polygons: #polygon = cv2.approxPolyDP(contour, 2, False)[:, 0, ::] # already ordered x,y # already ordered x,y # keep open
line_polygon
region_labels
region_bin
line_id
extend_margins
threshold_relative
threshold_absolute