Spaces:
No application file
No application file
import math | |
from typing import Union, Tuple | |
from numpy import ndarray | |
import numpy as np | |
def cal_start_end_point(big: float, small: float, center: float = None): | |
if center is None: | |
center = big / 2 | |
if center < small / 2: | |
center = small / 2 | |
if center > (big - small / 2): | |
center = big - small / 2 | |
start = center - small / 2 | |
end = center + small / 2 | |
return (start, end) | |
def cal_small_bbox_coord_of_big_bbox( | |
bigbbox_width, | |
bigbbox_height, | |
smallbbox_width, | |
smallbbox_height, | |
center_width: float = None, | |
center_height: float = None, | |
need_round2even=False, | |
): | |
"""只有宽高信息,按中心crop计算小矩形在大矩形的剪辑坐标 | |
Args: | |
bigbbox_width (float): _description_ | |
bigbbox_height (float): _description_ | |
smallbbox_width (float): _description_ | |
smallbbox_height (float): _description_ | |
Returns: | |
(float, float, float, float): (x1, y1, x2, y2) 在大矩形中的剪辑位置 | |
""" | |
x1, x2 = cal_start_end_point(bigbbox_width, smallbbox_width, center=center_width) | |
y1, y2 = cal_start_end_point(bigbbox_height, smallbbox_height, center=center_height) | |
# x1 = (bigbbox_width - smallbbox_width) / 2 | |
# y1 = (bigbbox_height - smallbbox_height) / 2 | |
# x2 = (bigbbox_width + smallbbox_width) / 2 | |
# y2 = (bigbbox_height + smallbbox_height) / 2 | |
if need_round2even: | |
x1, y1, x2, y2 = round_up_coord_to_even(x1, y1, x2, y2) | |
return (x1, y1, x2, y2) | |
def round_up_to_even(num): | |
return math.floor(num / 2.0) * 2 | |
def round_up_coord_to_even(x1, y1, x2, y2): | |
x2 = x1 + round_up_to_even(x2 - x1) | |
y2 = y1 + round_up_to_even(y2 - y1) | |
return (x1, y1, x2, y2) | |
def cal_crop_coord( | |
width, | |
height, | |
target_width_height_ratio, | |
restricted_bbox=None, | |
need_round2even=False, | |
): | |
""" | |
(TODO): 当前只考虑crop,不考虑补全; | |
(TODO): 当前只考虑视频尺寸比目标尺寸大 | |
Args: | |
width (float): 原视频的宽 | |
height (float): 原视频的高 | |
target_width (float): 目标视频的宽 | |
target_height (float): 目标视频的高 | |
restricted_bbox ((float, float, float, float), optional): (x1, y1, x2, y2). Defaults to None. | |
Returns: | |
(float, float, float, float): (x1, y1, x2, y2) 在原视频中的剪辑位置 | |
""" | |
if restricted_bbox is None: | |
target_width, target_height = cal_target_width_height_by_ratio( | |
width=width, | |
height=height, | |
target_width_height_ratio=target_width_height_ratio, | |
) | |
crop_bbox = cal_small_bbox_coord_of_big_bbox( | |
width, height, target_width, target_height | |
) | |
else: | |
r_width = restricted_bbox[2] - restricted_bbox[0] | |
r_height = restricted_bbox[3] - restricted_bbox[1] | |
target_width, target_height = cal_target_width_height_by_ratio( | |
width=r_width, | |
height=r_height, | |
target_width_height_ratio=target_width_height_ratio, | |
) | |
crop_bbox = cal_small_bbox_coord_of_big_bbox( | |
r_width, r_height, target_width, target_height | |
) | |
crop_bbox = ( | |
crop_bbox[0] + restricted_bbox[0], | |
crop_bbox[1] + restricted_bbox[1], | |
crop_bbox[2] + restricted_bbox[0], | |
crop_bbox[3] + restricted_bbox[1], | |
) | |
if need_round2even: | |
crop_bbox = round_up_coord_to_even(*crop_bbox) | |
return crop_bbox | |
def cal_target_width_height_by_ratio( | |
width, height, target_width_height_ratio, need_round2even=False | |
): | |
"""针对原视频的宽、高和目标视频宽高比,计算合适的宽、高 | |
Args: | |
width (float): 原视频的宽 | |
height (float): 原视频的高 | |
target_width_height_ratio (float): 目标视频宽高比 | |
Returns: | |
target_width (float)): 目标宽 | |
target_height (float): 目标高 | |
""" | |
width_height_ratio = width / height | |
if width_height_ratio >= target_width_height_ratio: | |
target_width = height * target_width_height_ratio | |
target_height = height | |
else: | |
target_width = width | |
target_height = width / target_width_height_ratio | |
if need_round2even: | |
target_height = round_up_to_even(target_height) | |
target_width = round_up_to_even(target_width) | |
return target_width, target_height | |
def cal_target_width_height( | |
target_width=None, | |
target_height=None, | |
target_width_height_ratio=None, | |
need_even=True, | |
): | |
if target_width and not target_height and target_width_height_ratio: | |
target_height = int(target_width / target_width_height_ratio) | |
if need_even: | |
target_height = round_up_to_even(target_height) | |
if target_height and not target_width and target_width_height_ratio: | |
target_width = int(target_height * target_width_height_ratio) | |
if need_even: | |
target_width = round_up_to_even(target_width) | |
if target_height and target_width: | |
target_width_height_ratio = target_width / target_height | |
return target_width, target_height, target_width_height_ratio | |
def find_outlier(grid: ndarray) -> ndarray: | |
"""find outlier coordinary out of grid | |
Args: | |
grid (ndarray): 2xHxW | |
Returns: | |
mask: ndarray, HxW, 1 for coordinary in grid, 0 for outlier | |
""" | |
c, h, w = grid.shape | |
mask = np.zeros((h, w)) | |
for i, j in zip(range(h), range(w)): | |
x = int(grid[0, i, j]) | |
y = int(grid[1, i, j]) | |
if x < h and y < w: | |
mask[x, y] = 1 | |
return mask | |