File size: 3,293 Bytes
d8b3f49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
# """
# Parts of the code are taken or adapted from
# https://github.com/mkocabas/EpipolarPose/blob/master/lib/utils/img_utils.py
# """

from typing import Tuple

import cv2
import numpy as np


def generate_image_patch_cv2_resize(
    img: np.array,
    c_x: float,
    c_y: float,
    bb_width: float,
    bb_height: float,
    patch_width: float,
    patch_height: float,
    do_flip: bool,
    scale: float,
    rot: float,
) -> Tuple[np.array, np.array]:
    """
    Crop and resize the input image with zero padding when needed
    """
    assert bb_width == bb_height

    img_height, img_width, img_channels = img.shape
    if do_flip:
        img = img[:, ::-1, :]
        c_x = img_width - c_x - 1

    # Calculate scaled dimensions
    scaled_size = max(bb_width, bb_height) * scale

    # Calculate desired crop coordinates without clamping
    half_size = scaled_size / 2
    x1_desired = c_x - half_size
    y1_desired = c_y - half_size
    x2_desired = c_x + half_size
    y2_desired = c_y + half_size

    # Calculate padding amounts
    pad_left = max(0, -x1_desired)
    pad_right = max(0, x2_desired - img_width)
    pad_top = max(0, -y1_desired)
    pad_bottom = max(0, y2_desired - img_height)

    # Create padded image
    padded_height = img_height + int(pad_top + pad_bottom)
    padded_width = img_width + int(pad_left + pad_right)
    if img_channels == 4:
        padded_img = np.zeros((padded_height, padded_width, 4), dtype=img.dtype)
    else:
        padded_img = np.zeros((padded_height, padded_width, img_channels), dtype=img.dtype)

    # Copy original image into padded image
    padded_img[
        int(pad_top) : int(pad_top + img_height),
        int(pad_left) : int(pad_left + img_width),
    ] = img

    # Calculate crop coordinates in padded image
    x1 = max(0, int(x1_desired + pad_left))
    y1 = max(0, int(y1_desired + pad_top))
    x2 = x1 + int(scaled_size)
    y2 = y1 + int(scaled_size)

    # Crop the square region
    cropped = padded_img[y1:y2, x1:x2]

    # Apply rotation if needed
    if rot != 0:
        center = (scaled_size / 2, scaled_size / 2)
        rot_mat = cv2.getRotationMatrix2D(center, rot, 1.0)
        cropped = cv2.warpAffine(cropped, rot_mat, (int(scaled_size), int(scaled_size)))

    # Resize to target size
    if img_channels == 4:
        rgb = cv2.resize(
            cropped[:, :, :3],
            (int(patch_width), int(patch_height)),
            interpolation=cv2.INTER_LINEAR,
        )
        alpha = cv2.resize(
            cropped[:, :, 3],
            (int(patch_width), int(patch_height)),
            interpolation=cv2.INTER_LINEAR,
        )
        img_patch = np.dstack((rgb, alpha))
    else:
        img_patch = cv2.resize(
            cropped,
            (int(patch_width), int(patch_height)),
            interpolation=cv2.INTER_LINEAR,
        )

    return img_patch


def convert_cvimg_to_tensor(cvimg: np.array):
    """
    Convert image from HWC to CHW format.
    Args:
        cvimg (np.array): Image of shape (H, W, 3) as loaded by OpenCV.
    Returns:
        np.array: Output image of shape (3, H, W).
    """
    # from h,w,c(OpenCV) to c,h,w
    img = cvimg.copy()
    img = np.transpose(img, (2, 0, 1))
    # from int to float
    img = img.astype(np.float32)
    return img