Spaces:
Runtime error
Runtime error
| """ | |
| The FDF dataset expands bound boxes differently from what is used for CSE. | |
| """ | |
| import numpy as np | |
| def quadratic_bounding_box(x0, y0, width, height, imshape): | |
| # We assume that we can create a image that is quadratic without | |
| # minimizing any of the sides | |
| assert width <= min(imshape[:2]) | |
| assert height <= min(imshape[:2]) | |
| min_side = min(height, width) | |
| if height != width: | |
| side_diff = abs(height - width) | |
| # Want to extend the shortest side | |
| if min_side == height: | |
| # Vertical side | |
| height += side_diff | |
| if height > imshape[0]: | |
| # Take full frame, and shrink width | |
| y0 = 0 | |
| height = imshape[0] | |
| side_diff = abs(height - width) | |
| width -= side_diff | |
| x0 += side_diff // 2 | |
| else: | |
| y0 -= side_diff // 2 | |
| y0 = max(0, y0) | |
| else: | |
| # Horizontal side | |
| width += side_diff | |
| if width > imshape[1]: | |
| # Take full frame width, and shrink height | |
| x0 = 0 | |
| width = imshape[1] | |
| side_diff = abs(height - width) | |
| height -= side_diff | |
| y0 += side_diff // 2 | |
| else: | |
| x0 -= side_diff // 2 | |
| x0 = max(0, x0) | |
| # Check that bbox goes outside image | |
| x1 = x0 + width | |
| y1 = y0 + height | |
| if imshape[1] < x1: | |
| diff = x1 - imshape[1] | |
| x0 -= diff | |
| if imshape[0] < y1: | |
| diff = y1 - imshape[0] | |
| y0 -= diff | |
| assert x0 >= 0, "Bounding box outside image." | |
| assert y0 >= 0, "Bounding box outside image." | |
| assert x0 + width <= imshape[1], "Bounding box outside image." | |
| assert y0 + height <= imshape[0], "Bounding box outside image." | |
| return x0, y0, width, height | |
| def expand_bounding_box(bbox, percentage, imshape): | |
| orig_bbox = bbox.copy() | |
| x0, y0, x1, y1 = bbox | |
| width = x1 - x0 | |
| height = y1 - y0 | |
| x0, y0, width, height = quadratic_bounding_box( | |
| x0, y0, width, height, imshape) | |
| expanding_factor = int(max(height, width) * percentage) | |
| possible_max_expansion = [(imshape[0] - width) // 2, | |
| (imshape[1] - height) // 2, | |
| expanding_factor] | |
| expanding_factor = min(possible_max_expansion) | |
| # Expand height | |
| if expanding_factor > 0: | |
| y0 = y0 - expanding_factor | |
| y0 = max(0, y0) | |
| height += expanding_factor * 2 | |
| if height > imshape[0]: | |
| y0 -= (imshape[0] - height) | |
| height = imshape[0] | |
| if height + y0 > imshape[0]: | |
| y0 -= (height + y0 - imshape[0]) | |
| # Expand width | |
| x0 = x0 - expanding_factor | |
| x0 = max(0, x0) | |
| width += expanding_factor * 2 | |
| if width > imshape[1]: | |
| x0 -= (imshape[1] - width) | |
| width = imshape[1] | |
| if width + x0 > imshape[1]: | |
| x0 -= (width + x0 - imshape[1]) | |
| y1 = y0 + height | |
| x1 = x0 + width | |
| assert y0 >= 0, "Y0 is minus" | |
| assert height <= imshape[0], "Height is larger than image." | |
| assert x0 + width <= imshape[1] | |
| assert y0 + height <= imshape[0] | |
| assert width == height, "HEIGHT IS NOT EQUAL WIDTH!!" | |
| assert x0 >= 0, "Y0 is minus" | |
| assert width <= imshape[1], "Height is larger than image." | |
| # Check that original bbox is within new | |
| x0_o, y0_o, x1_o, y1_o = orig_bbox | |
| assert x0 <= x0_o, f"New bbox is outisde of original. O:{x0_o}, N: {x0}" | |
| assert x1 >= x1_o, f"New bbox is outisde of original. O:{x1_o}, N: {x1}" | |
| assert y0 <= y0_o, f"New bbox is outisde of original. O:{y0_o}, N: {y0}" | |
| assert y1 >= y1_o, f"New bbox is outisde of original. O:{y1_o}, N: {y1}" | |
| x0, y0, width, height = [int(_) for _ in [x0, y0, width, height]] | |
| x1 = x0 + width | |
| y1 = y0 + height | |
| return np.array([x0, y0, x1, y1]) | |
| def is_keypoint_within_bbox(x0, y0, x1, y1, keypoint): | |
| keypoint = keypoint[:, :3] # only nose + eyes are relevant | |
| kp_X = keypoint[0, :] | |
| kp_Y = keypoint[1, :] | |
| within_X = np.all(kp_X >= x0) and np.all(kp_X <= x1) | |
| within_Y = np.all(kp_Y >= y0) and np.all(kp_Y <= y1) | |
| return within_X and within_Y | |
| def expand_bbox_simple(bbox, percentage): | |
| x0, y0, x1, y1 = bbox.astype(float) | |
| width = x1 - x0 | |
| height = y1 - y0 | |
| x_c = int(x0) + width // 2 | |
| y_c = int(y0) + height // 2 | |
| avg_size = max(width, height) | |
| new_width = avg_size * (1 + percentage) | |
| x0 = x_c - new_width // 2 | |
| y0 = y_c - new_width // 2 | |
| x1 = x_c + new_width // 2 | |
| y1 = y_c + new_width // 2 | |
| return np.array([x0, y0, x1, y1]).astype(int) | |
| def pad_image(im, bbox, pad_value): | |
| x0, y0, x1, y1 = bbox | |
| if x0 < 0: | |
| pad_im = np.zeros((im.shape[0], abs(x0), im.shape[2]), | |
| dtype=np.uint8) + pad_value | |
| im = np.concatenate((pad_im, im), axis=1) | |
| x1 += abs(x0) | |
| x0 = 0 | |
| if y0 < 0: | |
| pad_im = np.zeros((abs(y0), im.shape[1], im.shape[2]), | |
| dtype=np.uint8) + pad_value | |
| im = np.concatenate((pad_im, im), axis=0) | |
| y1 += abs(y0) | |
| y0 = 0 | |
| if x1 >= im.shape[1]: | |
| pad_im = np.zeros( | |
| (im.shape[0], x1 - im.shape[1] + 1, im.shape[2]), | |
| dtype=np.uint8) + pad_value | |
| im = np.concatenate((im, pad_im), axis=1) | |
| if y1 >= im.shape[0]: | |
| pad_im = np.zeros( | |
| (y1 - im.shape[0] + 1, im.shape[1], im.shape[2]), | |
| dtype=np.uint8) + pad_value | |
| im = np.concatenate((im, pad_im), axis=0) | |
| return im[y0:y1, x0:x1] | |
| def clip_box(bbox, im): | |
| bbox[0] = max(0, bbox[0]) | |
| bbox[1] = max(0, bbox[1]) | |
| bbox[2] = min(im.shape[1] - 1, bbox[2]) | |
| bbox[3] = min(im.shape[0] - 1, bbox[3]) | |
| return bbox | |
| def cut_face(im, bbox, simple_expand=False, pad_value=0, pad_im=True): | |
| outside_im = (bbox < 0).any() or bbox[2] > im.shape[1] or bbox[3] > im.shape[0] | |
| if simple_expand or (outside_im and pad_im): | |
| return pad_image(im, bbox, pad_value) | |
| bbox = clip_box(bbox, im) | |
| x0, y0, x1, y1 = bbox | |
| return im[y0:y1, x0:x1] | |
| def expand_bbox( | |
| bbox_ltrb, imshape, simple_expand, default_to_simple=False, | |
| expansion_factor=0.35): | |
| assert bbox_ltrb.shape == (4,), f"BBox shape was: {bbox_ltrb.shape}" | |
| bbox = bbox_ltrb.astype(float) | |
| # FDF256 uses simple expand with ratio 0.4 | |
| if simple_expand: | |
| return expand_bbox_simple(bbox, 0.4) | |
| try: | |
| return expand_bounding_box(bbox, expansion_factor, imshape) | |
| except AssertionError: | |
| return expand_bbox_simple(bbox, expansion_factor * 2) | |