theDocWho's picture
Refactor: extract utils + base pipeline, expand docs
76955d6
Raw
History Blame Contribute Delete
2.62 kB
"""Image preprocessing transforms shared by trainers and inference.
Three callables are exported:
* :data:`IMAGENET_MEAN` / :data:`IMAGENET_STD` β€” normalisation statistics that
match the ImageNet-pretrained ResNet50 weights we fine-tune from.
* :func:`eval_transform` β€” deterministic resize+centre-crop+normalise. Used
for validation, test, feature extraction, and inference.
* :func:`train_transform` β€” augmentation pipeline with optional RandAugment.
Both transforms accept ``image_size`` (typically 224 for ResNet50). The train
transform optionally takes RandAugment parameters; setting ``num_ops=0`` falls
back to a simpler ColorJitter for backwards compatibility.
"""
from __future__ import annotations
from typing import Callable
from torchvision import transforms
IMAGENET_MEAN: tuple[float, float, float] = (0.485, 0.456, 0.406)
IMAGENET_STD: tuple[float, float, float] = (0.229, 0.224, 0.225)
def eval_transform(image_size: int = 224) -> Callable:
"""Return the deterministic preprocessing pipeline.
Resize to 1.15Γ— the target size, centre-crop down to ``image_size``, then
convert to a normalised float tensor. The 1.15Γ— margin matches what we use
during training so train/eval distributions agree.
"""
return transforms.Compose([
transforms.Resize(int(image_size * 1.15)),
transforms.CenterCrop(image_size),
transforms.ToTensor(),
transforms.Normalize(IMAGENET_MEAN, IMAGENET_STD),
])
def train_transform(
image_size: int = 224,
randaug_num_ops: int = 0,
randaug_magnitude: int = 9,
) -> Callable:
"""Return a training-time augmentation pipeline.
With ``randaug_num_ops > 0`` the pipeline uses :class:`torchvision.transforms.RandAugment`
with the given operation count and magnitude (typical values: ``num_ops=2,
magnitude=9``). With ``num_ops=0`` it falls back to a hand-tuned ColorJitter
that matches our pre-RandAugment baseline so old behaviour is recoverable.
"""
pipeline = [
transforms.Resize(int(image_size * 1.15)),
transforms.RandomResizedCrop(image_size, scale=(0.7, 1.0)),
transforms.RandomHorizontalFlip(),
]
if randaug_num_ops > 0:
pipeline.append(transforms.RandAugment(
num_ops=randaug_num_ops, magnitude=randaug_magnitude,
))
else:
pipeline.append(transforms.ColorJitter(
brightness=0.2, contrast=0.2, saturation=0.15,
))
pipeline += [
transforms.ToTensor(),
transforms.Normalize(IMAGENET_MEAN, IMAGENET_STD),
]
return transforms.Compose(pipeline)