Ejemplo n.º 1
0
    def test_contains_with_overlapping_rectangles(self):
        rect1 = Rectangle(0, 0, 50, 50)
        rect2 = Rectangle(10, 40, 20, 20)
        border_rect = Rectangle(10, 40, 10, 10)

        self.assertFalse(rect2 in rect1)
        self.assertTrue(border_rect in rect1)
Ejemplo n.º 2
0
def find_bubbles(labelnum, labels, rectangles, img, show_image=False):
    height, width = img.shape
    colors = dict()
    colors[0] = 0
    for label in range(1, labelnum):
        labels[labels == label] = random.randint(0, 255)
    labels = labels.astype(np.uint8)
    img1 = cv2.bitwise_not(img)

    _, contours, hierarchy = cv2.findContours(
        img1, cv2.cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    n = 0
    area = float(labels.shape[0] * labels.shape[1])
    medium_tree = Tree()
    large_tree = Tree()
    for elem in hierarchy[0]:
        contour = contours[n]
        x, y, w, h = cv2.boundingRect(contour)
        bounding_box = Rectangle(x, y, w, h)
        box_area = bounding_box.area()
        node = Node(elem[3], n, contour, bounding_box)
        if box_area > area / 10:
            large_tree.add(node)
        elif box_area > area / 1000:
            medium_tree.add(node)
        n += 1

    possible_bubbles = [(node, level)
                        for node, level in
                        medium_tree.level_order_traversal()]
    img2 = np.zeros((height, width, 3), np.uint8)

    if show_image:
        for node, level1 in medium_tree.level_order_traversal():
            if node.n != -1:
                cv2.drawContours(img2, contours, node.n,
                                 (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)), -1)

        for rect in rectangles:
            print("Drawing ", rect)
            img2 = cv2.rectangle(img2, (rect.x, rect.y), (rect.r_bot.x, rect.r_bot.y), (255, 255, 0), 1)

            """
            font = cv2.FONT_HERSHEY_SIMPLEX
            bottomLeftCornerOfText = (rect.l_bot.x, rect.l_bot.y)
            fontScale = 0.4
            fontColor = (255, 255, 255)
            cv2.putText(img2, str(rect.area()),
                        bottomLeftCornerOfText,
                        font,
                        fontScale,
                        fontColor)
            """
        show(img2)
    return possible_bubbles
Ejemplo n.º 3
0
def is_first_letter(rect, quadtree, draw = None):
    left_rec = Rectangle(rect.x - rect.height,
                         rect.y, rect.height, rect.height)
    if draw:
        left_rec.draw(draw, outline="yellow")
    neighbours = []
    quadtree.retrieve(neighbours, rect)
    for rect1 in neighbours:
        if rect1 is not rect and rect1.overlaps_with(left_rec):
            return False
    return True
Ejemplo n.º 4
0
    def test_get_index(self):
        bounds = Rectangle(0, 0, 400, 400)
        quadtree = Quadtree(0, bounds)

        rect1 = Rectangle(100, 10, 10, 10)
        rect2 = Rectangle(190, 10, 20, 20)

        quadtree.insert(rect1)
        quadtree.insert(rect2)
        self.assertEqual(1, quadtree.get_index(rect1))
        self.assertEqual(-1, quadtree.get_index(rect2))
Ejemplo n.º 5
0
    def test_retrieve(self):
        bounds = Rectangle(0, 0, 1000, 1000)
        quadtree = Quadtree(0, bounds)
        for x in range(10):
            for y in range(10):
                quadtree.insert(Rectangle(x * 20, y * 20, 10, 10))

        rect3 = Rectangle(150, 10, 10, 10)

        rectangles = []
        quadtree.retrieve(rectangles, rect3)

        self.assertEqual(len(rectangles), 33)
Ejemplo n.º 6
0
    def split(self):
        x = self.bounds.x
        y = self.bounds.y
        subWidth = self.bounds.width / 2
        subHeight = self.bounds.height / 2

        self.nodes[0] = Quadtree(
            self.level + 1, Rectangle(x + subWidth, y, subWidth, subHeight))
        self.nodes[1] = Quadtree(self.level + 1,
                                 Rectangle(x, y, subWidth, subHeight))
        self.nodes[2] = Quadtree(
            self.level + 1, Rectangle(x, y + subHeight, subWidth, subHeight))
        self.nodes[3] = Quadtree(
            self.level + 1,
            Rectangle(x + subWidth, y + subHeight, subWidth, subHeight))
Ejemplo n.º 7
0
def cv2_connected_components(img1, min_size=50, max_size=100000):
    img1 = cv2.bitwise_not(img1)
    labelnum, labels, stats, centroids = cv2.connectedComponentsWithStats(img1)

    rectangles = []

    for label in range(1, labelnum):

        x, y, w, h, size = stats[label]
        rect = Rectangle(x,y,w,h)

        if min_size < rect.area() < max_size:
            rectangles.append(rect)


    return labelnum, labels, rectangles
Ejemplo n.º 8
0
def mask_groups(img, groups, possible_bubbles):
    """
    Returns list of masked images
    :param img: image to mask
    :type img: Image
    :param groups: group of rectangles to use as masks
    :return: list of masked images and their
    top left corner position on the original image
    :rtype: list[int, int, Image, Rectangle, list[Rectangles], list[Rectangle]]

    """
    masks = []
    width, height = img.size
    used_bubbles = []
    for label in groups:
        lines = groups[label]
        (x_max, x_min, y_max, y_min) = crop_size_rectangles(groups[label])
        bounding_box = Rectangle(x_min, y_min, x_max - x_min, y_max - y_min)
        line_length = len(lines)
        if line_length <= 1:
            continue
        """
        if line_length > 1 or \
                (line_length == 1 and
                    lines[0].width/lines[0].height > 2 and
                    lines[0].width * lines[0].height > 500):
        """
        highest_level = 0
        index = -1
        for i, bubble in enumerate(possible_bubbles):
            if i != 0 and \
                    bounding_box in bubble[0].box:
                if i in used_bubbles:
                    break
                if highest_level < bubble[1]:
                    highest_level=bubble[1]
                    index = i
        if index > 0 and index not in used_bubbles:
            used_bubbles.append(index)
            bubble = possible_bubbles[index][0]
            cv2_img = np.full((height, width), 255, dtype=np.uint8)
            cv2.drawContours(cv2_img, [bubble.contour], 0, 0, -1)

            masked_img = Image.fromarray(cv2_img)
            draw = ImageDraw.Draw(masked_img)

            for rect in lines:
                rect.draw(draw, fill=True)
            temp_img = img.copy()
            temp_img.paste(masked_img, mask=masked_img)
            bounding_box = bubble.box
            temp_img = temp_img.crop((bounding_box.x, bounding_box.y,
                                      bounding_box.x + bounding_box.width,
                                      bounding_box.y + bounding_box.height))
            masks.append((bounding_box.x, bounding_box.y, temp_img, bounding_box, lines, bubble))

            continue

    return masks
Ejemplo n.º 9
0
def iterate_rectangles(rectangles1, rectangles2, width, height):
    quadtree = Quadtree(0, Rectangle(0, 0, width, height))
    for rect in rectangles2:
        if rect:
            quadtree.insert(rect)
    for rect in rectangles1:
        neighbours = []
        quadtree.retrieve(neighbours, rect)
        for rect1 in neighbours:
            yield rect, rect1
Ejemplo n.º 10
0
def get_lines(rectangles, width, height):
    """
    Finds all rectangles that are aligned with each other
    and have similar height and groups them
    :param rectangles:
    :type: Rectangle
    :return: groups of rectangles
    :rtype: dict[int, list]
    """
    n = 0
    lines = dict()
    quadtree = Quadtree(0, Rectangle(0,0,width, height))
    for rect in rectangles:
        quadtree.insert(rect)
    for rect in rectangles:
        is_first = is_first_letter(rect, quadtree)
        if is_first:

            last_rect = rect
            lines[n] = list()
            lines[n].append(last_rect)
            neighbours = []
            quadtree.retrieve(neighbours, rect)
            for rect1 in sorted(neighbours, key=lambda rec: rec.x):
                right_last_rect = Rectangle(last_rect.x + last_rect.width,
                                            last_rect.y, last_rect.height * 1.5,
                                            last_rect.height)

                if rect is not rect1 and \
                        rect.inline(rect1) and \
                        right_last_rect.intersects(rect1) and \
                        math.sqrt(pow(rect.height-rect1.height, 2)) < 0.5*rect.height:
                    last_rect = rect1
                    lines[n].append(last_rect)

            n += 1
    result = []
    for key in lines:
        line = line_bounding_box(lines[key])
        result.append(line)
    return result
Ejemplo n.º 11
0
def group_lines(lines):
    """
    Groups lines together
    :param lines: dictionary that contains all the
    black pixels in a line
    :type lines: dict[int, list]
    :return:
    :rtype: dict[int, list[Rectangle]]
    """
    bounding_boxes = dict()
    uf_arr = UFarray()
    n = 0
    for line in lines:
        bounding_boxes[n] = line
        n += 1

    groups = dict()
    uf_arr.setLabel(len(bounding_boxes))
    for n in bounding_boxes:
        rect = bounding_boxes[n]
        top_rect = Rectangle(rect.x, rect.y + rect.height,
                             rect.width, rect.height)
        bottom_rect = Rectangle(rect.x, rect.y - rect.height,
                                rect.width, rect.height)
        for k in bounding_boxes:
            rect1 = bounding_boxes[k]
            if rect is not rect1:
                if (rect1.intersects(bottom_rect) or
                        rect1.intersects(top_rect)) and \
                        abs(rect.height - rect1.height) < 0.3 * rect.height:
                    uf_arr.setLabel(max(n, k))
                    uf_arr.union(n, k)
    uf_arr.flatten()

    for n in bounding_boxes:
        index = uf_arr.find(n)
        line_list = groups.get(index, list())
        line_list.append(bounding_boxes[n])
        groups[index] = line_list
    return groups
Ejemplo n.º 12
0
def third_pass(rectangles):
    possible_letters = list()

    for rec in rectangles:
        top_rec = Rectangle(rec.x, rec.y - rec.height,
                            rec.height, rec.height)
        bottom_rec = Rectangle(rec.x, rec.y + rec.height,
                               rec.height, rec.height)
        right_rec = Rectangle(rec.x + rec.width, rec.y,
                              rec.height, rec.height)
        left_rec = Rectangle(rec.x - rec.width, rec.y - rec.height,
                             rec.height, rec.height)

        for rect2 in rectangles:
            if (rect2.intersects(top_rec) or
                    rect2.intersects(right_rec) or
                    rect2.intersects(bottom_rec) or
                    rect2.intersects(left_rec) or
                    rect2.intersects(rec)):
                if rec not in possible_letters:
                    possible_letters.append(rec)

    logger.info("found " + str(len(possible_letters)) + " possible letters")
    return possible_letters
Ejemplo n.º 13
0
def line_bounding_box(line):
    left = min([v.l_top.x for v in line])
    right = max([v.r_bot.x for v in line])
    top = min([v.l_top.y for v in line])
    bottom = max([v.r_bot.y for v in line])
    return Rectangle(left, top, (right - left), (bottom - top))
Ejemplo n.º 14
0
    def test_contains(self):
        rect1 = Rectangle(0, 0, 50, 50)
        rect2 = Rectangle(10, 10, 20, 20)

        self.assertTrue(rect2 in rect1)
        self.assertFalse(rect1 in rect2)
Ejemplo n.º 15
0
 def test_overlap(self):
     rect1 = Rectangle(0, 0, 50, 50)
     rect2 = Rectangle(10, 10, 100, 20)
     self.assertTrue(rect2.overlaps_with(rect1))