File size: 2,722 Bytes
7826761
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from __future__ import annotations

import cv2
import numpy as np


def create_default_face_bbox(image: np.ndarray, scale: float = 0.9) -> np.ndarray:
    img_h, img_w = image.shape[:2]
    box_size = min(img_w, img_h) * float(scale)
    cx = (img_w - 1) * 0.5
    cy = (img_h - 1) * 0.5
    half = box_size * 0.5
    return np.array([cx - half, cy - half, cx + half, cy + half], dtype=np.float32)


def enlarge_bbox(bbox: np.ndarray, scale: float) -> np.ndarray:
    bbox = np.asarray(bbox, dtype=np.float32)
    center = np.array([(bbox[0] + bbox[2]) * 0.5, (bbox[1] + bbox[3]) * 0.5], dtype=np.float32)
    size = np.array([bbox[2] - bbox[0], bbox[3] - bbox[1]], dtype=np.float32) * float(scale)
    half = size * 0.5
    return np.array(
        [center[0] - half[0], center[1] - half[1], center[0] + half[0], center[1] + half[1]],
        dtype=np.float32,
    )


def make_bbox_square(bbox: np.ndarray) -> np.ndarray:
    x0, y0, x1, y1 = np.asarray(bbox, dtype=np.float32)
    size = int(round(max(x1 - x0, y1 - y0)))
    cx = (x0 + x1) * 0.5
    cy = (y0 + y1) * 0.5
    new_x0 = int(round(cx - size * 0.5))
    new_y0 = int(round(cy - size * 0.5))
    new_x1 = new_x0 + size
    new_y1 = new_y0 + size
    return np.array([new_x0, new_y0, new_x1, new_y1], dtype=np.int32)


def calc_crop_pad_info(

    bbox: np.ndarray,

    img_width: int,

    img_height: int,

) -> tuple[tuple[int, int, int, int], tuple[int, int, int, int]]:
    x0, y0, x1, y1 = np.asarray(bbox, dtype=np.int32)
    pad_left = max(0, -x0)
    pad_top = max(0, -y0)
    pad_right = max(0, x1 - img_width)
    pad_bottom = max(0, y1 - img_height)
    crop_left = max(0, x0)
    crop_top = max(0, y0)
    crop_right = min(img_width, x1)
    crop_bottom = min(img_height, y1)
    return (pad_left, pad_top, pad_right, pad_bottom), (crop_left, crop_top, crop_right, crop_bottom)


def crop_and_resize_image(

    image: np.ndarray,

    bbox: np.ndarray,

    target_size: int,

) -> tuple[np.ndarray, np.ndarray]:
    img_h, img_w = image.shape[:2]
    bbox = np.asarray(bbox, dtype=np.float32).copy()
    pad_info, crop_info = calc_crop_pad_info(bbox, img_w, img_h)
    bbox_w = int(round(float(bbox[2] - bbox[0])))
    bbox_h = int(round(float(bbox[3] - bbox[1])))

    x0, y0, x1, y1 = crop_info
    cropped = image[y0:y1, x0:x1]
    if sum(pad_info) > 0:
        padded = np.zeros((bbox_h, bbox_w, 3), dtype=image.dtype)
        padded[pad_info[1]:(bbox_h - pad_info[3]), pad_info[0]:(bbox_w - pad_info[2])] = cropped
        cropped = padded

    resized = cv2.resize(cropped, (int(target_size), int(target_size)), interpolation=cv2.INTER_LINEAR)
    return resized, bbox