Skip to content

Commit fcdb37d

Browse files
authored
Support subset for KITTI 3D format (#1621)
<!-- Contributing guide: https://github.com/openvinotoolkit/datumaro/blob/develop/CONTRIBUTING.md --> ### Summary <!-- Resolves #111 and #222. Depends on #1000 (for series of dependent commits). This PR introduces this capability to make the project better in this and that. - Added this feature - Removed that feature - Fixed the problem #1234 --> - Support subset structure for KITTI 3d format - Update media type from PointCloud to Image ### How to test <!-- Describe the testing procedure for reviewers, if changes are not fully covered by unit tests or manual testing can be complicated. --> - Add unit test ### Checklist <!-- Put an 'x' in all the boxes that apply --> - [X] I have added unit tests to cover my changes.​ - [ ] I have added integration tests to cover my changes.​ - [X] I have added the description of my changes into [CHANGELOG](https://github.com/openvinotoolkit/datumaro/blob/develop/CHANGELOG.md).​ - [ ] I have updated the [documentation](https://github.com/openvinotoolkit/datumaro/tree/develop/docs) accordingly ### License - [ ] I submit _my code changes_ under the same [MIT License](https://github.com/openvinotoolkit/datumaro/blob/develop/LICENSE) that covers the project. Feel free to contact the maintainers if that's a concern. - [ ] I have updated the license header for each file (see an example below). ```python # Copyright (C) 2024 Intel Corporation # # SPDX-License-Identifier: MIT ```
1 parent e96dbe2 commit fcdb37d

File tree

20 files changed

+284
-29
lines changed

20 files changed

+284
-29
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### New features
1111
- Support KITTI 3D format
1212
(<https://github.com/openvinotoolkit/datumaro/pull/1619>)
13+
(<https://github.com/openvinotoolkit/datumaro/pull/1621>)
1314
- Add PseudoLabeling transform for unlabeled dataset
1415
(<https://github.com/openvinotoolkit/datumaro/pull/1594>)
1516

src/datumaro/plugins/data_formats/kitti_3d/base.py

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,18 @@
44

55
import glob
66
import logging
7+
import os
78
import os.path as osp
89
from typing import List, Optional, Type, TypeVar
910

10-
from datumaro.components.annotation import AnnotationType, Bbox, LabelCategories
11+
from datumaro.components.annotation import AnnotationType, Bbox
1112
from datumaro.components.dataset_base import DatasetItem, SubsetBase
1213
from datumaro.components.errors import InvalidAnnotationError
1314
from datumaro.components.importer import ImportContext
14-
from datumaro.components.media import Image, PointCloud
15+
from datumaro.components.media import Image
1516
from datumaro.util.image import find_images
1617

17-
from .format import Kitti3dPath
18+
from .format import Kitti3DLabelMap, Kitti3dPath, make_kitti3d_categories
1819

1920
T = TypeVar("T")
2021

@@ -30,26 +31,37 @@ def __init__(
3031
ctx: Optional[ImportContext] = None,
3132
):
3233
assert osp.isdir(path), path
33-
super().__init__(subset=subset, media_type=PointCloud, ctx=ctx)
3434

3535
self._path = path
3636

37-
common_attrs = {"truncated", "occluded", "alpha", "dimensions", "location", "rotation_y"}
38-
self._categories = {AnnotationType.label: LabelCategories(attributes=common_attrs)}
37+
if not subset:
38+
folder_path = path.rsplit(Kitti3dPath.LABEL_DIR, 1)[0]
39+
img_dir = osp.join(folder_path, Kitti3dPath.IMAGE_DIR)
40+
if any(os.path.isdir(os.path.join(img_dir, item)) for item in os.listdir(img_dir)):
41+
subset = osp.split(path)[-1]
42+
self._path = folder_path
43+
super().__init__(subset=subset, ctx=ctx)
44+
45+
self._categories = make_kitti3d_categories(Kitti3DLabelMap)
3946
self._items = self._load_items()
4047

4148
def _load_items(self) -> List[DatasetItem]:
4249
items = []
50+
4351
image_dir = osp.join(self._path, Kitti3dPath.IMAGE_DIR)
4452
image_path_by_id = {
45-
osp.splitext(osp.relpath(p, image_dir))[0]: p
53+
osp.split(osp.splitext(osp.relpath(p, image_dir))[0])[-1]: p
4654
for p in find_images(image_dir, recursive=True)
4755
}
4856

49-
ann_dir = osp.join(self._path, Kitti3dPath.LABEL_DIR)
57+
if self._subset == "default":
58+
ann_dir = osp.join(self._path, Kitti3dPath.LABEL_DIR)
59+
else:
60+
ann_dir = osp.join(self._path, Kitti3dPath.LABEL_DIR, self._subset)
61+
5062
label_categories = self._categories[AnnotationType.label]
5163

52-
for labels_path in sorted(glob.glob(osp.join(ann_dir, "*.txt"), recursive=True)):
64+
for labels_path in sorted(glob.glob(osp.join(ann_dir, "**", "*.txt"), recursive=True)):
5365
item_id = osp.splitext(osp.relpath(labels_path, ann_dir))[0]
5466
anns = []
5567

@@ -116,17 +128,18 @@ def _load_items(self) -> List[DatasetItem]:
116128
if image:
117129
image = Image.from_file(path=image)
118130

131+
if self._subset == "default":
132+
calib_path = osp.join(self._path, Kitti3dPath.CALIB_DIR, item_id + ".txt")
133+
else:
134+
calib_path = osp.join(
135+
self._path, Kitti3dPath.CALIB_DIR, self._subset, item_id + ".txt"
136+
)
119137
items.append(
120138
DatasetItem(
121139
id=item_id,
122140
subset=self._subset,
123-
media=PointCloud.from_file(
124-
path=osp.join(self._path, Kitti3dPath.PCD_DIR, item_id + ".bin"),
125-
extra_images=[image],
126-
),
127-
attributes={
128-
"calib_path": osp.join(self._path, Kitti3dPath.CALIB_DIR, item_id + ".txt")
129-
},
141+
media=image,
142+
attributes={"calib_path": calib_path},
130143
annotations=anns,
131144
)
132145
)

src/datumaro/plugins/data_formats/kitti_3d/format.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,40 @@
44

55
import os.path as osp
66

7+
from datumaro.components.annotation import AnnotationType, LabelCategories
8+
79

810
class Kitti3dPath:
911
PCD_DIR = osp.join("velodyne")
1012
IMAGE_DIR = "image_2"
1113
LABEL_DIR = "label_2"
1214
CALIB_DIR = "calib"
15+
16+
17+
Kitti3DLabelMap = [
18+
"DontCare",
19+
"Car",
20+
"Pedestrian",
21+
"Van",
22+
"Truck",
23+
"Cyclist",
24+
"Sitter",
25+
"Train",
26+
"Motorcycle",
27+
"Bus",
28+
"Misc",
29+
]
30+
31+
32+
def make_kitti3d_categories(label_map=None):
33+
if label_map is None:
34+
label_map = Kitti3DLabelMap
35+
36+
categories = {}
37+
common_attrs = {"truncated", "occluded", "alpha", "dimensions", "location", "rotation_y"}
38+
label_categories = LabelCategories(attributes=common_attrs)
39+
for label in label_map:
40+
label_categories.add(label)
41+
categories[AnnotationType.label] = label_categories
42+
43+
return categories

src/datumaro/plugins/data_formats/kitti_3d/importer.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#
33
# SPDX-License-Identifier: MIT
44

5+
import os.path as osp
56
from typing import List
67

78
from datumaro.components.errors import DatasetImportError
@@ -16,7 +17,7 @@ class Kitti3dImporter(Importer):
1617

1718
@classmethod
1819
def detect(cls, context: FormatDetectionContext) -> FormatDetectionConfidence:
19-
context.require_file(f"{Kitti3dPath.PCD_DIR}/*.bin")
20+
context.require_file(f"{Kitti3dPath.CALIB_DIR}/*.txt")
2021
cls._check_ann_file(context.require_file(f"{Kitti3dPath.LABEL_DIR}/*.txt"), context)
2122
return FormatDetectionConfidence.MEDIUM
2223

@@ -42,4 +43,11 @@ def get_file_extensions(cls) -> List[str]:
4243

4344
@classmethod
4445
def find_sources(cls, path):
45-
return [{"url": path, "format": "kitti3d"}]
46+
# return [{"url": path, "format": "kitti3d"}]
47+
sources = cls._find_sources_recursive(
48+
path, "", "kitti3d", dirname=Kitti3dPath.LABEL_DIR, file_filter=lambda p: osp.isdir(p)
49+
)
50+
if len(sources) == 0:
51+
return [{"url": path, "format": "kitti3d"}]
52+
else:
53+
return sources
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)