Spaces:
Runtime error
Runtime error
File size: 6,696 Bytes
97a6728 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
"""
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)
|