Spaces:
Runtime error
Runtime error
import numpy as np | |
def expand_bbox_to_ratio(bbox, imshape, target_aspect_ratio): | |
x0, y0, x1, y1 = [int(_) for _ in bbox] | |
h, w = y1 - y0, x1 - x0 | |
cur_ratio = h / w | |
if cur_ratio == target_aspect_ratio: | |
return [x0, y0, x1, y1] | |
if cur_ratio < target_aspect_ratio: | |
target_height = int(w*target_aspect_ratio) | |
y0, y1 = expand_axis(y0, y1, target_height, imshape[0]) | |
else: | |
target_width = int(h/target_aspect_ratio) | |
x0, x1 = expand_axis(x0, x1, target_width, imshape[1]) | |
return x0, y0, x1, y1 | |
def expand_axis(start, end, target_width, limit): | |
# Can return a bbox outside of limit | |
cur_width = end - start | |
start = start - (target_width-cur_width)//2 | |
end = end + (target_width-cur_width)//2 | |
if end - start != target_width: | |
end += 1 | |
assert end - start == target_width | |
if start < 0 and end > limit: | |
return start, end | |
if start < 0 and end < limit: | |
to_shift = min(0 - start, limit - end) | |
start += to_shift | |
end += to_shift | |
if end > limit and start > 0: | |
to_shift = min(end - limit, start) | |
end -= to_shift | |
start -= to_shift | |
assert end - start == target_width | |
return start, end | |
def expand_box(bbox, imshape, mask, percentage_background: float): | |
assert isinstance(bbox[0], int) | |
assert 0 < percentage_background < 1 | |
# Percentage in S | |
mask_pixels = mask.long().sum().cpu() | |
total_pixels = (bbox[2] - bbox[0]) * (bbox[3] - bbox[1]) | |
percentage_mask = mask_pixels / total_pixels | |
if (1 - percentage_mask) > percentage_background: | |
return bbox | |
target_pixels = mask_pixels / (1 - percentage_background) | |
x0, y0, x1, y1 = bbox | |
H = y1 - y0 | |
W = x1 - x0 | |
p = np.sqrt(target_pixels/(H*W)) | |
target_width = int(np.ceil(p * W)) | |
target_height = int(np.ceil(p * H)) | |
x0, x1 = expand_axis(x0, x1, target_width, imshape[1]) | |
y0, y1 = expand_axis(y0, y1, target_height, imshape[0]) | |
return [x0, y0, x1, y1] | |
def expand_axises_by_percentage(bbox_XYXY, imshape, percentage): | |
x0, y0, x1, y1 = bbox_XYXY | |
H = y1 - y0 | |
W = x1 - x0 | |
expansion = int(((H*W)**0.5) * percentage) | |
new_width = W + expansion | |
new_height = H + expansion | |
x0, x1 = expand_axis(x0, x1, min(new_width, imshape[1]), imshape[1]) | |
y0, y1 = expand_axis(y0, y1, min(new_height, imshape[0]), imshape[0]) | |
return [x0, y0, x1, y1] | |
def get_expanded_bbox( | |
bbox_XYXY, | |
imshape, | |
mask, | |
percentage_background: float, | |
axis_minimum_expansion: float, | |
target_aspect_ratio: float): | |
bbox_XYXY = bbox_XYXY.long().cpu().numpy().tolist() | |
# Expand each axis of the bounding box by a minimum percentage | |
bbox_XYXY = expand_axises_by_percentage(bbox_XYXY, imshape, axis_minimum_expansion) | |
# Find the minimum bbox with the aspect ratio. Can be outside of imshape | |
bbox_XYXY = expand_bbox_to_ratio(bbox_XYXY, imshape, target_aspect_ratio) | |
# Expands square box such that X% of the bbox is background | |
bbox_XYXY = expand_box(bbox_XYXY, imshape, mask, percentage_background) | |
assert isinstance(bbox_XYXY[0], (int, np.int64)) | |
return bbox_XYXY | |
def include_box(bbox, minimum_area, aspect_ratio_range, min_bbox_ratio_inside, imshape): | |
def area_inside_ratio(bbox, imshape): | |
area = (bbox[2] - bbox[0]) * (bbox[3] - bbox[1]) | |
area_inside = (min(bbox[2], imshape[1]) - max(0, bbox[0])) * (min(imshape[0], bbox[3]) - max(0, bbox[1])) | |
return area_inside / area | |
ratio = (bbox[3] - bbox[1]) / (bbox[2] - bbox[0]) | |
area = (bbox[3] - bbox[1]) * (bbox[2] - bbox[0]) | |
if area_inside_ratio(bbox, imshape) < min_bbox_ratio_inside: | |
return False | |
if ratio <= aspect_ratio_range[0] or ratio >= aspect_ratio_range[1] or area < minimum_area: | |
return False | |
return True | |