Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added keypoints support to RandomSizedBBoxSafeCrop. #686

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ Spatial-level transforms will simultaneously change both an input image as well
| [RandomResizedCrop](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.RandomResizedCrop) | ✓ | ✓ | ✓ | ✓ |
| [RandomRotate90](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.RandomRotate90) | ✓ | ✓ | ✓ | ✓ |
| [RandomScale](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.RandomScale) | ✓ | ✓ | ✓ | ✓ |
| [RandomSizedBBoxSafeCrop](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.RandomSizedBBoxSafeCrop) | ✓ | ✓ | ✓ | |
| [RandomSizedBBoxSafeCrop](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.RandomSizedBBoxSafeCrop) | ✓ | ✓ | ✓ | |
| [RandomSizedCrop](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.RandomSizedCrop) | ✓ | ✓ | ✓ | ✓ |
| [Resize](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.Resize) | ✓ | ✓ | ✓ | ✓ |
| [Rotate](https://albumentations.ai/docs/api_reference/augmentations/transforms/#albumentations.augmentations.transforms.Rotate) | ✓ | ✓ | ✓ | ✓ |
Expand Down
29 changes: 12 additions & 17 deletions albumentations/augmentations/functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -1502,16 +1502,16 @@ def bbox_flip(bbox, d, rows, cols):


def crop_bbox_by_coords(bbox, crop_coords, crop_height, crop_width, rows, cols):
"""Crop a bounding box using the provided coordinates of bottom-left and top-right corners in pixels and the
required height and width of the crop.
"""Crop a bounding box using the provided coordinates `crop_coords` of bottom-left and top-right corners in pixels
and scale it to fit cropped area being scaled to `(crop_height, crop_width)` size.

Args:
bbox (tuple): A cropped box `(x_min, y_min, x_max, y_max)`.
crop_coords (tuple): Crop coordinates `(x1, y1, x2, y2)`.
crop_height (int):
crop_width (int):
rows (int): Image rows.
cols (int): Image cols.
crop_coords (tuple): Crop area coordinates in an original image `(x1, y1, x2, y2)`.
crop_height (int): Target height of cropped area after scaling.
crop_width (int): Target width of cropped area after scaling.
rows (int): Original image height.
cols (int): Original image width.

Returns:
tuple: A cropped bounding box `(x_min, y_min, x_max, y_max)`.
Expand Down Expand Up @@ -1771,17 +1771,12 @@ def keypoint_scale(keypoint, scale_x, scale_y):
return x * scale_x, y * scale_y, angle, scale * max(scale_x, scale_y)


def crop_keypoint_by_coords(keypoint, crop_coords, crop_height, crop_width, rows, cols): # skipcq: PYL-W0613
"""Crop a keypoint using the provided coordinates of bottom-left and top-right corners in pixels and the
required height and width of the crop.
def crop_keypoint_by_coords(keypoint, crop_coords): # skipcq: PYL-W0613
"""Crop a keypoint using the provided coordinates `crop_coords` of bottom-left and top-right corners in pixels

Args:
keypoint (tuple): A keypoint `(x, y, angle, scale)`.
crop_coords (tuple): Crop box coords `(x1, x2, y1, y2)`.
crop height (int): Crop height.
crop_width (int): Crop width.
rows (int): Image height.
cols (int): Image width.
crop_coords (tuple): Crop area coords `(x1, x2, y1, y2)`. Actually only `(x1,y1)` matters.

Returns:
A keypoint `(x, y, angle, scale)`.
Expand Down Expand Up @@ -1809,7 +1804,7 @@ def keypoint_random_crop(keypoint, crop_height, crop_width, h_start, w_start, ro

"""
crop_coords = get_random_crop_coords(rows, cols, crop_height, crop_width, h_start, w_start)
return crop_keypoint_by_coords(keypoint, crop_coords, crop_height, crop_width, rows, cols)
return crop_keypoint_by_coords(keypoint, crop_coords)


def keypoint_center_crop(keypoint, crop_height, crop_width, rows, cols):
Expand All @@ -1829,7 +1824,7 @@ def keypoint_center_crop(keypoint, crop_height, crop_width, rows, cols):

"""
crop_coords = get_center_crop_coords(rows, cols, crop_height, crop_width)
return crop_keypoint_by_coords(keypoint, crop_coords, crop_height, crop_width, rows, cols)
return crop_keypoint_by_coords(keypoint, crop_coords)


def py3round(number):
Expand Down
38 changes: 13 additions & 25 deletions albumentations/augmentations/transforms.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,7 @@ def apply_to_bbox(self, bbox, **params):
return F.bbox_crop(bbox, x_min=self.x_min, y_min=self.y_min, x_max=self.x_max, y_max=self.y_max, **params)

def apply_to_keypoint(self, keypoint, **params):
return F.crop_keypoint_by_coords(
keypoint,
crop_coords=(self.x_min, self.y_min, self.x_max, self.y_max),
crop_height=self.y_max - self.y_min,
crop_width=self.x_max - self.x_min,
rows=params["rows"],
cols=params["cols"],
)
return F.crop_keypoint_by_coords(keypoint, crop_coords=(self.x_min, self.y_min, self.x_max, self.y_max))

def get_transform_init_args_names(self):
return ("x_min", "y_min", "x_max", "y_max")
Expand Down Expand Up @@ -778,14 +771,7 @@ def apply_to_bbox(self, bbox, x_min=0, x_max=0, y_min=0, y_max=0, **params):
return F.bbox_crop(bbox, y_max - y_min, x_max - x_min, h_start, w_start, **params)

def apply_to_keypoint(self, keypoint, x_min=0, x_max=0, y_min=0, y_max=0, **params):
return F.crop_keypoint_by_coords(
keypoint,
crop_coords=(x_min, y_min, x_max, y_max),
crop_height=y_max - y_min,
crop_width=x_max - x_min,
rows=params["rows"],
cols=params["cols"],
)
return F.crop_keypoint_by_coords(keypoint, crop_coords=(x_min, y_min, x_max, y_max))

@property
def targets_as_params(self):
Expand Down Expand Up @@ -953,6 +939,8 @@ def get_transform_init_args_names(self):

class RandomSizedBBoxSafeCrop(DualTransform):
"""Crop a random part of the input and rescale it to some size without loss of bboxes.
Keypoints are processed but does not affect selection of crop region. So if you need to crop preserving
keypoints you have to pass fictive bbox enclosing keypoints.
Dipet marked this conversation as resolved.
Show resolved Hide resolved

Args:
height (int): height after crop and resize.
Expand All @@ -964,7 +952,7 @@ class RandomSizedBBoxSafeCrop(DualTransform):
p (float): probability of applying the transform. Default: 1.

Targets:
image, mask, bboxes
image, mask, bboxes, keypoints

Image types:
uint8, float32
Expand Down Expand Up @@ -1009,6 +997,13 @@ def get_params_dependent_on_targets(self, params):
def apply_to_bbox(self, bbox, crop_height=0, crop_width=0, h_start=0, w_start=0, rows=0, cols=0, **params):
return F.bbox_random_crop(bbox, crop_height, crop_width, h_start, w_start, rows, cols)

def apply_to_keypoint(self, keypoint, crop_height=0, crop_width=0, h_start=0, w_start=0, rows=0, cols=0, **params):
return F.keypoint_scale(
F.keypoint_random_crop(keypoint, crop_height, crop_width, h_start, w_start, rows, cols),
self.width / crop_width,
self.height / crop_height,
)

@property
def targets_as_params(self):
return ["image", "bboxes"]
Expand Down Expand Up @@ -1058,14 +1053,7 @@ def apply_to_bbox(self, bbox, x_min=0, x_max=0, y_min=0, y_max=0, **params):
)

def apply_to_keypoint(self, keypoint, x_min=0, x_max=0, y_min=0, y_max=0, **params):
return F.crop_keypoint_by_coords(
keypoint,
crop_coords=[x_min, y_min, x_max, y_max],
crop_height=y_max - y_min,
crop_width=x_max - x_min,
rows=params["rows"],
cols=params["cols"],
)
return F.crop_keypoint_by_coords(keypoint, crop_coords=[x_min, y_min, x_max, y_max])

@property
def targets_as_params(self):
Expand Down