Skip to content

Commit 0f2b28d

Browse files
chore: sync table definition with tier4_perception_dataset (#185)
* update table definitions * remove lidarseg * style(pre-commit): autofix * updated tests * style(pre-commit): autofix * removed redundancy * style(pre-commit): autofix * fixed test failures * add ke_only * style(pre-commit): autofix * added test for autolabel_metadata * style(pre-commit): autofix
1 parent 682cbfb commit 0f2b28d

10 files changed

Lines changed: 213 additions & 18 deletions

File tree

docs/schema/table.md

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22

33
## Type Definition
44

5-
| Expression | Description |
6-
| --------------- | -------------------------------------------------------------------------------------------------------------- |
7-
| `str` | String |
8-
| `int` | Integer |
9-
| `float` | Floating point number |
10-
| `bool` | Boolean |
11-
| `enum[X,Y,...]` | Enumerated type with possible values X, Y, ... |
12-
| `[T;N]` | Array of N elements of type T |
13-
| `option[T]` | Optional value of type T |
14-
| `RLE` | Run-length encoding given as `{"size": <[int;2]>, "counts": <str>}`, where `size` represents `(width, height)` |
5+
| Expression | Description |
6+
| ---------------- | -------------------------------------------------------------------------------------------------------------- |
7+
| `str` | String |
8+
| `int` | Integer |
9+
| `float` | Floating point number |
10+
| `bool` | Boolean |
11+
| `enum[X,Y,...]` | Enumerated type with possible values X, Y, ... |
12+
| `[T;N]` | Array of N elements of type T |
13+
| `option[T]` | Optional value of type T |
14+
| `RLE` | Run-length encoding given as `{"size": <[int;2]>, "counts": <str>}`, where `size` represents `(width, height)` |
15+
| `AutolabelModel` | Autolabel model information given as `{"name": <str>, "score": <float>, "uncertainty": <option[float]>}` |
1516

1617
## Mandatory Tables
1718

@@ -68,6 +69,8 @@ category {
6869
"name": <str> -- Name of the category.
6970
"description": <str> -- Description of the category.
7071
"index": <option[int]> -- Category index, this is added to support `lidarseg`, or `None` when it doesn't support `lidarseg`.
72+
"has_orientation": <bool> -- Indicates whether annotations for this category may include an `orientation` field (e.g., traffic light arrows). If omitted, it is treated as `false`.
73+
"has_number": <bool> -- Indicates whether annotations for this category may include a `number` field (e.g., numeric traffic lights). If omitted, it is treated as `false`.
7174
}
7275
```
7376

@@ -178,6 +181,7 @@ sample_annotation {
178181
"next": <str> -- Foreign key to the `SampleAnnotation` table associated with the next annotation in the sequence. Empty string `""` if this is the last annotation.
179182
"prev": <str> -- Foreign key to the `SampleAnnotation` table associated with the previous annotation in the sequence. Empty string `""` if this is the first annotation.
180183
"automatic_annotation": <bool> -- Indicates whether the annotation was automatically generated. Defaults to `false`.
184+
"autolabel_metadata": <option[[AutolabelModel;N]]> -- List of models used for autolabeling. Required if `automatic_annotation` is `true`.
181185
}
182186
```
183187

@@ -204,6 +208,7 @@ sample_data {
204208
"prev": <str> -- Foreign key to the `SampleData` table associated with the previous data in the sequence. Empty string `""` if this is the first data.
205209
"is_valid": <bool> -- Indicates whether this data is valid. Defaults to `true`.
206210
"info_filename": <option[str]> -- Relative path to metadata-blob file.
211+
"autolabel_metadata": <option[[AutolabelModel;N]]> -- List of models used for autolabeling applied to this entire sample_data item (e.g., image or scan).
207212
}
208213
```
209214

@@ -295,7 +300,10 @@ object_ann {
295300
"attribute_tokens": <[str;N]> -- Foreign keys to the `Attribute` table associated with the attributes of the object.
296301
"bbox": <[int;4]> -- Bounding box coordinates in the format (xmin, ymin, xmax, ymax).
297302
"mask": <RLE> -- Run length encoding of instance mask.
303+
"orientation": <option[float]> -- Orientation of the arrow shape within the bounding box, in radians. Present only for categories where `has_orientation` is true (e.g., traffic light arrows).
304+
"number": <option[int]> -- The digit displayed within the bounding box. Present only for categories where `has_number` is true (e.g., numeric traffic lights).
298305
"automatic_annotation": <bool> -- Whether the annotation was automatically generated. Defaults to `false`.
306+
"autolabel_metadata": <option[[AutolabelModel;N]]> -- List of models used for autolabeling. Required if `automatic_annotation` is `true`.
299307
}
300308
```
301309

@@ -312,6 +320,7 @@ surface_ann {
312320
"category_token": <str> -- Foreign key to the `Category` table associated with the category of the surface.
313321
"mask": <RLE> -- Run length encoding of instance mask.
314322
"automatic_annotation": <bool> -- Whether the annotation was automatically generated. Defaults to `false`.
323+
"autolabel_metadata": <option[[AutolabelModel;N]]> -- List of models used for autolabeling. Required if `automatic_annotation` is `true`.
315324
}
316325
```
317326

@@ -343,3 +352,15 @@ vehicle_state {
343352
"additional_info": <option[AdditionalInfo]> -- Additional information about the vehicle state.
344353
}
345354
```
355+
356+
## AutolabelModel Definition
357+
358+
The `AutolabelModel` type used in `autolabel_metadata` fields has the following structure:
359+
360+
```json
361+
AutolabelModel {
362+
"name": <str> -- Name of the model used for annotation. Can include version information.
363+
"score": <float> -- Label score for the annotation from this model (range: 0.0–1.0).
364+
"uncertainty": <option[float]> -- Model-reported uncertainty for the annotation (range: 0.0–1.0). Lower values imply higher confidence.
365+
}
366+
```

t4_devkit/schema/tables/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from .attribute import * # noqa
2+
from .autolabel_metadata import * # noqa
23
from .base import * # noqa
34
from .calibrated_sensor import * # noqa
45
from .category import * # noqa
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
from __future__ import annotations
2+
3+
from attrs import define, field, validators
4+
5+
__all__ = ["AutolabelModel", "AutolabelMixin"]
6+
7+
8+
@define
9+
class AutolabelModel:
10+
"""A dataclass to represent a model used in autolabeling.
11+
12+
Attributes:
13+
name (str): Name of the model used for annotation. Can include version information.
14+
score (float): Label score for the annotation from this model (range: 0.0–1.0).
15+
uncertainty (float | None, optional): Model-reported uncertainty for the annotation (range: 0.0–1.0).
16+
Lower values imply higher confidence.
17+
"""
18+
19+
name: str = field(validator=validators.instance_of(str))
20+
score: float = field(
21+
validator=[
22+
validators.instance_of(float),
23+
validators.and_(validators.ge(0.0), validators.le(1.0)),
24+
]
25+
)
26+
uncertainty: float | None = field(
27+
default=None,
28+
validator=validators.optional(
29+
(validators.instance_of(float), validators.and_(validators.ge(0.0), validators.le(1.0)))
30+
),
31+
)
32+
33+
@staticmethod
34+
def to_autolabel_model(x) -> list[AutolabelModel] | None:
35+
"""Convert input to a list of AutolabelModel instances.
36+
37+
Args:
38+
x: Input to convert. Can be None, a list of dicts, or a list of AutolabelModel instances.
39+
40+
Returns:
41+
list[AutolabelModel] | None: Converted list of AutolabelModel instances or None.
42+
"""
43+
if x is None:
44+
return None
45+
if isinstance(x, list):
46+
return [AutolabelModel(**model) if isinstance(model, dict) else model for model in x]
47+
raise TypeError("Input must be None or a list of [dicts or AutolabelModel] instances.")
48+
49+
50+
@define(slots=False)
51+
class AutolabelMixin:
52+
"""Mixin class for schema tables that use autolabel metadata with automatic annotation."""
53+
54+
automatic_annotation: bool = field(
55+
default=False, validator=validators.instance_of(bool), kw_only=True
56+
)
57+
autolabel_metadata: list[AutolabelModel] | None = field(
58+
default=None,
59+
converter=AutolabelModel.to_autolabel_model,
60+
validator=validators.optional(
61+
validators.deep_iterable(validators.instance_of(AutolabelModel))
62+
),
63+
kw_only=True,
64+
)
65+
66+
def __attrs_post_init__(self) -> None:
67+
"""Post-initialization validation for autolabel consistency."""
68+
# if automatic_annotation=True, autolabel_metadata must exist
69+
if self.automatic_annotation and self.autolabel_metadata is None:
70+
raise TypeError("autolabel_metadata must be provided when automatic_annotation is True")
71+
# if automatic_annotation=False, autolabel_metadata must not exist
72+
if not self.automatic_annotation and self.autolabel_metadata is not None:
73+
raise TypeError("autolabel_metadata must be None when automatic_annotation is False")

t4_devkit/schema/tables/category.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,14 @@ class Category(SchemaBase):
1919
name (str): Category name.
2020
description (str): Category description.
2121
index (int | None, optional): Category index for lidar segmentation.
22+
has_orientation (bool | None, optional): Indicates whether annotations for this category may include an `orientation` field (e.g., traffic light arrows). If omitted, it is treated as `false`.
23+
has_number (bool | None, optional): Indicates whether annotations for this category may include a `number` field (e.g., numeric traffic lights). If omitted, it is treated as `false`.
2224
"""
2325

2426
name: str = field(validator=validators.instance_of(str))
2527
description: str = field(validator=validators.instance_of(str))
2628
index: int | None = field(
2729
default=None, validator=validators.optional(validators.instance_of(int))
2830
)
31+
has_orientation: bool = field(default=False, validator=validators.instance_of(bool))
32+
has_number: bool = field(default=False, validator=validators.instance_of(bool))

t4_devkit/schema/tables/object_ann.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from t4_devkit.typing import Roi
1010

1111
from ..name import SchemaName
12+
from .autolabel_metadata import AutolabelMixin
1213
from .base import SchemaBase
1314
from .registry import SCHEMAS
1415

@@ -51,7 +52,7 @@ def decode(self) -> NDArrayU8:
5152

5253
@define(slots=False)
5354
@SCHEMAS.register(SchemaName.OBJECT_ANN)
54-
class ObjectAnn(SchemaBase):
55+
class ObjectAnn(SchemaBase, AutolabelMixin):
5556
"""A dataclass to represent schema table of `object_ann.json`.
5657
5758
Attributes:
@@ -62,8 +63,13 @@ class ObjectAnn(SchemaBase):
6263
attribute_tokens (list[str]): Foreign keys. List of attributes for this annotation.
6364
bbox (Roi): Annotated bounding box. Given as [xmin, ymin, xmax, ymax].
6465
mask (RLEMask): Instance mask using the COCO format compressed by RLE.
66+
orientation (float | None, optional): Orientation of the arrow shape within the bounding box, in radians. Present only for categories where `has_orientation` is true (e.g., traffic light arrows).
67+
number (int | None, optional): The digit displayed within the bounding box. Present only for categories where `has_number` is true (e.g., numeric traffic lights).
68+
69+
Inherited from AutolabelMixin:
6570
automatic_annotation (bool, optional): Indicates if the annotation is fully generated by an ML model.
6671
If any part is manually modified or annotated by human this value is False.
72+
autolabel_metadata (list[AutolabelModel] | None, optional): List of models used for autolabeling. Required if `automatic_annotation` is `true`.
6773
6874
Shortcuts:
6975
---------
@@ -82,7 +88,12 @@ class ObjectAnn(SchemaBase):
8288
converter=lambda x: RLEMask(**x) if isinstance(x, dict) else x,
8389
validator=validators.optional(validators.instance_of(RLEMask)),
8490
)
85-
automatic_annotation: bool = field(default=False, validator=validators.instance_of(bool))
91+
orientation: float | None = field(
92+
default=None, validator=validators.optional(validators.instance_of(float))
93+
)
94+
number: int | None = field(
95+
default=None, validator=validators.optional(validators.instance_of(int))
96+
)
8697

8798
# shortcuts
8899
category_name: str = field(init=False, factory=str)

t4_devkit/schema/tables/sample_annotation.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from t4_devkit.typing import Quaternion, Vector3
77

88
from ..name import SchemaName
9+
from .autolabel_metadata import AutolabelMixin
910
from .base import SchemaBase
1011
from .registry import SCHEMAS
1112

@@ -14,7 +15,7 @@
1415

1516
@define(slots=False)
1617
@SCHEMAS.register(SchemaName.SAMPLE_ANNOTATION)
17-
class SampleAnnotation(SchemaBase):
18+
class SampleAnnotation(SchemaBase, AutolabelMixin):
1819
"""A dataclass to represent schema table of `sample_annotation.json`.
1920
2021
Attributes:
@@ -36,8 +37,11 @@ class SampleAnnotation(SchemaBase):
3637
[vx, vy, vz] in [m/s].
3738
acceleration (Vector3 | None, optional): Bonding box acceleration
3839
given as [ax, ay, av] in [m/s^2].
40+
41+
Inherited from AutolabelMixin:
3942
automatic_annotation (bool, optional): Indicates if the annotation is fully generated by an ML model.
4043
If any part is manually modified or annotated by human this value is False.
44+
autolabel_metadata (list[AutolabelModel] | None, optional): List of models used for autolabeling. Required if `automatic_annotation` is `true`.
4145
4246
Shortcuts:
4347
---------
@@ -59,7 +63,6 @@ class SampleAnnotation(SchemaBase):
5963
prev: str = field(validator=validators.instance_of(str))
6064
velocity: Vector3 | None = field(default=None, converter=converters.optional(Vector3))
6165
acceleration: Vector3 | None = field(default=None, converter=converters.optional(Vector3))
62-
automatic_annotation: bool = field(default=False, validator=validators.instance_of(bool))
6366

6467
# shortcuts
6568
category_name: str = field(init=False, factory=str)

t4_devkit/schema/tables/sample_data.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from attrs import define, field, validators
77

88
from ..name import SchemaName
9+
from .autolabel_metadata import AutolabelModel
910
from .base import SchemaBase
1011
from .registry import SCHEMAS
1112

@@ -85,6 +86,7 @@ class SampleData(SchemaBase):
8586
Empty if start of scene.
8687
is_valid (bool): True if this data is valid, else False. Invalid data should be ignored.
8788
info_filename (str): Relative path to metainfo data-blob on disk.
89+
autolabel_metadata (list[AutolabelModel] | None, optional): List of models used for autolabeling applied to this entire sample_data item (e.g., image or scan).
8890
8991
Shortcuts:
9092
---------
@@ -107,6 +109,13 @@ class SampleData(SchemaBase):
107109
info_filename: str | None = field(
108110
default=None, validator=validators.optional(validators.instance_of(str))
109111
)
112+
autolabel_metadata: list[AutolabelModel] | None = field(
113+
default=None,
114+
converter=AutolabelModel.to_autolabel_model,
115+
validator=validators.optional(
116+
validators.deep_iterable(validators.instance_of(AutolabelModel))
117+
),
118+
)
110119

111120
# shortcuts
112121
modality: SensorModality | None = field(init=False, default=None)

t4_devkit/schema/tables/surface_ann.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from t4_devkit.typing import Roi
77

88
from ..name import SchemaName
9+
from .autolabel_metadata import AutolabelMixin
910
from .base import SchemaBase
1011
from .object_ann import RLEMask
1112
from .registry import SCHEMAS
@@ -15,16 +16,19 @@
1516

1617
@define(slots=False)
1718
@SCHEMAS.register(SchemaName.SURFACE_ANN)
18-
class SurfaceAnn(SchemaBase):
19+
class SurfaceAnn(SchemaBase, AutolabelMixin):
1920
"""A dataclass to represent schema table of `surface_ann.json`.
2021
2122
Attributes:
2223
token (str): Unique record identifier.
2324
sample_data_token (str): Foreign key pointing to the sample data, which must be a keyframe image.
2425
category_token (str): Foreign key pointing to the surface category.
2526
mask (RLEMask): Segmentation mask using the COCO format compressed by RLE.
27+
28+
Inherited from AutolabelMixin:
2629
automatic_annotation (bool, optional): Indicates if the annotation is fully generated by an ML model.
2730
If any part is manually modified or annotated by human this value is False.
31+
autolabel_metadata (list[AutolabelModel] | None, optional): List of models used for autolabeling. Required if `automatic_annotation` is `true`.
2832
2933
Shortcuts:
3034
---------
@@ -38,7 +42,6 @@ class SurfaceAnn(SchemaBase):
3842
converter=lambda x: RLEMask(**x) if isinstance(x, dict) else x,
3943
validator=validators.optional(validators.instance_of(RLEMask)),
4044
)
41-
automatic_annotation: bool = field(default=False, validator=validators.instance_of(bool))
4245

4346
# shortcuts
4447
category_name: str = field(init=False, factory=str)

tests/schema/conftest.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ def category_dict() -> dict:
6262
"name": "animal",
6363
"description": "",
6464
"index": None,
65+
"has_number": False,
66+
"has_orientation": False,
6567
}
6668

6769

@@ -178,7 +180,8 @@ def sample_annotation_dict() -> dict:
178180
"num_radar_pts": 0,
179181
"next": "7b0ae1dae7531b7b917f403cb22259e6",
180182
"prev": "",
181-
"automatic_annotation": False,
183+
"automatic_annotation": True,
184+
"autolabel_metadata": [{"name": "centerpoint_v1.2", "score": 0.95, "uncertainty": 0.1}],
182185
}
183186

184187

@@ -230,6 +233,9 @@ def sample_data_dict() -> dict:
230233
"is_valid": True,
231234
"next": "efe096cc01a610af846c29aaf4decc9a",
232235
"prev": "",
236+
"autolabel_metadata": [
237+
{"name": "image_preprocessor_v2.1", "score": 0.99, "uncertainty": None}
238+
],
233239
}
234240

235241

@@ -314,7 +320,13 @@ def object_ann_dict() -> dict:
314320
"attribute_tokens": [],
315321
"bbox": [0, 408.0529355733727, 1920, 728.1832152454293],
316322
"mask": {"size": [1920, 1280], "counts": "UFBQWzI='"},
317-
"automatic_annotation": False,
323+
"automatic_annotation": True,
324+
"autolabel_metadata": [
325+
{"name": "yolo_v8_segmentation", "score": 0.87, "uncertainty": 0.15},
326+
{"name": "mask_rcnn_v3.0", "score": 0.92, "uncertainty": None},
327+
],
328+
"number": None,
329+
"orientation": None,
318330
}
319331

320332

@@ -336,6 +348,7 @@ def surface_ann_dict() -> dict:
336348
"category_token": "7864884179fb37bf9e973016b13a332c",
337349
"mask": {"size": [1920, 1280], "counts": "UFBQWzI='"},
338350
"automatic_annotation": False,
351+
"autolabel_metadata": None,
339352
}
340353

341354

0 commit comments

Comments
 (0)