File size: 5,624 Bytes
a57c6eb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
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