Exemplo n.º 1
0
    def test_detect_intersection_rect_T(self):
        image = np.array(
            [
                [False, False, False, False],
                [True, True, True, True],
                [True, True, True, True],
                [True, True, True, True],
                [False, True, True, False],
            ]
        )
        i_regions = [
            DirectedLine.btwn(*np.array([(3, 1), (1, 1)])),
            DirectedLine.btwn(*np.array([(3, 2), (1, 2)])),
            DirectedLine.btwn(*np.array([(3, 1), (3, 2)])),
            DirectedLine.btwn(*np.array([(2, 1), (2, 2)])),
            DirectedLine.btwn(*np.array([(1, 1), (1, 2)])),
        ]

        for line in i_regions:
            (top_left, bottom_right) = detect_intersection_rect(image, line)
            assert (
                top_left == 1
            ).all(), f"{line.direction}: Top left of junction should be [1 1] but was {top_left}"
            assert (
                bottom_right == np.array([3, 2])
            ).all(), f"{line.direction}: Intersection BR should be [3 2] but was {bottom_right}"

            line = line.reverse()
            (top_left, bottom_right) = detect_intersection_rect(image, line)
            assert (
                top_left == 1
            ).all(), f"{line.direction}: Top left of junction should be [1 1] but was {top_left}"
            assert (
                bottom_right == np.array([3, 2])
            ).all(), f"{line.direction}: Intersection BR should be [3 2] but was {bottom_right}"
Exemplo n.º 2
0
    def test_detect_intersection_rect_L_270(self):
        image = np.array(
            [
                [False, True, True, False],
                [True, True, True, False],
                [True, True, True, False],
                [False, False, False, False],
            ]
        )

        i_regions = [
            DirectedLine.btwn(*np.array([(1, 1), (1, 2)])),
            DirectedLine.btwn(*np.array([(1, 2), (1, 1)])),
            DirectedLine.btwn(*np.array([(1, 1), (2, 1)])),
            DirectedLine.btwn(*np.array([(2, 1), (1, 1)])),
        ]

        for line in i_regions:
            (top_left, bottom_right) = detect_intersection_rect(image, line)
            assert (top_left == 1).all()
            assert (bottom_right == 2).all()
Exemplo n.º 3
0
 def test_detect_intersection_big(self):
     image = np.zeros((20, 20), dtype=bool)
     image[:, 12] = True
     image[5, :] = True
     line = DirectedLine.btwn(np.array([10, 12]), np.array([0, 12]))
     intersection = line.detect_intersection(image)
     assert intersection
     (x, y, width, height) = intersection.bounding_box()
     assert x == 12
     assert y == 5
     assert width == 1
     assert height == 1
     assert line.remove_overlap_into(intersection.bounding_box())
Exemplo n.º 4
0
    def test_detect_intersection_rect_L(self):
        image = np.array(
            [
                [False, True, True, False],
                [False, True, True, True],
                [False, True, True, True],
                [False, False, False, False],
            ]
        )
        i_regions = [
            DirectedLine.btwn(*np.array([(1, 1), (1, 2)])),
            DirectedLine.btwn(*np.array([(1, 2), (1, 1)])),
            DirectedLine.btwn(*np.array([(1, 2), (2, 2)])),
            DirectedLine.btwn(*np.array([(2, 2), (1, 2)])),
        ]

        for line in i_regions:
            (top_left, bottom_right) = detect_intersection_rect(image, line)
            assert (
                top_left == 1
            ).all(), f"Expected top left to be [1 1]. Found {top_left}"
            assert (
                bottom_right == 2
            ).all(), f"Expected bottom right to be [2 2]. Found {bottom_right}"
Exemplo n.º 5
0
 def test_detect_intersection(self):
     image = np.array(
         [
             [False, False, True, False, False, False, False],
             [False, False, True, True, True, True, True],
             [False, False, True, False, False, False, False],
             [False, False, True, False, True, False, False],
             [False, False, True, False, False, False, False],
             [False, False, True, False, False, False, False],
             [False, False, True, False, False, False, False],
         ]
     )
     line = DirectedLine.btwn(np.array([6, 2]), np.array([0, 2]))
     intersection = line.detect_intersection(image)
     assert intersection
     (x, y, width, height) = intersection.bounding_box()
     assert width == 1
     assert height == 1
     assert line.remove_overlap_into(intersection.bounding_box())
Exemplo n.º 6
0
def get_start_lines(image, annotation, min_length=5):
    x, y, width, height = annotation.bounding_box(inclusive=True).astype(int)

    directions = [
        Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST
    ]
    box_size = np.array([height, width])
    box_location = [y, x]
    lines = []
    for direction in directions:
        # If we are vertical, "fixed dim" is y else it is x
        # If we are positive, we need to add the width/height to the fixed dim
        #
        # First, we will define some masks that we will use to make the code generic
        # including masks for vertical/horizontal values and the positivity mask
        vh_mask = direction.value() != 0
        pos_mask = direction.value() > 0

        fixed_dim_offset = vh_mask * box_location + pos_mask * box_size
        candidate_idx = [None, None]
        idx = fixed_dim_offset.nonzero()[0].item()
        candidate_idx[idx] = fixed_dim_offset[idx]

        r_dir = direction.turn_right()
        rvh_mask = r_dir.value() != 0
        start = rvh_mask * box_location
        end = rvh_mask * box_size + start

        # Next, we will determine the "start (point) candidates". These are
        # the locations on the bounding box that are black and might be the
        # beginning of an outgoing line
        o_idx = start.nonzero()[0].item()
        candidate_idx[o_idx] = range(start[o_idx], end[o_idx] + 1)
        start_candidates = (
            np.where(image[candidate_idx[0], candidate_idx[1]])[0] +
            start[o_idx])

        # Now, we will determine the actual start points. These are the start
        # candidates which extend at least the minimum distance.
        region_idx = [None, None]
        region_idx_start = fixed_dim_offset[idx]
        region_idx_step = direction.value()[idx]
        region_idx_end = (fixed_dim_offset +
                          min_length * direction.value())[idx]
        min_len_is_off_image = region_idx_end > image.shape[
            idx] or region_idx_end < 0
        if min_len_is_off_image:
            continue

        region_idx[idx] = range(region_idx_start, region_idx_end,
                                region_idx_step)
        region_idx[o_idx] = start_candidates
        region_idx = np.ix_(*region_idx)

        line_region = image[region_idx[0], region_idx[1]]
        sum_axis = 0 if direction.is_vertical() else 1
        start_values = start_candidates[np.where(
            line_region.sum(axis=sum_axis) == min_length)[0]]
        start_points = np.zeros((start_values.shape[0], 2))
        start_points[:, o_idx] = start_values
        start_points[:, idx] = fixed_dim_offset[idx]

        # Finally, we will back each line up as far as we can into the bounding box
        is_line = lambda pt: image[pt[0], pt[1]]
        end_points = [
            point + min_length * direction.value() for point in start_points
        ]
        for pt in start_points:
            possible_points = np.zeros(((vh_mask * box_size).sum() + 1, 2))
            possible_points[:, o_idx] = pt[o_idx]
            end_point = pt + (vh_mask *
                              (box_size + 1) * direction.reverse().value())
            possible_points[:, idx] = range(int(pt[idx]), int(end_point[idx]),
                                            -1 * direction.value()[idx])
            assert len(
                possible_points), f"No start points from {pt} for {annotation}"
            last_valid_point = list(
                takewhile(is_line, possible_points.astype(int)))[-1]
            pt[idx] = last_valid_point[idx]

        lines.extend([
            DirectedLine(start, end, direction)
            for (start, end) in zip(start_points, end_points)
        ])

    return lines