Neolix OD¶
This topic describes how to manage the Neolix OD dataset, which is a dataset with Box3D label type (Fig. 3).
Authorize a Client Instance¶
An accesskey is needed to authenticate identity when using TensorBay.
from tensorbay import GAS
ACCESS_KEY = "Accesskey-*****"
gas = GAS(ACCESS_KEY)
Create Dataset¶
gas.create_dataset("NeolixOD")
Organize Dataset¶
It takes the following steps to organize “Neolix OD” dataset by the Dataset
instance.
Step 1: Write the Catalog¶
A Catalog contains all label information of one dataset, which is typically stored in a json file.
1{
2 "BOX3D": {
3 "categories": [
4 { "name": "Adult" },
5 { "name": "Animal" },
6 { "name": "Barrier" },
7 { "name": "Bicycle" },
8 { "name": "Bicycles" },
9 { "name": "Bus" },
10 { "name": "Car" },
11 { "name": "Child" },
12 { "name": "Cyclist" },
13 { "name": "Motorcycle" },
14 { "name": "Motorcyclist" },
15 { "name": "Trailer" },
16 { "name": "Tricycle" },
17 { "name": "Truck" },
18 { "name": "Unknown" }
19 ],
20 "attributes": [
21 {
22 "name": "Alpha",
23 "type": "number",
24 "description": "Angle of view"
25 },
26 {
27 "name": "Occlusion",
28 "enum": [0, 1, 2],
29 "description": "It indicates the degree of occlusion of objects by other obstacles"
30 },
31 {
32 "name": "Truncation",
33 "type": "boolean",
34 "description": "It indicates whether the object is truncated by the edge of the image"
35 }
36 ]
37 }
38}
The only annotation type for “Neolix OD” is Box3D, and there are 15 category types and 3 attributes types.
Important
See catalog table for more catalogs with different label types.
Step 2: Write the Dataloader¶
A dataloader is needed to organize the dataset into
a Dataset
instance.
1#!/usr/bin/env python3
2#
3# Copyright 2021 Graviti. Licensed under MIT License.
4#
5# pylint: disable=invalid-name
6# pylint: disable=missing-module-docstring
7
8import os
9
10from quaternion import from_rotation_vector
11
12from ...dataset import Data, Dataset
13from ...label import LabeledBox3D
14from .._utility import glob
15
16DATASET_NAME = "NeolixOD"
17
18
19def NeolixOD(path: str) -> Dataset:
20 """Dataloader of the `Neolix OD`_ dataset.
21
22 .. _Neolix OD: https://www.graviti.cn/dataset-detail/NeolixOD
23
24 The file structure should be like::
25
26 <path>
27 bins/
28 <id>.bin
29 labels/
30 <id>.txt
31 ...
32
33 Arguments:
34 path: The root directory of the dataset.
35
36 Returns:
37 Loaded :class:`~tensorbay.dataset.dataset.Dataset` instance.
38
39 """
40 root_path = os.path.abspath(os.path.expanduser(path))
41
42 dataset = Dataset(DATASET_NAME)
43 dataset.load_catalog(os.path.join(os.path.dirname(__file__), "catalog.json"))
44 segment = dataset.create_segment()
45
46 point_cloud_paths = glob(os.path.join(root_path, "bins", "*.bin"))
47
48 for point_cloud_path in point_cloud_paths:
49 data = Data(point_cloud_path)
50 data.label.box3d = []
51
52 point_cloud_id = os.path.basename(point_cloud_path)[:6]
53 label_path = os.path.join(root_path, "labels", f"{point_cloud_id}.txt")
54
55 with open(label_path, encoding="utf-8") as fp:
56 for label_value_raw in fp:
57 label_value = label_value_raw.rstrip().split()
58 label = LabeledBox3D(
59 size=[float(label_value[10]), float(label_value[9]), float(label_value[8])],
60 translation=[
61 float(label_value[11]),
62 float(label_value[12]),
63 float(label_value[13]) + 0.5 * float(label_value[8]),
64 ],
65 rotation=from_rotation_vector((0, 0, float(label_value[14]))),
66 category=label_value[0],
67 attributes={
68 "Occlusion": int(label_value[1]),
69 "Truncation": bool(int(label_value[2])),
70 "Alpha": float(label_value[3]),
71 },
72 )
73 data.label.box3d.append(label)
74
75 segment.append(data)
76 return dataset
See Box3D annotation for more details.
Note
Since the Neolix OD dataloader above is already included in TensorBay, so it uses relative import. However, the regular import should be used when writing a new dataloader.
from tensorbay.dataset import Data, Dataset
from tensorbay.label import LabeledBox3D
There are already a number of dataloaders in TensorBay SDK provided by the community. Thus, instead of writing, importing an available dataloader is also feasible.
from tensorbay.opendataset import NeolixOD
dataset = NeolixOD("path/to/dataset/directory")
Note
Note that catalogs are automatically loaded in available dataloaders, users do not have to write them again.
Important
See dataloader table for dataloaders with different label types.
Visualize Dataset¶
Optionally, the organized dataset can be visualized by Pharos, which is a TensorBay SDK plug-in. This step can help users to check whether the dataset is correctly organized. Please see Visualization for more details.
Upload Dataset¶
The organized “Neolix OD” dataset can be uploaded to tensorBay for sharing, reuse, etc.
dataset_client = gas.upload_dataset(dataset, jobs=8)
dataset_client.commit("initial commit")
Similar with Git, the commit step after uploading can record changes to the dataset as a version. If needed, do the modifications and commit again. Please see Version Control for more details.
Read Dataset¶
Now “Neolix OD” dataset can be read from TensorBay.
dataset = Dataset("NeolixOD", gas)
In dataset “Neolix OD”, there is only one default
Segment: ""
(empty string).
Get a segment by passing the required segment name.
segment = dataset[0]
In the default segment, there is a sequence of data, which can be obtained by index.
data = segment[0]
In each data, there is a sequence of Box3D annotations,
label_box3d = data.label.box3d[0]
category = label_box3d.category
attributes = label_box3d.attributes
There is only one label type in “Neolix OD” dataset, which is box3d
.
The information stored in category is
one of the category names in “categories” list of catalog.json.
The information stored in attributes
is one of the attributes in “attributes” list of catalog.json.
See Box3D label format for more details.
Delete Dataset¶
gas.delete_dataset("NeolixOD")