Neolix OD#

This topic describes how to manage the Neolix OD dataset, which is a dataset with Box3D label type (Fig. 2).

../../_images/example-Box3D.png

Fig. 2 The preview of a point cloud from “Neolix OD” with Box3D labels.#

Authorize a Client Instance#

An accesskey is needed to authenticate identity when using TensorBay.

from tensorbay import GAS

# Please visit `https://gas.graviti.cn/tensorbay/developer` to get the AccessKey.
gas = GAS("<YOUR_ACCESSKEY>")

Create Dataset#

gas.create_dataset("NeolixOD")

Organize Dataset#

Normally, dataloader.py and catalog.json are required to organize the “Neolix OD” dataset into the Dataset instance. In this example, they are stored in the same directory like:

Neolix OD/
    catalog.json
    dataloader.py

Step 1: Write the Catalog#

A Catalog contains all label information of one dataset, which is typically stored in a json file like catalog.json.

 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.

Note

By passing the path of the catalog.json, load_catalog() supports loading the catalog into dataset.

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
 7"""Dataloader of NeolixOD dataset."""
 8
 9import os
10
11from quaternion import from_rotation_vector
12
13from tensorbay.dataset import Data, Dataset
14from tensorbay.label import LabeledBox3D
15from tensorbay.opendataset._utility import glob
16
17DATASET_NAME = "NeolixOD"
18
19
20def NeolixOD(path: str) -> Dataset:
21    """`Neolix OD <https://gas.graviti.cn/dataset\
22    /graviti-open-dataset/NeolixOD>`_ dataset.
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.

There are already a number of dataloaders in TensorBay SDK provided by the community. Thus, in addition to writing, importing an available dataloader is also feasible.

from tensorbay.opendataset import NeolixOD

dataset = NeolixOD("<path/to/dataset>")

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 segment: default. Get a segment by passing the required segment name or the index.

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")