Ejemplo n.º 1
0
def strip_projections(image, num_strips=30):

    newimg = image.image_copy()

    bottom_contour = image.contour_bottom()
    left_side = min([
        i for i in range(len(bottom_contour) - 1)
        if bottom_contour[i + 1] != np.inf and bottom_contour[i] == np.inf
    ])
    right_side = max([
        i for i in range(len(bottom_contour) - 1)
        if bottom_contour[i + 1] == np.inf and bottom_contour[i] != np.inf
    ])

    vert_strips = []
    strip_dim = gc.Dim(1 + (right_side - left_side) // num_strips,
                       image.height)
    for i in range(num_strips):
        ul = gc.Point(left_side + strip_dim.ncols * i, 0)
        subimg = image.subimage(ul, strip_dim)
        vert_strips.append(subimg)

    strip_centers = [
        int((x + 0.5) * strip_dim.ncols + left_side) for x in range(num_strips)
    ]
    strip_projections = [x.projection_rows() for x in vert_strips]
    strip_proj_smooth = [moving_avg_filter(x) for x in strip_projections]
    strip_log = [np.log(x / (max(x) + 1) + 1) for x in strip_proj_smooth]
    anchor_points = []
    # find runs of consecutive zeroes and take points in middle of these runs: anchors
    for s in strip_log:
        iszero = np.concatenate(([0], np.less(s, 0.2).view(np.int8), [0]))
        absdiff = np.abs(np.diff(iszero))
        ranges = np.where(absdiff == 1)[0].reshape(-1, 2)
        anchors = [int((x[0] + x[1]) / 2) for x in ranges]
        anchor_points.append(anchors)

    for i, x in enumerate(strip_centers):
        for y in anchor_points[i]:
            newimg.draw_marker(gc.Point(x, y), 10, 3, 1)

    newimg.to_rgb().to_pil().save('aaaaaaa.png')
Ejemplo n.º 2
0
 def display_lines(self, clear=1):
     """Display the lines found by placing a box around them
     in a display. If clear is true then any boxes already on
     the displayed are cleared first."""
     if self.image._display is None:
         self.image.display()
     display = self.image._display
     if clear:
         display.clear_all_boxes()
     for s in self.sections:
         for line in s.lines:
             b = line.bbox
             display.add_box(
                 core.Rect(core.Point(b.ul_x, b.ul_y),
                           core.Dim(b.ncols, b.nrows)))
Ejemplo n.º 3
0
    def display_sections(self, clear=1):
        """Display the sections found by placing a box around them
        in a display. If clear is true then any boxes already on
        the displayed are cleared first."""
        # display the sections
        result = self.sections

        if self.image._display is None:
            self.image.display()
        display = self.image._display
        if clear:
            display.clear_all_boxes()
        for rect in result:
            b = rect.bbox
            display.add_box(
                core.Rect(core.Point(b.ul_x, b.ul_y),
                          core.Dim(b.ncols, b.nrows)))
Ejemplo n.º 4
0
def rotate_bbox(cbox, angle, orig_dim, target_dim, radians=False):
    pivot = gc.Point(orig_dim.ncols / 2, orig_dim.nrows / 2)

    # amount to translate to compensate for padding added by gamera's rotation in preprocessing.
    # i am pretty sure this is the most "correct" amount. my math might be off.
    dx = (orig_dim.ncols - target_dim.ncols) / 2
    dy = (orig_dim.nrows - target_dim.nrows) / 2

    if not radians:
        angle = angle * np.pi / 180

    s = np.sin(angle)
    c = np.cos(angle)

    # move to origin
    old_ulx = cbox.ulx - pivot.x
    old_uly = cbox.uly - pivot.y
    old_lrx = cbox.lrx - pivot.x
    old_lry = cbox.lry - pivot.y

    # rotate using a 2d rotation matrix
    new_ulx = (old_ulx * c) - (old_uly * s)
    new_uly = (old_ulx * s) + (old_uly * c)
    new_lrx = (old_lrx * c) - (old_lry * s)
    new_lry = (old_lrx * s) + (old_lry * c)

    # move back to original position adjusted for padding
    new_ulx += (pivot.x - dx)
    new_uly += (pivot.y - dy)
    new_lrx += (pivot.x - dx)
    new_lry += (pivot.y - dy)

    new_ul = np.round([new_ulx, new_uly]).astype('int16')
    new_lr = np.round([new_lrx, new_lry]).astype('int16')

    return CharBox(cbox.char, new_ul, new_lr)
Ejemplo n.º 5
0
 def __init__(self, glyph):
     self.center = 0
     self.bbox = core.Rect(core.Point(glyph.ul_x, glyph.ul_y),
                           core.Dim(glyph.ncols, glyph.nrows))
     self.glyphs = []
     self.add_glyph(glyph)
Ejemplo n.º 6
0
    def find_sections(self):
        """Find the sections within an image - this finds large blocks
        of text making it possible to find the lines within complex
        text layouts."""

        glyphs = self.glyphs

        FUDGE = self.__avg_glyph_size(glyphs) * self.section_search_size

        # remove noise and large objects
        self.__noise_size = FUDGE
        self.__large_size = FUDGE * 20
        new_glyphs = []
        for g in glyphs:
            if self.__section_size_test(g):
                new_glyphs.append(g)
            else:
                if self.__fill:
                    g.fill_white()
        glyphs = new_glyphs

        # Sort the glyphs left-to-right and top-to-bottom
        glyphs.sort(lambda x, y: cmp(x.ul_x, y.ul_x))
        glyphs.sort(lambda x, y: cmp(x.ul_y, y.ul_y))

        # Create rectangles for each glyph that are bigger by FUDGE
        big_rects = []
        for g in glyphs:
            ul_y = max(0, g.ul_y - FUDGE)
            ul_x = max(0, g.ul_x - FUDGE)
            lr_y = min(self.image.lr_y, g.lr_y + FUDGE)
            lr_x = min(self.image.lr_x, g.lr_x + FUDGE)
            ul_x = int(ul_x)
            ul_y = int(ul_y)
            nrows = int(lr_y - ul_y + 1)
            ncols = int(lr_x - ul_x + 1)
            big_rects.append(
                core.Rect(core.Point(ul_x, ul_y), core.Dim(ncols, nrows)))

        # Search for intersecting glyphs and merge them. This is
        # harder than it seems at first because we want everything
        # to merge together that intersects regardless of the order
        # in the list. It ends up being similar to connected-component
        # labeling. This is prone to be kind-of slow.
        current = 0
        rects = big_rects
        while (1):
            # Find the indexexes of any rects that interesect with current
            inter = self.__find_intersecting_rects(rects, current)
            # If we found intersecting rectangles merge them with them current
            # rect, remove them from the list, and start the whole process
            # over. We start over to make certain that everything that should
            # be merged is.
            if len(inter):
                g = rects[current]
                new_rects = [g]
                for i in range(len(rects)):
                    if i == current:
                        continue
                    if i in inter:
                        g.union(rects[i])
                    else:
                        new_rects.append(rects[i])
                rects = new_rects
                current = 0
            # If we didn't find anything that intersected move on to the next
            # rectangle.
            else:
                current += 1
            # Bail when we are done.
            if current >= len(rects):
                break

        # Create the sections
        sections = []
        for rect in rects:
            sections.append(Section(rect))

        # Place the original (small) glyphs into the sections
        for glyph in self.glyphs:
            if self.__section_size_test(glyph):
                for s in sections:
                    if s.bbox.intersects(glyph):
                        s.add_glyph(glyph)
                        break

        # Fix up the bounding boxes
        for s in sections:
            s.calculate_bbox()

        self.sections = sections