Skip to content

Commit

Permalink
Fix Affine and Perspective bbox clipping (#1231)
Browse files Browse the repository at this point in the history
* Fix Affine bbox clipping

* Fix Perspective bbox clipping

Co-authored-by: Mikhail Druzhinin <dipet@gmail.com>
  • Loading branch information
Dipet and Mikhail Druzhinin committed Jul 18, 2022
1 parent 0203864 commit 85c3c0b
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 9 deletions.
10 changes: 1 addition & 9 deletions albumentations/augmentations/geometric/functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,18 +461,12 @@ def perspective_bbox(
for pt in points:
pt = perspective_keypoint(pt.tolist() + [0, 0], height, width, matrix, max_width, max_height, keep_size)
x, y = pt[:2]
x = np.clip(x, 0, width if keep_size else max_width)
y = np.clip(y, 0, height if keep_size else max_height)
x1 = min(x1, x)
x2 = max(x2, x)
y1 = min(y1, y)
y2 = max(y2, y)

x = np.clip([x1, x2], 0, width if keep_size else max_width)
y = np.clip([y1, y2], 0, height if keep_size else max_height)
return normalize_bbox(
(x[0], y[0], x[1], y[1]), height if keep_size else max_height, width if keep_size else max_width
)
return normalize_bbox((x1, y1, x2, y2), height if keep_size else max_height, width if keep_size else max_width)


def rotation2DMatrixToEulerAngles(matrix: np.ndarray, y_up: bool = False) -> float:
Expand Down Expand Up @@ -575,8 +569,6 @@ def bbox_affine(
]
)
points = skimage.transform.matrix_transform(points, matrix.params)
points[:, 0] = np.clip(points[:, 0], 0, output_shape[1])
points[:, 1] = np.clip(points[:, 1], 0, output_shape[0])
x_min = np.min(points[:, 0])
x_max = np.max(points[:, 0])
y_min = np.min(points[:, 1])
Expand Down
37 changes: 37 additions & 0 deletions tests/test_transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -1188,3 +1188,40 @@ def test_rotate_equal(img, aug_cls, angle):
diff = np.round(np.abs(res_a - res_b))
assert diff[:, :2].max() <= 2
assert (diff[:, -1] % 360).max() <= 1


@pytest.mark.parametrize(
"get_transform",
[
lambda sign: A.Affine(translate_px=sign * 2),
lambda sign: A.ShiftScaleRotate(shift_limit=(sign * 0.02, sign * 0.02), scale_limit=0, rotate_limit=0),
],
)
@pytest.mark.parametrize(
["bboxes", "expected", "min_visibility", "sign"],
[
[[(0, 0, 10, 10, 1)], [], 0.9, -1],
[[(0, 0, 10, 10, 1)], [(0, 0, 8, 8, 1)], 0.6, -1],
[[(90, 90, 100, 100, 1)], [], 0.9, 1],
[[(90, 90, 100, 100, 1)], [(92, 92, 100, 100, 1)], 0.6, 1],
],
)
def test_bbox_clipping(get_transform, image, bboxes, expected, min_visibility: float, sign: int):
transform = get_transform(sign)
transform.p = 1
transform = A.Compose([transform], bbox_params=A.BboxParams(format="pascal_voc", min_visibility=min_visibility))

res = transform(image=image, bboxes=bboxes)["bboxes"]
assert res == expected


def test_bbox_clipping_perspective():
random.seed(0)
transform = A.Compose(
[A.Perspective(scale=(0.05, 0.05), p=1)], bbox_params=A.BboxParams(format="pascal_voc", min_visibility=0.6)
)

image = np.empty([1000, 1000, 3], dtype=np.uint8)
bboxes = np.array([[0, 0, 100, 100, 1]])
res = transform(image=image, bboxes=bboxes)["bboxes"]
assert len(res) == 0

0 comments on commit 85c3c0b

Please sign in to comment.