deep_privacy2 / dp2 /detection /box_utils_fdf.py
haakohu's picture
fix
44539fc
raw
history blame contribute delete
No virus
6.7 kB
"""
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)