Skip to content

resize

data.transform.resize

RESAMPLE_TORCH module-attribute

RESAMPLE_TORCH = {'nearest': 'nearest-exact', 'bilinear': 'bilinear', 'bicubic': 'bicubic'}

RESAMPLE_PIL module-attribute

RESAMPLE_PIL = {'nearest': NEAREST, 'bilinear': BILINEAR, 'bicubic': BICUBIC}

ImageSizeType module-attribute

ImageSizeType = Sequence[int]

Resizer

Resizer(size: Optional[Union[ImageSizeType, int]] = None, scale: Optional[Union[int, float]] = None, area_sqrt: Optional[Union[int, float]] = None, max_size: Optional[Union[ImageSizeType, int]] = None, round: Optional[int] = None, round_type: str = 'round', resampling: str = 'bilinear', image_only: bool = False, use_cv2_for_numpy: bool = True)

Module for resizing PIL, torch, numpy images Resizer의 작동 방식은 다음과 같습니다. 1. target size 계산 2. target size 미세 조정 3. 데이터에 resize 적용

Args에 따라 1, 2번의 작동 방식이 달라집니다. 1. target size 계산 - resize 될 target size를 계산합니다. - target size는 4개의 args에 영향을 받을 수 있습니다. (size, scale, area_sqrt, max_size) 하나의 Resizer는 4개중 하나의 args만 사용할 수 있으며, 2개 이상의 args가 None이 아닐시 error를 raise 합니다. 1-1. size: image를 size로 resize 합니다. aspect ratio가 변경될 수 있습니다. 1-2. scale: image를 scale배로 늘리거나 줄입니다. aspect ratio는 유지됩니다. 1-3. area_sqrt: image의 면적이 area_sqrt^2이 되도록 이미지를 늘리거나 줄입니다. aspect ratio는 유지됩니다. 1-4. max_size: image의 size가 max_size보다 클 경우 max_size로 resize 합니다. aspect ratio를 유지하기 위해, width/height중 더 많이 줄어야 하는 비율에 맞추어 전체를 resize합니다.

  1. target size 미세 조정
  2. resize된 이미지가 특정 값의 배수가 되도록 target size를 미세 조정 합니다. model의 입력으로 넣을 때, image size가 특정 값의 배수가 되어야 하기 때문에 필요합니다.
    1. target size 계산의 size parameter와 함께 사용할 수 없습니다. (고정 size이기 때문)
  3. target size 미세 조정은 총 2개의 args에 영향을 받을 수 있습니다. (round, round_type) round가 None이면 미세 조정을 하지 않습니다, round_type에 따라 다른 방식의 미세 조정을 적용합니다. 2-1. round: 미세 조정시 반올림합니다. (target size보다 작거나 크거나 같습니다.) 2-2. floor: 미세 조정시 내림합니다. (target size보다 작거나 같습니다.) 2-3. ceil: 미세 조정시 올림합니다. (target size보다 크거나 같습니다.)
  4. 미세 조정된 target_size의 width혹은 height가 0이 될 경우, round 값으로 변경해줍니다. (ex. size=(3, 3), round=8이면 round_type에 상관없이 size=(8, 8)이 됨.)

Parameters:

  • size (Optional[Union[ImageSizeType, int]], default: None ) –

    target image size. Defaults to None.

  • scale (Optional[Union[int, float]], default: None ) –

    target image scale. Defaults to None.

  • area_sqrt (Optional[Union[int, float]], default: None ) –

    target image sqrt area. Defaults to None.

  • max_size (Optional[Union[ImageSizeType, int]], default: None ) –

    target maximum image size. Defaults to None.

  • round (Optional[int], default: None ) –

    round image size. Defaults to None.

  • round_type (Optional[str], default: 'round' ) –

    type of round image. One of ["round", "floor", "ceil"]. Defaults to "round".

  • resampling (str, default: 'bilinear' ) –

    One of ["nearest", "bilinear", "bicubic"]. Defaults to "bilinear".

  • image_only (bool, default: False ) –

    to resize image only. Defaults to False.

  • use_cv2_for_numpy (bool, default: True ) –

    use cv2 instead of PIL for faster numpy array image resizing. Defaults to True.

Raises:

  • ResizerParameterValueError

    target size parameter가 2개 이상 들어오면 error를 raise 합니다. round_type이 ["round", "floor", "ceil"]안에 없으면 error를 raise 합니다. size와 미세조정 parameter가 함께 들어오면 error를 raise 합니다.

Source code in SaigeToolkit/data/transform/resize.py
def __init__(
    self,
    size: Optional[Union[ImageSizeType, int]] = None,
    scale: Optional[Union[int, float]] = None,
    area_sqrt: Optional[Union[int, float]] = None,
    max_size: Optional[Union[ImageSizeType, int]] = None,
    round: Optional[int] = None,
    round_type: str = "round",
    resampling: str = "bilinear",
    image_only: bool = False,
    use_cv2_for_numpy: bool = True,
) -> None:
    """Module for resizing PIL, torch, numpy images
    Resizer의 작동 방식은 다음과 같습니다.
    1. target size 계산
    2. target size 미세 조정
    3. 데이터에 resize 적용

    Args에 따라 1, 2번의 작동 방식이 달라집니다.
    1. target size 계산
    - resize 될 target size를 계산합니다.
    - target size는 4개의 args에 영향을 받을 수 있습니다. (size, scale, area_sqrt, max_size)
      하나의 Resizer는 4개중 하나의 args만 사용할 수 있으며, 2개 이상의 args가 None이 아닐시 error를 raise 합니다.
        1-1. size: image를 size로 resize 합니다. aspect ratio가 변경될 수 있습니다.
        1-2. scale: image를 scale배로 늘리거나 줄입니다. aspect ratio는 유지됩니다.
        1-3. area_sqrt: image의 면적이 area_sqrt^2이 되도록 이미지를 늘리거나 줄입니다. aspect ratio는 유지됩니다.
        1-4. max_size: image의 size가 max_size보다 클 경우 max_size로 resize 합니다.
                        aspect ratio를 유지하기 위해, width/height중 더 많이 줄어야 하는 비율에 맞추어 전체를 resize합니다.

    2. target size 미세 조정
    - resize된 이미지가 특정 값의 배수가 되도록 target size를 미세 조정 합니다.
      model의 입력으로 넣을 때, image size가 특정 값의 배수가 되어야 하기 때문에 필요합니다.
    - 1. target size 계산의 size parameter와 함께 사용할 수 없습니다. (고정 size이기 때문)
    - target size 미세 조정은 총 2개의 args에 영향을 받을 수 있습니다. (round, round_type)
      round가 None이면 미세 조정을 하지 않습니다, round_type에 따라 다른 방식의 미세 조정을 적용합니다.
        2-1. round: 미세 조정시 반올림합니다. (target size보다 작거나 크거나 같습니다.)
        2-2. floor: 미세 조정시 내림합니다. (target size보다 작거나 같습니다.)
        2-3. ceil: 미세 조정시 올림합니다. (target size보다 크거나 같습니다.)
    - 미세 조정된 target_size의 width혹은 height가 0이 될 경우, round 값으로 변경해줍니다.
      (ex. size=(3, 3), round=8이면 round_type에 상관없이 size=(8, 8)이 됨.)

    Args:
        size (Optional[Union[ImageSizeType, int]], optional): target image size. Defaults to None.
        scale (Optional[Union[int, float]], optional): target image scale. Defaults to None.
        area_sqrt (Optional[Union[int, float]], optional): target image sqrt area. Defaults to None.
        max_size (Optional[Union[ImageSizeType, int]], optional): target maximum image size. Defaults to None.
        round (Optional[int], optional): round image size. Defaults to None.
        round_type (Optional[str], optional): type of round image. One of ["round", "floor", "ceil"]. Defaults to "round".
        resampling (str): One of ["nearest", "bilinear", "bicubic"]. Defaults to "bilinear".
        image_only (bool): to resize image only. Defaults to False.
        use_cv2_for_numpy (bool): use cv2 instead of PIL for faster numpy array image resizing. Defaults to True.

    Raises:
        ResizerParameterValueError: target size parameter가 2개 이상 들어오면 error를 raise 합니다.
                                    round_type이 ["round", "floor", "ceil"]안에 없으면 error를 raise 합니다.
                                    size와 미세조정 parameter가 함께 들어오면 error를 raise 합니다.
    """

    self._check_parameter(
        size=size,
        scale=scale,
        area_sqrt=area_sqrt,
        max_size=max_size,
        round=round,
        round_type=round_type,
    )

    size = self._preprocess_size(size)
    max_size = self._preprocess_size(max_size)

    if scale == 1:
        scale = None

    self.size = size
    self.scale = scale
    self.area_sqrt = area_sqrt
    self.max_size = max_size
    self.round = round
    self.round_type = round_type

    if resampling not in RESAMPLE_PIL or resampling not in RESAMPLE_TORCH:
        raise ValueError
    self.resampling = resampling

    self.image_only = image_only
    self.use_cv2_for_numpy = use_cv2_for_numpy

round_functions class-attribute instance-attribute

round_functions = {'round': round, 'floor': floor, 'ceil': ceil}

size instance-attribute

size = size

scale instance-attribute

scale = scale

area_sqrt instance-attribute

area_sqrt = area_sqrt

max_size instance-attribute

max_size = max_size

round instance-attribute

round = round

round_type instance-attribute

round_type = round_type

resampling instance-attribute

resampling = resampling

image_only instance-attribute

image_only = image_only

use_cv2_for_numpy instance-attribute

use_cv2_for_numpy = use_cv2_for_numpy

__call__

__call__(return_revert_params: bool = False, **data) -> Union[Dict, Tuple[Dict, Dict]]
Source code in SaigeToolkit/data/transform/resize.py
def __call__(self, return_revert_params: bool = False, **data) -> Union[Dict, Tuple[Dict, Dict]]:
    input_size = self.compute_input_size(data)
    target_size = self.compute_target_size(input_size)
    data = self.apply_with_params(
        data=data,
        input_size=input_size,
        target_size=target_size,
        resampling=self.resampling,
        image_only=self.image_only,
        use_cv2_for_numpy=self.use_cv2_for_numpy,
    )

    if return_revert_params:
        revert_params = {
            "image_size_before_resize": input_size,
            "image_size_after_resize": target_size,
        }
        return_value = (data, revert_params)
    else:
        return_value = data

    return return_value

compute_input_size staticmethod

compute_input_size(data: Dict) -> ImageSizeType

target size를 계산하기 위해 input size를 가져옵니다. Note: data에 image 혹은 mask data는 있다고 가정하며, 둘의 size는 같다고 가정합니다.

Source code in SaigeToolkit/data/transform/resize.py
@staticmethod
def compute_input_size(data: Dict) -> ImageSizeType:
    """target size를 계산하기 위해 input size를 가져옵니다.
    Note: data에 image 혹은 mask data는 있다고 가정하며, 둘의 size는 같다고 가정합니다.
    """
    if "image" in data:
        multipage = isinstance(data["image"], List)
        input_size = read_image_size(data["image"][0] if multipage else data["image"])
    elif "mask" in data:
        input_size = read_image_size(data["mask"])
    else:
        raise NotImplementedError

    return input_size

compute_target_size

compute_target_size(input_size: Union[ImageSizeType, ndarray]) -> ImageSizeType

compute resize target size from input image size

Parameters:

Returns:

Source code in SaigeToolkit/data/transform/resize.py
def compute_target_size(self, input_size: Union[ImageSizeType, np.ndarray]) -> ImageSizeType:
    """compute resize target size from input image size

    Args:
        input_size (Union[ImageSizeType, np.ndarray]): (width, height)

    Returns:
        ImageSizeType: (width, height)
    """
    return self._compute_target_size(
        input_size=input_size,
        size=self.size,
        scale=self.scale,
        area_sqrt=self.area_sqrt,
        max_size=self.max_size,
        round=self.round,
        round_type=self.round_type,
    )

apply_with_params classmethod

apply_with_params(data: Dict, input_size: ImageSizeType, target_size: ImageSizeType, resampling: str, image_only: bool, use_cv2_for_numpy: bool = True) -> Dict
Source code in SaigeToolkit/data/transform/resize.py
@classmethod
def apply_with_params(
    cls,
    data: Dict,
    input_size: ImageSizeType,
    target_size: ImageSizeType,
    resampling: str,
    image_only: bool,
    use_cv2_for_numpy: bool = True,
) -> Dict:
    if "image" in data:
        data["image"] = cls.apply_to_image(
            image=data["image"],
            target_size=target_size,
            resampling=resampling,
            use_cv2_for_numpy=use_cv2_for_numpy,
        )

    if image_only:
        return data

    if "mask" in data:
        data["mask"] = cls.apply_to_mask(mask=data["mask"], target_size=target_size)

    if "bboxes" in data:
        data["bboxes"] = cls.apply_to_bboxes(
            bboxes=data["bboxes"], input_size=input_size, target_size=target_size
        )

    if "polygons" in data:
        data["polygons"] = cls.apply_to_polygons(
            polygons=data["polygons"], input_size=input_size, target_size=target_size
        )

    return data

apply_to_image staticmethod

apply_to_image(image, target_size: ImageSizeType, resampling: str, use_cv2_for_numpy: bool = True)
Source code in SaigeToolkit/data/transform/resize.py
@staticmethod
def apply_to_image(
    image,
    target_size: ImageSizeType,
    resampling: str,
    use_cv2_for_numpy: bool = True,
):
    multipage = isinstance(image, List)
    input_size = read_image_size(image[0] if multipage else image)
    if list(target_size) != list(input_size):
        if multipage:
            image = [
                resize_image(
                    image_, target_size, resampling=resampling, use_cv2_for_numpy=use_cv2_for_numpy
                )
                for image_ in image
            ]
        else:
            image = resize_image(
                image, target_size, resampling=resampling, use_cv2_for_numpy=use_cv2_for_numpy
            )

    return image

apply_to_mask staticmethod

apply_to_mask(mask, target_size: ImageSizeType)
Source code in SaigeToolkit/data/transform/resize.py
@staticmethod
def apply_to_mask(mask, target_size: ImageSizeType):
    input_size = read_image_size(mask)
    if list(target_size) != list(input_size):
        mask = resize_mask(mask, target_size)
    return mask

apply_to_bboxes staticmethod

apply_to_bboxes(bboxes, input_size: ImageSizeType, target_size: ImageSizeType)
Source code in SaigeToolkit/data/transform/resize.py
@staticmethod
def apply_to_bboxes(bboxes, input_size: ImageSizeType, target_size: ImageSizeType):
    bboxes = resize_box(bboxes, input_size, target_size[0], target_size[1])
    return bboxes

apply_to_polygons staticmethod

apply_to_polygons(polygons, input_size: ImageSizeType, target_size: ImageSizeType)
Source code in SaigeToolkit/data/transform/resize.py
@staticmethod
def apply_to_polygons(polygons, input_size: ImageSizeType, target_size: ImageSizeType):
    polygons = resize_polygon(
        polygons=polygons,
        image_size=input_size,
        tw=target_size[0],
        th=target_size[1],
    )
    return polygons

_compute_target_size classmethod

_compute_target_size(input_size: Union[ImageSizeType, ndarray], size: Optional[Union[ImageSizeType, int]] = None, scale: Optional[Union[int, float]] = None, area_sqrt: Optional[Union[int, float]] = None, max_size: Optional[Union[ImageSizeType, int]] = None, round: Optional[int] = None, round_type: str = 'round') -> ImageSizeType
Source code in SaigeToolkit/data/transform/resize.py
@classmethod
def _compute_target_size(
    cls,
    input_size: Union[ImageSizeType, np.ndarray],
    size: Optional[Union[ImageSizeType, int]] = None,
    scale: Optional[Union[int, float]] = None,
    area_sqrt: Optional[Union[int, float]] = None,
    max_size: Optional[Union[ImageSizeType, int]] = None,
    round: Optional[int] = None,
    round_type: str = "round",
) -> ImageSizeType:
    input_size = np.array(input_size)

    if size is not None:
        target_size = np.array(size)
    elif scale is not None:
        target_size = (input_size * scale).astype(int)
    elif area_sqrt is not None:
        scale = area_sqrt / sqrt(input_size[0] * input_size[1])
        target_size = (input_size * scale).astype(int)
    elif max_size is not None:
        max_size = np.array(max_size)
        scale = min(np.min(max_size / input_size), 1)
        target_size = (input_size * scale).astype(int)
    else:
        target_size = input_size

    if size is None and round is not None:
        round_func = cls.round_functions[round_type]
        target_size = (round * round_func(target_size / round)).astype(int)
        target_size = np.clip(a=target_size, a_min=round, a_max=None)

    return tuple(target_size)

_preprocess_size staticmethod

_preprocess_size(size: Optional[Union[ImageSizeType, int]] = None) -> ImageSizeType
Source code in SaigeToolkit/data/transform/resize.py
@staticmethod
def _preprocess_size(size: Optional[Union[ImageSizeType, int]] = None) -> ImageSizeType:
    if isinstance(size, int):
        size = (size, size)
    elif isinstance(size, Sequence):
        size = (size[0], size[1])

    return size

_check_parameter classmethod

_check_parameter(size: Optional[Union[ImageSizeType, int]], scale: Optional[Union[int, float]], area_sqrt: Optional[Union[int, float]], max_size: Optional[Union[ImageSizeType, int]], round: Optional[int], round_type: str) -> None
Source code in SaigeToolkit/data/transform/resize.py
@classmethod
def _check_parameter(
    cls,
    size: Optional[Union[ImageSizeType, int]],
    scale: Optional[Union[int, float]],
    area_sqrt: Optional[Union[int, float]],
    max_size: Optional[Union[ImageSizeType, int]],
    round: Optional[int],
    round_type: str,
) -> None:
    num_of_not_none = 0
    for arg in [size, scale, area_sqrt, max_size]:
        if arg is not None:
            num_of_not_none += 1
    if num_of_not_none > 1:
        raise ResizerParameterValueError

    if round_type not in cls.round_functions:
        raise ResizerParameterValueError

    if (size is not None) and (round is not None):
        raise ResizerParameterValueError

InspectionSizeResizer

InspectionSizeResizer(inspection_size_wh: Optional[ImageSizeType] = None, resizer: Optional[Resizer] = None)

Bases: Resizer

원본 이미지가 inspection_size를 넘지 않도록 resize 했을 때의 image scale만큼 resize를 해주는 resizer를 생성하는 class 입니다.

inspection_size는 원본 이미지에 대해 적용하지만, 실제 연산은 ROI가 먼저 계산되기 때문에, 원본 이미지가 inspection_size를 넘지 않도록 resize 했을 때의 image scale을 미리 계산해두고, 해당 scale만큼 resize를 하는 resizer를 생성하여 계산합니다.

Source code in SaigeToolkit/data/transform/resize.py
def __init__(
    self,
    inspection_size_wh: Optional[ImageSizeType] = None,
    resizer: Optional[Resizer] = None,
) -> None:
    self._check_inspection_size_type(inspection_size_wh)
    self._check_inspection_size_value(inspection_size_wh)

    initial_params = {}
    if resizer is not None:
        initial_params["resampling"] = resizer.resampling
        initial_params["image_only"] = resizer.image_only

    super().__init__(**initial_params)

    self.inspection_size_wh = self._preprocess_size(inspection_size_wh)

inspection_size_wh instance-attribute

inspection_size_wh = _preprocess_size(inspection_size_wh)

_check_inspection_size_type

_check_inspection_size_type(inspection_size_wh: Optional[ImageSizeType]) -> None
Source code in SaigeToolkit/data/transform/resize.py
def _check_inspection_size_type(self, inspection_size_wh: Optional[ImageSizeType]) -> None:
    # 타입 체크
    valid_type = (
        inspection_size_wh is None
        or len(inspection_size_wh) == 2
        and all(isinstance(v, int) for v in inspection_size_wh)
    )
    if not valid_type:
        raise InspectionSizeTypeError

_check_inspection_size_value

_check_inspection_size_value(inspection_size_wh: Optional[ImageSizeType]) -> None
Source code in SaigeToolkit/data/transform/resize.py
def _check_inspection_size_value(self, inspection_size_wh: Optional[ImageSizeType]) -> None:
    # 값 체크, inspection_size_wh의 값은 모두 1 이상이어야 한다.
    valid_value = inspection_size_wh is None or all(value >= 1 for value in inspection_size_wh)
    if not valid_value:
        raise InspectionSizeValueError

set_scale_from_data

set_scale_from_data(**data) -> None
Source code in SaigeToolkit/data/transform/resize.py
def set_scale_from_data(self, **data) -> None:
    if self.inspection_size_wh is not None:
        input_size = np.array(self.compute_input_size(data))
        inspection_size_wh = np.array(self.inspection_size_wh)
        self.scale = min(np.min(inspection_size_wh / input_size), 1)

StackedResizerHandler

StackedResizerHandler(resizer_list: List[Optional[Resizer]])

같은 image에 대해 여러번의 resize가 연속적으로 적용될 때, 여러개의 resize를 하나로 묶어서 최종 target size로 한번에 resize를 해주는 class입니다.

Source code in SaigeToolkit/data/transform/resize.py
def __init__(
    self,
    resizer_list: List[Optional[Resizer]],
) -> None:
    self.resizer_list = resizer_list
    self.is_empty = len(resizer_list) == 0 or all(x is None for x in resizer_list)

    if not self.is_empty:
        resampling = set()
        image_only = set()
        use_cv2_for_numpy = set()
        for resizer in resizer_list:
            if resizer is not None:
                resampling.add(resizer.resampling)
                image_only.add(resizer.image_only)
                use_cv2_for_numpy.add(resizer.use_cv2_for_numpy)

        if len(resampling) > 1 or len(image_only) > 1 or len(use_cv2_for_numpy) > 1:
            raise StackedResizerHandlerParameterValueError

        self.resampling = resampling.pop()
        self.image_only = image_only.pop()
        self.use_cv2_for_numpy = use_cv2_for_numpy.pop()

resizer_list instance-attribute

resizer_list = resizer_list

is_empty instance-attribute

is_empty = len(resizer_list) == 0 or all(x is None for x in resizer_list)

resampling instance-attribute

resampling = pop()

image_only instance-attribute

image_only = pop()

use_cv2_for_numpy instance-attribute

use_cv2_for_numpy = pop()

__call__

__call__(return_revert_params: bool = False, **data) -> Union[Dict, Tuple[Dict, Dict]]
Source code in SaigeToolkit/data/transform/resize.py
def __call__(self, return_revert_params: bool = False, **data) -> Union[Dict, Tuple[Dict, Dict]]:
    if return_revert_params:
        revert_params = []

    if self.is_empty:
        revert_params = [None] * len(self.resizer_list)
    else:
        input_size = Resizer.compute_input_size(data)
        target_size = input_size

        for resizer in self.resizer_list:
            if resizer is None:
                if return_revert_params:
                    revert_params.append(None)
            else:
                revert_param = {"image_size_before_resize": target_size}
                target_size = resizer.compute_target_size(target_size)
                revert_param["image_size_after_resize"] = target_size
                if return_revert_params:
                    revert_params.append(revert_param)

        if list(input_size) != list(target_size):
            data = Resizer.apply_with_params(
                data=data,
                input_size=input_size,
                target_size=target_size,
                resampling=self.resampling,
                image_only=self.image_only,
                use_cv2_for_numpy=self.use_cv2_for_numpy,
            )

    if return_revert_params:
        return_value = (data, revert_params)
    else:
        return_value = data

    return return_value

resize_box

resize_box(bboxes: BBoxesType, image_size: Tuple[int], tw: int, th: int) -> BBoxesType

bbox resize from (w, h) to (tw, th)

Source code in SaigeToolkit/data/transform/box_function.py
@preserve_coordinates
def resize_box(bboxes: BBoxesType, image_size: Tuple[int], tw: int, th: int) -> BBoxesType:
    """bbox resize from (w, h) to (tw, th)"""
    dtype = bboxes.dtype
    w, h = image_size
    if w == tw and h == th:
        return bboxes
    else:
        w_scale = tw / w
        h_scale = th / h
        return (bboxes * (w_scale, h_scale, w_scale, h_scale)).astype(dtype)

resize_polygon

resize_polygon(polygons: PolygonType, image_size: Tuple[int], tw: int, th: int) -> PolygonType

Resize polygon from (w, h) to (tw, th)

Source code in SaigeToolkit/data/transform/polygon_function.py
def resize_polygon(polygons: PolygonType, image_size: Tuple[int], tw: int, th: int) -> PolygonType:
    """Resize polygon from (w, h) to (tw, th)"""
    if len(polygons) == 0:
        return polygons

    w, h = image_size
    if w == tw and h == th:
        return polygons

    dtype = polygons[0].dtype

    w_scale = tw / w
    h_scale = th / h

    new_polygons = deepcopy(polygons)

    for polygon in new_polygons:
        polygon[:, 0] = polygon[:, 0] * w_scale
        polygon[:, 1] = polygon[:, 1] * h_scale
        polygon = polygon.astype(dtype)

    return new_polygons

read_image_size

read_image_size(image: Union[Image, Tensor, ndarray]) -> ImageSizeType

image size: (W, H)

Source code in SaigeToolkit/data/transform/image_function.py
def read_image_size(image: Union[Image.Image, torch.Tensor, np.ndarray]) -> ImageSizeType:
    """image size: (W, H)"""
    if isinstance(image, Image.Image):
        return image.size
    elif isinstance(image, torch.Tensor) and image.ndim in (2, 3, 4):  # HW, CHW, BCHW
        return (image.shape[-1], image.shape[-2])
    elif isinstance(image, np.ndarray) and image.ndim in (2, 3):  # HW, HWC
        return (image.shape[1], image.shape[0])
    else:
        raise NotImplementedError

resize_image

resize_image(image: Union[Image, Tensor, ndarray], target_size: ImageSizeType, resampling: str = 'bilinear', use_cv2_for_numpy: bool = True) -> Union[Image, Tensor, ndarray]

이미지를 resize합니다.

Parameters:

  • image (Union[Image, Tensor, ndarray]) –

    image data

  • target_size (ImageSizeType) –

    [W, H]

  • resampling (str, default: 'bilinear' ) –

    resampling method. Defaults to "bilinear".

  • use_cv2_for_numpy (bool, default: True ) –

    use cv2 instead of PIL for faster numpy array image resizing. Defaults to True.

Returns:

  • Union[Image, Tensor, ndarray]

    Union[Image.Image, torch.Tensor, np.ndarray]: resized image

Source code in SaigeToolkit/data/transform/image_function.py
def resize_image(
    image: Union[Image.Image, torch.Tensor, np.ndarray],
    target_size: ImageSizeType,
    resampling: str = "bilinear",
    use_cv2_for_numpy: bool = True,
) -> Union[Image.Image, torch.Tensor, np.ndarray]:
    """이미지를 resize합니다.

    Args:
        image (Union[Image.Image, torch.Tensor, np.ndarray]): image data
        target_size (ImageSizeType): [W, H]
        resampling (str): resampling method. Defaults to "bilinear".
        use_cv2_for_numpy (bool): use cv2 instead of PIL for faster numpy array image resizing. Defaults to True.

    Returns:
        Union[Image.Image, torch.Tensor, np.ndarray]: resized image
    """
    if isinstance(image, Image.Image):
        image = image.resize(target_size, RESAMPLE_PIL[resampling])
    elif isinstance(image, torch.Tensor):  # CHW, BCHW
        is_three_dim = image.ndim == 3
        if is_three_dim:  # CHW -> 1CHW
            image = image.unsqueeze(0)
        image = torch.nn.functional.interpolate(
            image,
            size=(target_size[1], target_size[0]),
            mode=RESAMPLE_TORCH[resampling],
            antialias=None if resampling == "nearest" else True,
        )
        if is_three_dim:
            image = image.squeeze(0)
    elif isinstance(image, np.ndarray):  # HWC, HW
        if use_cv2_for_numpy:
            # NOTE: cv2 resize is different from PIL/torch (inaccurate but fast)
            image = cv2.resize(image, dsize=target_size, interpolation=RESAMPLE_CV2[resampling])
        else:
            is_single_channel = image.ndim == 3 and image.shape[-1] == 1
            if is_single_channel:
                image = image[:, :, 0]
            image = Image.fromarray(image)
            image = image.resize(target_size, RESAMPLE_PIL[resampling])
            image = np.array(image)
            if is_single_channel:
                image = image[:, :, np.newaxis]
    return image

resize_mask

resize_mask(mask: Union[Image, Tensor, ndarray], target_size: ImageSizeType) -> Union[Image, Tensor, ndarray]

mask 이미지를 resize합니다. (NEAREST resampling)

Parameters:

  • mask (Union[Image, Tensor, ndarray]) –

    mask image

  • target_size (ImageSizeType) –

    [W, H]

Returns:

  • Union[Image, Tensor, ndarray]

    Union[Image.Image, torch.Tensor, np.ndarray]: resized mask image

Source code in SaigeToolkit/data/transform/image_function.py
def resize_mask(
    mask: Union[Image.Image, torch.Tensor, np.ndarray],
    target_size: ImageSizeType,
) -> Union[Image.Image, torch.Tensor, np.ndarray]:
    """mask 이미지를 resize합니다. (NEAREST resampling)

    Args:
        mask (Union[Image.Image, torch.Tensor, np.ndarray]): mask image
        target_size (ImageSizeType): [W, H]

    Returns:
        Union[Image.Image, torch.Tensor, np.ndarray]: resized mask image
    """
    if isinstance(mask, Image.Image):
        mask = mask.resize(target_size, Image.Resampling.NEAREST)
    elif isinstance(mask, torch.Tensor):  # HW, BHW
        is_two_dim = mask.ndim == 2
        if is_two_dim:  # HW -> 1HW
            mask = mask.unsqueeze(0)
        mask = torch.nn.functional.interpolate(
            mask.unsqueeze(1),  # BHW -> B1HW
            size=(target_size[1], target_size[0]),
            mode="nearest-exact",
        ).squeeze(1)
        if is_two_dim:
            mask = mask.squeeze(0)
    elif isinstance(mask, np.ndarray):  # HW
        mask = Image.fromarray(mask)
        mask = mask.resize(target_size, Image.Resampling.NEAREST)
        mask = np.array(mask)
    return mask