예제 #1
0
def test_eq_is_equal(empty_bbox: BoundingBox, partial_bbox: BoundingBox,
                     full_bbox: BoundingBox) -> None:
    for a, b in [
        (empty_bbox, BoundingBox(0.0, 0.0, 0.0, 0.0)),
        (partial_bbox, BoundingBox(25.0, 75.0, 26.0, 70.0)),
        (full_bbox, BoundingBox(0.0, 100.0, 0.0, 100.0)),
    ]:
        assert (a == b)
예제 #2
0
def test_from_dict_input_format(raw_dict: Dict) -> None:
    bbox = BoundingBox.from_dict(raw_dict)
    assert (not bbox.is_empty())
    assert (bbox.x_min == 1.0)
    assert (bbox.x_max == 2.0)
    assert (bbox.y_min == 3.0)
    assert (bbox.y_max == 4.0)
예제 #3
0
def test_from_points_valid_neg(full_bbox_points: List[Point], neg_point: Point,
                               full_bbox: BoundingBox) -> None:
    points = full_bbox_points + [neg_point]
    bbox = BoundingBox.from_points(points)
    expected_bbox = replace(full_bbox, x_min=-10.0, y_min=-10.0)
    assert (not bbox.is_empty())
    assert (bbox == expected_bbox)
예제 #4
0
def shape_image_to_bbox(image: np.ndarray, bbox: BoundingBox,
                        thumbnail_size: Tuple[float, float]) -> np.ndarray:
    # TODO: Change thumbnail size to paitypes.geometry.Shape

    if bbox.is_empty():
        return image

    # TODO: Refactor into `image.resizing` module as a helper method to be
    # shared across detectors.

    # TODO: Use paitypes.geometry.Shape for the following logic
    padded_bbox = pad_to_min_size(bbox, thumbnail_size)
    padded_bbox = pad_abs_amount(padded_bbox, (20.0, 20.0))

    aspect_ratio = (float(thumbnail_size[0]) / float(thumbnail_size[1]))
    padded_bbox = pad_to_aspect_ratio(padded_bbox, aspect_ratio)

    # mypy can't figure out that `image.shape[:2]` is limited to two cells
    shape = (image.shape[0], image.shape[1])
    cropped_bbox = snap_to_shape(padded_bbox, shape)

    # TODO: Type this call properly.
    cropped_image = crop_image_to_bounding_box(cast(Image, image),
                                               cropped_bbox)

    resized_image = cv2.resize(cropped_image,
                               thumbnail_size,
                               interpolation=cv2.INTER_AREA)

    return resized_image
예제 #5
0
def test_partially_contains(bbox1: BoundingBox) -> None:
    moved_bbox = BoundingBox(bbox1.x_min - bbox1.delta_x / 2.0,
                             bbox1.x_min + bbox1.delta_x / 2.0,
                             bbox1.y_min - bbox1.delta_y / 2.0,
                             bbox1.y_min + bbox1.delta_y / 2.0)

    assume(moved_bbox.area != 0.0)
    assert isclose(contains_ratio(bbox1, moved_bbox), 0.25, abs_tol=1e-5)
예제 #6
0
    def test_pad_out_of_bounds_neg(self) -> None:
        bbox = BoundingBox(0.0, 10.0, 2.0, 12.0)

        padded_bbox = pad_to_min_size(bbox, (20.0, 20.0))

        assert (padded_bbox.y_min == -3.0)
        assert (padded_bbox.y_max == 17.0)
        assert (padded_bbox.x_min == -5.0)
        assert (padded_bbox.x_max == 15.0)
예제 #7
0
    def test_pad_out_of_bounds_pos(self) -> None:
        bbox = BoundingBox(90.0, 100.0, 92.0, 102.0)

        padded_bbox = pad_to_min_size(bbox, (20.0, 20.0))

        assert (padded_bbox.y_min == 87.0)
        assert (padded_bbox.y_max == 107.0)
        assert (padded_bbox.x_min == 85.0)
        assert (padded_bbox.x_max == 105.0)
예제 #8
0
class TestResizeCropImageToBoundingBox():
    def test_crop_to_partial_bbox(self, all_valid_images: List[Image],
                                  partial_bbox: BoundingBox) -> None:
        for image in all_valid_images:
            cropped_image = crop_image_to_bounding_box(image, partial_bbox)
            assert (np.array_equal(cropped_image, image[26:70, 25:75]))

    def test_crop_to_full_bbox(self, all_valid_images: List[Image],
                               full_bbox: BoundingBox) -> None:
        for image in all_valid_images:
            cropped_image = crop_image_to_bounding_box(image, full_bbox)
            assert (np.array_equal(cropped_image, image))

    def test_crop_to_partial_float_bbox(
            self, all_valid_images: List[Image],
            partial_float_bbox: BoundingBox) -> None:
        for image in all_valid_images:
            cropped_image = crop_image_to_bounding_box(image,
                                                       partial_float_bbox)
            assert (np.array_equal(cropped_image, image[27:74, 33:68]))

    def test_crop_to_empty_bbox_raises(self, all_valid_images: List[Image],
                                       empty_bbox: BoundingBox) -> None:
        for image in all_valid_images:
            with pytest.raises(ImageResizingException):
                crop_image_to_bounding_box(image, empty_bbox)

    def test_crop_to_empty_image_raises(self, empty_images: List[Image],
                                        full_bbox: BoundingBox) -> None:
        for empty_image in empty_images:
            with pytest.raises(ImageResizingException):
                crop_image_to_bounding_box(empty_image, full_bbox)

    @pytest.mark.parametrize('bbox', [
        BoundingBox(-1.0, 0.0, 0.0, 100.0),
        BoundingBox(0.0, 0.0, -1.0, 100.0),
        BoundingBox(0.0, 101.0, 0.0, 100.0),
        BoundingBox(0.0, 100.0, 0.0, 101.0)
    ])
    def test_crop_to_out_of_bounds_bbox_raises(self, all_valid_images: Image,
                                               bbox: BoundingBox) -> None:
        for image in all_valid_images:
            with pytest.raises(ImageResizingException):
                crop_image_to_bounding_box(image, bbox)
예제 #9
0
def test_scale_around_corners_maintains_corners(bbox: BoundingBox, sx: float,
                                                sy: float) -> None:
    scaled_bbox = bbox.scale(Shape(sx, sy),
                             center=Point(bbox.x_min, bbox.y_min))
    assert scaled_bbox.x_min == approx(bbox.x_min, abs=1e-6)
    assert scaled_bbox.y_min == approx(bbox.y_min, abs=1e-6)

    scaled_bbox = bbox.scale(Shape(sx, sy),
                             center=Point(bbox.x_min, bbox.y_max))
    assert scaled_bbox.x_min == approx(bbox.x_min, abs=1e-6)
    assert scaled_bbox.y_max == approx(bbox.y_max, abs=1e-6)

    scaled_bbox = bbox.scale(Shape(sx, sy),
                             center=Point(bbox.x_max, bbox.y_min))
    assert scaled_bbox.x_max == approx(bbox.x_max, abs=1e-6)
    assert scaled_bbox.y_min == approx(bbox.y_min, abs=1e-6)

    scaled_bbox = bbox.scale(Shape(sx, sy),
                             center=Point(bbox.x_max, bbox.y_max))
    assert scaled_bbox.x_max == approx(bbox.x_max, abs=1e-6)
    assert scaled_bbox.y_max == approx(bbox.y_max, abs=1e-6)
예제 #10
0
def bounding_boxes(draw: Any, container: BoundingBox = None) -> BoundingBox:
    x_min = -10000
    y_min = -10000
    w_max = 10000
    h_max = 10000
    if container:
        x_min = container.x_min
        y_min = container.y_min
        w_max = container.delta_x
        h_max = container.delta_y

    x = draw(floats(min_value=x_min, max_value=10000.0))
    y = draw(floats(min_value=y_min, max_value=10000.0))
    w = draw(floats(min_value=0.0, max_value=w_max))
    h = draw(floats(min_value=0.0, max_value=h_max))
    return BoundingBox(x, x + w, y, y + h)
예제 #11
0
def crop_image_to_bounding_box(image: ImageT, bbox: BoundingBox) -> ImageT:
    """
    Crops `image` to the dimensions of `bbox`.
    """
    if image.shape[0] == 0 or image.shape[1] == 0:
        raise ImageResizingException('image shape is invalid')

    if bbox.is_empty():
        raise ImageResizingException('bbox is empty')

    y_min, y_max, x_min, x_max = (int(bbox.y_min), int(bbox.y_max),
                                  int(bbox.x_min), int(bbox.x_max))

    if (y_min < 0 or x_min < 0 or y_max > image.shape[0]
            or x_max > image.shape[1]):
        raise ImageResizingException('bbox outside image bounds')

    return image[y_min:y_max, x_min:x_max]
예제 #12
0
def test_no_move(bbox: BoundingBox) -> None:
    assert bbox.move(0, 0) == bbox
예제 #13
0
def test_from_dict_invalid_input(raw_dict: Dict) -> None:
    with pytest.raises(BoundingBoxError):
        bbox = BoundingBox.from_dict(raw_dict)
예제 #14
0
def test_from_points_valid(full_bbox_points: List[Point],
                           full_bbox: BoundingBox) -> None:
    bbox = BoundingBox.from_points(full_bbox_points)
    assert (not bbox.is_empty())
    assert (bbox == full_bbox)
예제 #15
0
def test_from_single_point_empty(full_bbox_points: List[Point]) -> None:
    for point in full_bbox_points:
        bbox = BoundingBox.from_points([point])
        assert (bbox.is_empty())
예제 #16
0
def test_offset_bboxes_returns_union(full_bbox: BoundingBox) -> None:
    other = BoundingBox(-100.0, 0.0, -100.0, 0.0)
    expected = BoundingBox(-100.0, 100.0, -100.0, 100.0)
    assert (full_bbox + other == expected)
예제 #17
0
def test_inverted_bbox_is_empty() -> None:
    bbox = BoundingBox(10.0, 10.0, 0.0, 0.0)
    assert (bbox.is_empty())
예제 #18
0
def test_fully_contains(bbox1: BoundingBox) -> None:
    contained = BoundingBox(bbox1.x_min, bbox1.x_min + bbox1.delta_x / 2.0,
                            bbox1.y_min, bbox1.y_min + bbox1.delta_y / 2.0)

    assume(contained.area != 0.0)
    assert contains_ratio(bbox1, contained) == 1.0
예제 #19
0
def test_scale_around_center_maintains_center(bbox: BoundingBox, sx: float,
                                              sy: float) -> None:
    scaled_bbox = bbox.scale(Shape(sx, sy), center=bbox.center)
    assert scaled_bbox.center.x == approx(bbox.center.x, abs=1e-6)
    assert scaled_bbox.center.y == approx(bbox.center.y, abs=1e-6)
예제 #20
0
def test_scale_around_center_changes_size(bbox: BoundingBox, sx: float,
                                          sy: float) -> None:
    scaled_bbox = bbox.scale(Shape(sx, sy), center=bbox.center)
    assert scaled_bbox.delta_x == approx(bbox.delta_x * sx, abs=1e-6)
    assert scaled_bbox.delta_y == approx(bbox.delta_y * sy, abs=1e-6)
예제 #21
0
def test_to_dict_from_dict(empty_bbox: BoundingBox, partial_bbox: BoundingBox,
                           full_bbox: BoundingBox) -> None:
    for bbox in [empty_bbox, partial_bbox, full_bbox]:
        assert BoundingBox.from_dict(bbox.to_dict()) == bbox
예제 #22
0
def test_scale_around_origin_moves_center(bbox: BoundingBox, sx: float,
                                          sy: float) -> None:
    scaled_bbox = bbox.scale(Shape(sx, sy))
    assert scaled_bbox.center.x == approx(bbox.center.x * sx, abs=1e-6)
    assert scaled_bbox.center.y == approx(bbox.center.y * sy, abs=1e-6)
예제 #23
0
def test_from_dict_to_dict(raw_dict: Dict) -> None:
    bbox1 = BoundingBox.from_dict(raw_dict)
    bbox2 = BoundingBox.from_dict(BoundingBox.from_dict(raw_dict).to_dict())
    assert (bbox1 == bbox2)