| |
| |
| |
| |
|
|
| import logging |
| from typing import Sequence |
|
|
| import torch |
| from torchvision.transforms import v2 |
|
|
| logger = logging.getLogger("dinov3") |
|
|
|
|
| def make_interpolation_mode(mode_str: str) -> v2.InterpolationMode: |
| return {mode.value: mode for mode in v2.InterpolationMode}[mode_str] |
|
|
|
|
| class GaussianBlur(v2.RandomApply): |
| """ |
| Apply Gaussian Blur to the PIL image. |
| """ |
|
|
| def __init__(self, *, p: float = 0.5, radius_min: float = 0.1, radius_max: float = 2.0): |
| |
| keep_p = 1 - p |
| transform = v2.GaussianBlur(kernel_size=9, sigma=(radius_min, radius_max)) |
| super().__init__(transforms=[transform], p=keep_p) |
|
|
|
|
| |
| IMAGENET_DEFAULT_MEAN = (0.485, 0.456, 0.406) |
| IMAGENET_DEFAULT_STD = (0.229, 0.224, 0.225) |
|
|
| CROP_DEFAULT_SIZE = 224 |
| RESIZE_DEFAULT_SIZE = int(256 * CROP_DEFAULT_SIZE / 224) |
|
|
|
|
| def make_normalize_transform( |
| mean: Sequence[float] = IMAGENET_DEFAULT_MEAN, |
| std: Sequence[float] = IMAGENET_DEFAULT_STD, |
| ) -> v2.Normalize: |
| return v2.Normalize(mean=mean, std=std) |
|
|
|
|
| def make_base_transform( |
| mean: Sequence[float] = IMAGENET_DEFAULT_MEAN, |
| std: Sequence[float] = IMAGENET_DEFAULT_STD, |
| ) -> v2.Normalize: |
| return v2.Compose( |
| [ |
| v2.ToDtype(torch.float32, scale=True), |
| make_normalize_transform(mean=mean, std=std), |
| ] |
| ) |
|
|
|
|
| |
| |
| def make_classification_train_transform( |
| *, |
| crop_size: int = CROP_DEFAULT_SIZE, |
| interpolation=v2.InterpolationMode.BICUBIC, |
| hflip_prob: float = 0.5, |
| mean: Sequence[float] = IMAGENET_DEFAULT_MEAN, |
| std: Sequence[float] = IMAGENET_DEFAULT_STD, |
| ): |
| transforms_list = [v2.ToImage(), v2.RandomResizedCrop(crop_size, interpolation=interpolation)] |
| if hflip_prob > 0.0: |
| transforms_list.append(v2.RandomHorizontalFlip(hflip_prob)) |
| transforms_list.append(make_base_transform(mean, std)) |
| transform = v2.Compose(transforms_list) |
| logger.info(f"Built classification train transform\n{transform}") |
| return transform |
|
|
|
|
| def make_resize_transform( |
| *, |
| resize_size: int, |
| resize_square: bool = False, |
| resize_large_side: bool = False, |
| interpolation: v2.InterpolationMode = v2.InterpolationMode.BICUBIC, |
| ): |
| assert not (resize_square and resize_large_side), "These two options can not be set together" |
| if resize_square: |
| logger.info("resizing image as a square") |
| size = (resize_size, resize_size) |
| transform = v2.Resize(size=size, interpolation=interpolation) |
| return transform |
| elif resize_large_side: |
| logger.info("resizing based on large side") |
| transform = v2.Resize(size=None, max_size=resize_size, interpolation=interpolation) |
| return transform |
| else: |
| transform = v2.Resize(resize_size, interpolation=interpolation) |
| return transform |
|
|
|
|
| |
| def make_eval_transform( |
| *, |
| resize_size: int = RESIZE_DEFAULT_SIZE, |
| crop_size: int = CROP_DEFAULT_SIZE, |
| resize_square: bool = False, |
| resize_large_side: bool = False, |
| interpolation: v2.InterpolationMode = v2.InterpolationMode.BICUBIC, |
| mean: Sequence[float] = IMAGENET_DEFAULT_MEAN, |
| std: Sequence[float] = IMAGENET_DEFAULT_STD, |
| ) -> v2.Compose: |
| transforms_list = [v2.ToImage()] |
| resize_transform = make_resize_transform( |
| resize_size=resize_size, |
| resize_square=resize_square, |
| resize_large_side=resize_large_side, |
| interpolation=interpolation, |
| ) |
| transforms_list.append(resize_transform) |
| if crop_size: |
| transforms_list.append(v2.CenterCrop(crop_size)) |
| transforms_list.append(make_base_transform(mean, std)) |
| transform = v2.Compose(transforms_list) |
| logger.info(f"Built eval transform\n{transform}") |
| return transform |
|
|
|
|
| |
| |
| def make_classification_eval_transform( |
| *, |
| resize_size: int = RESIZE_DEFAULT_SIZE, |
| crop_size: int = CROP_DEFAULT_SIZE, |
| interpolation=v2.InterpolationMode.BICUBIC, |
| mean: Sequence[float] = IMAGENET_DEFAULT_MEAN, |
| std: Sequence[float] = IMAGENET_DEFAULT_STD, |
| ) -> v2.Compose: |
| return make_eval_transform( |
| resize_size=resize_size, |
| crop_size=crop_size, |
| interpolation=interpolation, |
| mean=mean, |
| std=std, |
| resize_square=False, |
| resize_large_side=False, |
| ) |
|
|
|
|
| def voc2007_classification_target_transform(label, n_categories=20): |
| one_hot = torch.zeros(n_categories, dtype=int) |
| for instance in label.instances: |
| one_hot[instance.category_id] = True |
| return one_hot |
|
|
|
|
| def imaterialist_classification_target_transform(label, n_categories=294): |
| one_hot = torch.zeros(n_categories, dtype=int) |
| one_hot[label.attributes] = True |
| return one_hot |
|
|
|
|
| def get_target_transform(dataset_str): |
| if "VOC2007" in dataset_str: |
| return voc2007_classification_target_transform |
| elif "IMaterialist" in dataset_str: |
| return imaterialist_classification_target_transform |
| return None |
|
|