Skip to content

Commit ce49a8e

Browse files
Refactor Object Detection Transforms (#835)
* refactor object detection transform * add a protocol for ltdetr transform args
1 parent 4eff8fb commit ce49a8e

17 files changed

Lines changed: 1625 additions & 997 deletions

File tree

src/lightly_train/_commands/benchmark_task.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@
5959
_yolo_to_xyxy,
6060
)
6161
from lightly_train._task_models.task_model import TaskModel
62-
from lightly_train._transforms.object_detection_transform import (
63-
ObjectDetectionCollateFunction,
64-
ObjectDetectionTransform,
65-
ObjectDetectionTransformArgs,
62+
from lightly_train._transforms.ltdetr_transforms.object_detection import (
63+
LTDETRObjectDetectionCollateFunction,
64+
LTDETRObjectDetectionTransform,
65+
LTDETRObjectDetectionTransformArgs,
6666
)
6767
from lightly_train._transforms.transform import NormalizeArgs, ResizeArgs
6868
from lightly_train.types import (
@@ -341,7 +341,7 @@ def _make_val_bbox_params() -> BboxParams:
341341
)
342342

343343

344-
class _BenchmarkValTransformArgs(ObjectDetectionTransformArgs):
344+
class _BenchmarkValTransformArgs(LTDETRObjectDetectionTransformArgs):
345345
"""Val transform args that mirror the training validation pipeline.
346346
347347
All augmentations are disabled. Only resize and normalize (plus bbox params)
@@ -419,7 +419,7 @@ def _create_val_dataloader(
419419
val_dataset_args = data_args.get_val_args()
420420
dataset_cls = val_dataset_args.get_dataset_cls()
421421
image_info = list(val_dataset_args.list_image_info())
422-
transform = ObjectDetectionTransform(transform_args=transform_args)
422+
transform = LTDETRObjectDetectionTransform(transform_args=transform_args)
423423
dataset = dataset_cls(
424424
dataset_args=val_dataset_args,
425425
image_info=image_info,
@@ -435,7 +435,7 @@ def _create_val_dataloader(
435435
shuffle=False,
436436
num_workers=num_workers,
437437
drop_last=True,
438-
collate_fn=ObjectDetectionCollateFunction(
438+
collate_fn=LTDETRObjectDetectionCollateFunction(
439439
split="val",
440440
transform_args=transform_args,
441441
),

src/lightly_train/_data/object_detection_dataset.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323

2424
from lightly_train._data import file_helpers
2525
from lightly_train._data.task_dataset import TaskDataset
26-
from lightly_train._transforms.object_detection_transform import (
27-
ObjectDetectionCollateFunction,
26+
from lightly_train._transforms.ltdetr_transforms.object_detection import (
27+
LTDETRObjectDetectionCollateFunction,
2828
)
2929
from lightly_train._transforms.task_transform import TaskCollateFunction
3030
from lightly_train.types import ObjectDetectionDatasetItem
@@ -35,7 +35,7 @@ class ObjectDetectionDataset(TaskDataset):
3535
dataset_args: COCOObjectDetectionDatasetArgs | YOLOObjectDetectionDatasetArgs # type: ignore[assignment]
3636

3737
batch_collate_fn_cls: ClassVar[type[TaskCollateFunction]] = (
38-
ObjectDetectionCollateFunction
38+
LTDETRObjectDetectionCollateFunction
3939
)
4040

4141
def __getitem__(self, index: int) -> ObjectDetectionDatasetItem:

src/lightly_train/_task_models/dinov2_ltdetr_object_detection/transforms.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313
from lightning_utilities.core.imports import RequirementCache
1414
from pydantic import Field
1515

16-
from lightly_train._transforms.object_detection_transform import (
17-
ObjectDetectionTransform,
18-
ObjectDetectionTransformArgs,
16+
from lightly_train._transforms.ltdetr_transforms.object_detection import (
17+
LTDETRObjectDetectionTransform,
18+
LTDETRObjectDetectionTransformArgs,
19+
)
20+
from lightly_train._transforms.ltdetr_transforms.utils import (
1921
resolve_ltdetr_step_schedule_for_augmentation,
2022
)
2123
from lightly_train._transforms.transform import (
@@ -199,7 +201,7 @@ class DINOv2LTDETRObjectDetectionResizeArgs(ResizeArgs):
199201
width: int | Literal["auto"] = "auto"
200202

201203

202-
class DINOv2LTDETRObjectDetectionTrainTransformArgs(ObjectDetectionTransformArgs):
204+
class DINOv2LTDETRObjectDetectionTrainTransformArgs(LTDETRObjectDetectionTransformArgs):
203205
channel_drop: None = None
204206
num_channels: int | Literal["auto"] = "auto"
205207
photometric_distort: (
@@ -301,7 +303,7 @@ def resolve_step_schedule(
301303
)
302304

303305

304-
class DINOv2LTDETRObjectDetectionValTransformArgs(ObjectDetectionTransformArgs):
306+
class DINOv2LTDETRObjectDetectionValTransformArgs(LTDETRObjectDetectionTransformArgs):
305307
channel_drop: None = None
306308
num_channels: int | Literal["auto"] = "auto"
307309
photometric_distort: None = None
@@ -368,9 +370,9 @@ def resolve_auto(self, model_init_args: dict[str, Any]) -> None:
368370
self.num_channels = len(self.normalize.mean)
369371

370372

371-
class DINOv2LTDETRObjectDetectionTrainTransform(ObjectDetectionTransform):
373+
class DINOv2LTDETRObjectDetectionTrainTransform(LTDETRObjectDetectionTransform):
372374
transform_args_cls = DINOv2LTDETRObjectDetectionTrainTransformArgs
373375

374376

375-
class DINOv2LTDETRObjectDetectionValTransform(ObjectDetectionTransform):
377+
class DINOv2LTDETRObjectDetectionValTransform(LTDETRObjectDetectionTransform):
376378
transform_args_cls = DINOv2LTDETRObjectDetectionValTransformArgs

src/lightly_train/_task_models/ltdetr_object_detection/transforms.py

Lines changed: 20 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,22 @@
77
#
88
from __future__ import annotations
99

10-
import math
1110
from typing import Any, Literal, Sequence
1211

1312
from albumentations import BboxParams
14-
from lightning_utilities.core.imports import RequirementCache
1513
from pydantic import Field
1614

1715
from lightly_train._task_models.object_detection_components.ltdetr_geometry import (
1816
ltdetr_image_size_divisor,
1917
)
20-
from lightly_train._transforms.object_detection_transform import (
21-
ObjectDetectionTransform,
22-
ObjectDetectionTransformArgs,
18+
from lightly_train._transforms.ltdetr_transforms.object_detection import (
19+
LTDETRObjectDetectionTransform,
20+
LTDETRObjectDetectionTransformArgs,
21+
)
22+
from lightly_train._transforms.ltdetr_transforms.utils import (
23+
ALBUMENTATIONS_VERSION_GREATER_EQUAL_1_4_5,
24+
ALBUMENTATIONS_VERSION_GREATER_EQUAL_2_0_1,
25+
resolve_image_size_for_patch_size,
2326
resolve_ltdetr_step_schedule_for_augmentation,
2427
)
2528
from lightly_train._transforms.transform import (
@@ -39,39 +42,6 @@
3942
)
4043
from lightly_train.types import ImageSizeTuple
4144

42-
ALBUMENTATIONS_VERSION_GREATER_EQUAL_1_4_5 = RequirementCache("albumentations>=1.4.5")
43-
ALBUMENTATIONS_VERSION_GREATER_EQUAL_2_0_1 = RequirementCache("albumentations>=2.0.1")
44-
45-
46-
def _resolve_image_size_for_patch_size(
47-
model_init_args: dict[str, Any],
48-
*,
49-
default_image_size: tuple[int, int],
50-
patch_size: int | None,
51-
) -> tuple[int, int]:
52-
provided_image_size = model_init_args.get("image_size")
53-
if provided_image_size is not None:
54-
image_size = (
55-
int(provided_image_size[0]),
56-
int(provided_image_size[1]),
57-
)
58-
if patch_size is not None:
59-
divisor = ltdetr_image_size_divisor(patch_size)
60-
if any(size % divisor != 0 for size in image_size):
61-
raise ValueError(
62-
"When providing an image size in model_init_args, it must be divisible by 2 * the patch size."
63-
)
64-
return image_size
65-
66-
if patch_size is None:
67-
return default_image_size
68-
69-
divisor = ltdetr_image_size_divisor(patch_size)
70-
return (
71-
math.ceil(default_image_size[0] / divisor) * divisor,
72-
math.ceil(default_image_size[1] / divisor) * divisor,
73-
)
74-
7545

7646
class LTDETRObjectDetectionRandomPhotometricDistortArgs(RandomPhotometricDistortArgs):
7747
prob: float = 0.5
@@ -229,7 +199,7 @@ class LTDETRObjectDetectionResizeArgs(ResizeArgs):
229199
width: int | Literal["auto"] = "auto"
230200

231201

232-
class LTDETRObjectDetectionTrainTransformArgs(ObjectDetectionTransformArgs):
202+
class LTDETRObjectDetectionTrainTransformArgs(LTDETRObjectDetectionTransformArgs):
233203
channel_drop: ChannelDropArgs | None = None
234204
num_channels: int | Literal["auto"] = "auto"
235205
photometric_distort: LTDETRObjectDetectionRandomPhotometricDistortArgs | None = (
@@ -284,7 +254,7 @@ def resolve_auto(self, model_init_args: dict[str, Any]) -> None:
284254
patch_size: int | None = model_init_args.get("patch_size")
285255

286256
if self.image_size == "auto":
287-
self.image_size = _resolve_image_size_for_patch_size(
257+
self.image_size = resolve_image_size_for_patch_size(
288258
model_init_args,
289259
default_image_size=(640, 640),
290260
patch_size=patch_size,
@@ -350,7 +320,7 @@ def resolve_step_schedule(
350320
)
351321

352322

353-
class LTDETRObjectDetectionValTransformArgs(ObjectDetectionTransformArgs):
323+
class LTDETRObjectDetectionValTransformArgs(LTDETRObjectDetectionTransformArgs):
354324
channel_drop: None = None
355325
num_channels: int | Literal["auto"] = "auto"
356326
photometric_distort: None = None
@@ -387,7 +357,7 @@ def resolve_auto(self, model_init_args: dict[str, Any]) -> None:
387357
patch_size: int | None = model_init_args.get("patch_size")
388358

389359
if self.image_size == "auto":
390-
self.image_size = _resolve_image_size_for_patch_size(
360+
self.image_size = resolve_image_size_for_patch_size(
391361
model_init_args,
392362
default_image_size=(640, 640),
393363
patch_size=patch_size,
@@ -421,11 +391,11 @@ def resolve_auto(self, model_init_args: dict[str, Any]) -> None:
421391
self.num_channels = len(self.normalize.mean)
422392

423393

424-
class LTDETRObjectDetectionTrainTransform(ObjectDetectionTransform):
394+
class LTDETRObjectDetectionTrainTransform(LTDETRObjectDetectionTransform):
425395
transform_args_cls = LTDETRObjectDetectionTrainTransformArgs
426396

427397

428-
class LTDETRObjectDetectionValTransform(ObjectDetectionTransform):
398+
class LTDETRObjectDetectionValTransform(LTDETRObjectDetectionTransform):
429399
transform_args_cls = LTDETRObjectDetectionValTransformArgs
430400

431401

@@ -592,7 +562,9 @@ class DINOv2LTDETRObjectDetectionResizeArgsV2(ResizeArgs):
592562
width: int | Literal["auto"] = "auto"
593563

594564

595-
class DINOv2LTDETRObjectDetectionTrainTransformArgsV2(ObjectDetectionTransformArgs):
565+
class DINOv2LTDETRObjectDetectionTrainTransformArgsV2(
566+
LTDETRObjectDetectionTransformArgs
567+
):
596568
channel_drop: None = None
597569
num_channels: int | Literal["auto"] = "auto"
598570
photometric_distort: (
@@ -694,7 +666,7 @@ def resolve_step_schedule(
694666
)
695667

696668

697-
class DINOv2LTDETRObjectDetectionValTransformArgsV2(ObjectDetectionTransformArgs):
669+
class DINOv2LTDETRObjectDetectionValTransformArgsV2(LTDETRObjectDetectionTransformArgs):
698670
channel_drop: None = None
699671
num_channels: int | Literal["auto"] = "auto"
700672
photometric_distort: None = None
@@ -761,9 +733,9 @@ def resolve_auto(self, model_init_args: dict[str, Any]) -> None:
761733
self.num_channels = len(self.normalize.mean)
762734

763735

764-
class DINOv2LTDETRObjectDetectionTrainTransformV2(ObjectDetectionTransform):
736+
class DINOv2LTDETRObjectDetectionTrainTransformV2(LTDETRObjectDetectionTransform):
765737
transform_args_cls = DINOv2LTDETRObjectDetectionTrainTransformArgsV2
766738

767739

768-
class DINOv2LTDETRObjectDetectionValTransformV2(ObjectDetectionTransform):
740+
class DINOv2LTDETRObjectDetectionValTransformV2(LTDETRObjectDetectionTransform):
769741
transform_args_cls = DINOv2LTDETRObjectDetectionValTransformArgsV2

src/lightly_train/_task_models/picodet_object_detection/transforms.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
from lightning_utilities.core.imports import RequirementCache
1414
from pydantic import Field
1515

16-
from lightly_train._transforms.object_detection_transform import (
17-
ObjectDetectionTransform,
18-
ObjectDetectionTransformArgs,
16+
from lightly_train._transforms.ltdetr_transforms.object_detection import (
17+
LTDETRObjectDetectionTransform,
18+
LTDETRObjectDetectionTransformArgs,
1919
)
2020
from lightly_train._transforms.transform import (
2121
NormalizeArgs,
@@ -72,7 +72,7 @@ class PicoDetScaleJitterArgs(ScaleJitterArgs):
7272
divisible_by: int | None = None
7373

7474

75-
class PicoDetObjectDetectionTrainTransformArgs(ObjectDetectionTransformArgs):
75+
class PicoDetObjectDetectionTrainTransformArgs(LTDETRObjectDetectionTransformArgs):
7676
"""PicoDet training transforms aligned with the reference config.
7777
7878
PicoDet defaults mirror LTDETR training augmentations for consistency.
@@ -182,13 +182,13 @@ def resolve_auto(self, model_init_args: dict[str, Any]) -> None:
182182
self.scale_jitter.divisible_by = 32
183183

184184

185-
class PicoDetObjectDetectionTrainTransform(ObjectDetectionTransform):
185+
class PicoDetObjectDetectionTrainTransform(LTDETRObjectDetectionTransform):
186186
"""Training transforms for PicoDet."""
187187

188188
transform_args_cls = PicoDetObjectDetectionTrainTransformArgs
189189

190190

191-
class PicoDetObjectDetectionValTransformArgs(ObjectDetectionTransformArgs):
191+
class PicoDetObjectDetectionValTransformArgs(LTDETRObjectDetectionTransformArgs):
192192
"""PicoDet validation transforms."""
193193

194194
channel_drop: None = None
@@ -258,7 +258,7 @@ def resolve_auto(self, model_init_args: dict[str, Any]) -> None:
258258
self.num_channels = 3
259259

260260

261-
class PicoDetObjectDetectionValTransform(ObjectDetectionTransform):
261+
class PicoDetObjectDetectionValTransform(LTDETRObjectDetectionTransform):
262262
"""Validation transforms for PicoDet."""
263263

264264
transform_args_cls = PicoDetObjectDetectionValTransformArgs
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#
2+
# Copyright (c) Lightly AG and affiliates.
3+
# All rights reserved.
4+
#
5+
# This source code is licensed under the license found in the
6+
# LICENSE file in the root directory of this source tree.
7+
#

0 commit comments

Comments
 (0)