| | import torch |
| | import torchvision.transforms.functional as F |
| | from PIL import Image |
| | import warnings |
| | import math |
| | import random |
| | import numpy as np |
| |
|
| |
|
| | class ToNumpy: |
| |
|
| | def __call__(self, pil_img): |
| | np_img = np.array(pil_img, dtype=np.uint8) |
| | if np_img.ndim < 3: |
| | np_img = np.expand_dims(np_img, axis=-1) |
| | np_img = np.rollaxis(np_img, 2) |
| | return np_img |
| |
|
| |
|
| | class ToTensor: |
| |
|
| | def __init__(self, dtype=torch.float32): |
| | self.dtype = dtype |
| |
|
| | def __call__(self, pil_img): |
| | np_img = np.array(pil_img, dtype=np.uint8) |
| | if np_img.ndim < 3: |
| | np_img = np.expand_dims(np_img, axis=-1) |
| | np_img = np.rollaxis(np_img, 2) |
| | return torch.from_numpy(np_img).to(dtype=self.dtype) |
| |
|
| |
|
| | _pil_interpolation_to_str = { |
| | Image.NEAREST: 'PIL.Image.NEAREST', |
| | Image.BILINEAR: 'PIL.Image.BILINEAR', |
| | Image.BICUBIC: 'PIL.Image.BICUBIC', |
| | Image.LANCZOS: 'PIL.Image.LANCZOS', |
| | Image.HAMMING: 'PIL.Image.HAMMING', |
| | Image.BOX: 'PIL.Image.BOX', |
| | } |
| |
|
| |
|
| | def _pil_interp(method): |
| | if method == 'bicubic': |
| | return Image.BICUBIC |
| | elif method == 'lanczos': |
| | return Image.LANCZOS |
| | elif method == 'hamming': |
| | return Image.HAMMING |
| | else: |
| | |
| | return Image.BILINEAR |
| |
|
| |
|
| | _RANDOM_INTERPOLATION = (Image.BILINEAR, Image.BICUBIC) |
| |
|
| |
|
| | class RandomResizedCropAndInterpolation: |
| | """Crop the given PIL Image to random size and aspect ratio with random interpolation. |
| | |
| | A crop of random size (default: of 0.08 to 1.0) of the original size and a random |
| | aspect ratio (default: of 3/4 to 4/3) of the original aspect ratio is made. This crop |
| | is finally resized to given size. |
| | This is popularly used to train the Inception networks. |
| | |
| | Args: |
| | size: expected output size of each edge |
| | scale: range of size of the origin size cropped |
| | ratio: range of aspect ratio of the origin aspect ratio cropped |
| | interpolation: Default: PIL.Image.BILINEAR |
| | """ |
| |
|
| | def __init__(self, size, scale=(0.08, 1.0), ratio=(3. / 4., 4. / 3.), |
| | interpolation='bilinear'): |
| | if isinstance(size, (list, tuple)): |
| | self.size = tuple(size) |
| | else: |
| | self.size = (size, size) |
| | if (scale[0] > scale[1]) or (ratio[0] > ratio[1]): |
| | warnings.warn("range should be of kind (min, max)") |
| |
|
| | if interpolation == 'random': |
| | self.interpolation = _RANDOM_INTERPOLATION |
| | else: |
| | self.interpolation = _pil_interp(interpolation) |
| | self.scale = scale |
| | self.ratio = ratio |
| |
|
| | @staticmethod |
| | def get_params(img, scale, ratio): |
| | """Get parameters for ``crop`` for a random sized crop. |
| | |
| | Args: |
| | img (PIL Image): Image to be cropped. |
| | scale (tuple): range of size of the origin size cropped |
| | ratio (tuple): range of aspect ratio of the origin aspect ratio cropped |
| | |
| | Returns: |
| | tuple: params (i, j, h, w) to be passed to ``crop`` for a random |
| | sized crop. |
| | """ |
| | area = img.size[0] * img.size[1] |
| |
|
| | for attempt in range(10): |
| | target_area = random.uniform(*scale) * area |
| | log_ratio = (math.log(ratio[0]), math.log(ratio[1])) |
| | aspect_ratio = math.exp(random.uniform(*log_ratio)) |
| |
|
| | w = int(round(math.sqrt(target_area * aspect_ratio))) |
| | h = int(round(math.sqrt(target_area / aspect_ratio))) |
| |
|
| | if w <= img.size[0] and h <= img.size[1]: |
| | i = random.randint(0, img.size[1] - h) |
| | j = random.randint(0, img.size[0] - w) |
| | return i, j, h, w |
| |
|
| | |
| | in_ratio = img.size[0] / img.size[1] |
| | if in_ratio < min(ratio): |
| | w = img.size[0] |
| | h = int(round(w / min(ratio))) |
| | elif in_ratio > max(ratio): |
| | h = img.size[1] |
| | w = int(round(h * max(ratio))) |
| | else: |
| | w = img.size[0] |
| | h = img.size[1] |
| | i = (img.size[1] - h) // 2 |
| | j = (img.size[0] - w) // 2 |
| | return i, j, h, w |
| |
|
| | def __call__(self, img): |
| | """ |
| | Args: |
| | img (PIL Image): Image to be cropped and resized. |
| | |
| | Returns: |
| | PIL Image: Randomly cropped and resized image. |
| | """ |
| | i, j, h, w = self.get_params(img, self.scale, self.ratio) |
| | if isinstance(self.interpolation, (tuple, list)): |
| | interpolation = random.choice(self.interpolation) |
| | else: |
| | interpolation = self.interpolation |
| | return F.resized_crop(img, i, j, h, w, self.size, interpolation) |
| |
|
| | def __repr__(self): |
| | if isinstance(self.interpolation, (tuple, list)): |
| | interpolate_str = ' '.join([_pil_interpolation_to_str[x] for x in self.interpolation]) |
| | else: |
| | interpolate_str = _pil_interpolation_to_str[self.interpolation] |
| | format_string = self.__class__.__name__ + '(size={0}'.format(self.size) |
| | format_string += ', scale={0}'.format(tuple(round(s, 4) for s in self.scale)) |
| | format_string += ', ratio={0}'.format(tuple(round(r, 4) for r in self.ratio)) |
| | format_string += ', interpolation={0})'.format(interpolate_str) |
| | return format_string |
| |
|
| |
|
| |
|