Working with a continuous MCAP Scene? See MCAP Scene labels for timestamp-based 3D events, embedded point cloud segmentations, time-series ranges, and SDK-supported JSON export and import.
Cuboids
Basic This example includes the following:- Cuboid labeling
- Cuboid labeling
- Radio button options
- Checklist options
- Text input
# Import dependencies
from encord import EncordUserClient, Project
from encord.objects import Object
from encord.objects.coordinates import CuboidCoordinates
# User input
SSH_PATH = "/Users/chris-encord/ssh-private-key.txt" # Replace with the file path to your SSH private key
PROJECT_ID = "00000000-0000-0000-0000-000000000000" # Replace with the unique ID for the Project
BUNDLE_SIZE = 100
# Create user client using ssh key
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
# For US platform users use "https://api.us.encord.com"
domain="https://api.encord.com",
)
# Get project for which labels are to be added
project: Project = user_client.get_project(PROJECT_ID)
# Create radio button attribute for Person type
ontology_structure = project.ontology_structure
# Find a cuboid annotation object in the project ontology
cuboid_ontology_object: Object = ontology_structure.get_child_by_title(title="Person", type_=Object)
# Dictionary of labels per data unit and per frame with Person
pcd_labels = {
"scene-1094": {
0: {
"label_ref": "person_001",
"coordinates": CuboidCoordinates(
position=(9, 9, 9),
orientation=(0.11, 0.77, 0.33),
size=(0.2, 0.2, 0.2)
),
}
},
"scene-0916": {
0: [
{
"label_ref": "person_002",
"coordinates": CuboidCoordinates(
position=(0.4, 0.4, 0.4),
orientation=(0.0, 0.0, 0.4),
size=(0.1, 0.1, 0.1)
),
},
{
"label_ref": "person_003",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0),
orientation=(0.0, 0.0, 0.1),
size=(0.5, 0.5, 0.5)
),
},
{
"label_ref": "person_004",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0),
orientation=(0.0, 0.0, 0.1),
size=(0.7, 0.7, 0.7)
),
},
],
},
"scene-0796": {
0: {
"label_ref": "person_005",
"coordinates": CuboidCoordinates(
position=(0.4, 0.4, 0.0),
orientation=(0.0, 0.0, 0.4),
size=(0.12, 0.12, 0.12)
),
},
2: [
{
"label_ref": "person_006",
"coordinates": CuboidCoordinates(
position=(0.1, 0.1, 0.0),
orientation=(0.0, 0.0, 0.2),
size=(0.5, 0.5, 0.5)
),
},
{
"label_ref": "person_007",
"coordinates": CuboidCoordinates(
position=(0.1, 0.1, 0.0),
orientation=(0.0, 0.0, 0.2),
size=(0.0132, 0.0132, 0.0132)
),
},
{
"label_ref": "person_008",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0),
orientation=(0.0, 0.0, 0.1),
size=(0.8, 0.8, 0.8)
),
},
],
},
"scene-1100": {
0: {
"label_ref": "person_009",
"coordinates": CuboidCoordinates(
position=(0.4, 0.4, 0.0),
orientation=(0.0, 0.0, 0.4),
size=(0.012, 0.012, 0.012)
),
},
3: [
{
"label_ref": "person_010",
"coordinates": CuboidCoordinates(
position=(0.4, 0.4, 0.0),
orientation=(0.0, 0.0, 0.4),
size=(0.5, 0.5, 0.5)
),
},
{
"label_ref": "person_011",
"coordinates": CuboidCoordinates(
position=(0.3, 0.3, 0.0),
orientation=(0.0, 0.0, 0.3),
size=(0.13, 0.13, 0.13)
),
},
{
"label_ref": "person_012",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0),
orientation=(0.0, 0.0, 0.1),
size=(0.9, 0.9, 0.9)
),
},
],
},
"scene-0655": {
13: [
{
"label_ref": "person_013",
"coordinates": CuboidCoordinates(
position=(0.5, 0.5, 0.0),
orientation=(0.0, 0.0, 0.5),
size=(0.11, 0.11, 0.11)
),
},
{
"label_ref": "person_014",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0),
orientation=(0.0, 0.0, 0.2),
size=(0.6, 0.6, 0.6)
),
},
{
"label_ref": "person_015",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0),
orientation=(0.0, 0.0, 0.1),
size=(0.8, 0.8, 0.8)
),
},
],
14: [
{
"label_ref": "person_016",
"coordinates": CuboidCoordinates(
position=(0.5, 0.5, 0.0),
orientation=(0.0, 0.0, 0.5),
size=(0.3, 0.3, 0.3)
),
},
{
"label_ref": "person_014",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0),
orientation=(0.0, 0.0, 0.2),
size=(0.6, 0.6, 0.6)
),
},
{
"label_ref": "person_017",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0),
orientation=(0.0, 0.0, 0.1),
size=(0.8, 0.8, 0.8)
),
},
],
15: [
{
"label_ref": "person_016",
"coordinates": CuboidCoordinates(
position=(0.5, 0.5, 0.0),
orientation=(0.0, 0.0, 0.5),
size=(0.1, 0.1, 0.1)
),
},
{
"label_ref": "person_014",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0),
orientation=(0.0, 0.0, 0.2),
size=(0.6, 0.6, 0.6)
),
},
{
"label_ref": "person_017",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0),
orientation=(0.0, 0.0, 0.1),
size=(0.8, 0.8, 0.8)
),
},
],
},
}
# Initialize label rows
label_row_map = {}
with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
for data_title in pcd_labels.keys():
rows = project.list_label_rows_v2(data_title_eq=data_title)
if not rows:
print(f"Skipping: No label row found for {data_title}")
continue
lr = rows[0]
lr.initialise_labels(bundle=bundle)
label_row_map[data_title] = lr
# Create instances
label_rows_to_save = []
for data_title, frames in pcd_labels.items():
lr = label_row_map.get(data_title)
if not lr:
continue
instances_by_ref = {}
for frame_no, items in frames.items():
# normalize to list
items = items if isinstance(items, list) else [items]
for item in items:
ref = item["label_ref"]
coords = item["coordinates"]
if ref not in instances_by_ref:
instances_by_ref[ref] = cuboid_ontology_object.create_instance()
instances_by_ref[ref].set_for_frames(coordinates=coords, frames=frame_no)
# Add only instances that have at least one frame
for inst in instances_by_ref.values():
if inst.get_annotation_frames():
lr.add_object_instance(inst)
label_rows_to_save.append(lr)
# Save all label rows
with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
for lr in label_rows_to_save:
lr.save(bundle=bundle)
print(f"Saved label row for {lr.data_title}")
# Import dependencies
from encord import EncordUserClient, Project
from encord.objects import ChecklistAttribute, Object, ObjectInstance, Option, RadioAttribute, TextAttribute
from encord.objects.attributes import NumericAttribute
from encord.objects.coordinates import CuboidCoordinates
# User input
SSH_PATH = "/Users/chris-encord/ssh-private-key.txt" # Replace with the file path to your SSH private key
PROJECT_ID = "00000000-0000-0000-0000-000000000000" # Replace with the unique ID for the Project
BUNDLE_SIZE = 100
# Create user client using ssh key
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
# For US platform users use "https://api.us.encord.com"
domain="https://api.encord.com",
)
# Get project for which labels are to be added
project: Project = user_client.get_project(PROJECT_ID)
ontology_structure = project.ontology_structure
# Find the cuboid object in the project ontology
cuboid_ontology_object: Object = ontology_structure.get_child_by_title(title="Person", type_=Object)
# Look up the attributes under the Person object. get_child_by_title raises an error if a title isn't found.
person_type_radio_attribute = cuboid_ontology_object.get_child_by_title(title="Type?", type_=RadioAttribute)
other_person_option_text_attribute = cuboid_ontology_object.get_child_by_title(
title="Specify Person type", type_=TextAttribute
)
# For each Person type: the checklist attribute that holds its qualities, and the key for them in the data below
quality_checklists = {
"Adult": ("Adult Qualities?", "adult_quality_options"),
"Adolescent": ("Adolescent Qualities?", "adolescent_quality_options"),
"Child": ("Child Qualities?", "child_quality_options"),
}
# Dictionary of labels per data unit and per frame with Person type specified, including quality options
pcd_labels = {
"scene-1094": {
0: {
"label_ref": "person_001",
"coordinates": CuboidCoordinates(position=(9, 9, 9), orientation=(0.11, 0.77, 0.33), size=(0.2, 0.2, 0.2)),
"person_type": "Adult",
"adult_quality_options": "Moving, Well lit",
}
},
"scene-0916": {
0: [
{
"label_ref": "person_002",
"coordinates": CuboidCoordinates(
position=(0.4, 0.4, 0.4), orientation=(0.0, 0.0, 0.4), size=(0.1, 0.1, 0.1)
),
"person_type": "Adolescent",
"adolescent_quality_options": "Moving, Well lit, Fully visible",
},
{
"label_ref": "person_003",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0), orientation=(0.0, 0.0, 0.1), size=(0.5, 0.5, 0.5)
),
"person_type": "Child",
"child_quality_options": "Moving",
},
{
"label_ref": "person_004",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0), orientation=(0.0, 0.0, 0.1), size=(0.7, 0.7, 0.7)
),
"person_type": "Other Person type",
"Specify Person type": "Person with a baby stroller",
},
],
},
"scene-0796": {
0: {
"label_ref": "person_005",
"coordinates": CuboidCoordinates(
position=(0.4, 0.4, 0.0), orientation=(0.0, 0.0, 0.4), size=(0.12, 0.12, 0.12)
),
"person_type": "Adult",
"adult_quality_options": "Moving, Well lit",
},
2: [
{
"label_ref": "person_006",
"coordinates": CuboidCoordinates(
position=(0.1, 0.1, 0.0), orientation=(0.0, 0.0, 0.2), size=(0.5, 0.5, 0.5)
),
"person_type": "Adolescent",
"adolescent_quality_options": "Fully visible",
},
{
"label_ref": "person_007",
"coordinates": CuboidCoordinates(
position=(0.1, 0.1, 0.0), orientation=(0.0, 0.0, 0.2), size=(0.0132, 0.0132, 0.0132)
),
"person_type": "Child",
"child_quality_options": "Moving",
},
{
"label_ref": "person_008",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0), orientation=(0.0, 0.0, 0.1), size=(0.8, 0.8, 0.8)
),
"person_type": "Other Person type",
"Specify Person type": "Person with a baby stroller",
},
],
},
"scene-1100": {
0: {
"label_ref": "person_009",
"coordinates": CuboidCoordinates(
position=(0.4, 0.4, 0.0), orientation=(0.0, 0.0, 0.4), size=(0.012, 0.012, 0.012)
),
"person_type": "Adult",
"adult_quality_options": "Moving",
},
3: [
{
"label_ref": "person_010",
"coordinates": CuboidCoordinates(
position=(0.4, 0.4, 0.0), orientation=(0.0, 0.0, 0.4), size=(0.5, 0.5, 0.5)
),
"person_type": "Adolescent",
"adolescent_quality_options": "Moving, Well lit, Fully visible",
},
{
"label_ref": "person_011",
"coordinates": CuboidCoordinates(
position=(0.3, 0.3, 0.0), orientation=(0.0, 0.0, 0.3), size=(0.13, 0.13, 0.13)
),
"person_type": "Child",
"child_quality_options": "Moving",
},
{
"label_ref": "person_012",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0), orientation=(0.0, 0.0, 0.1), size=(0.9, 0.9, 0.9)
),
"person_type": "Other Person type",
"Specify Person type": "Person with a baby stroller",
},
],
},
"scene-0655": {
13: [
{
"label_ref": "person_013",
"coordinates": CuboidCoordinates(
position=(0.5, 0.5, 0.0), orientation=(0.0, 0.0, 0.5), size=(0.11, 0.11, 0.11)
),
"person_type": "Child",
"child_quality_options": "Moving",
},
{
"label_ref": "person_014",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0), orientation=(0.0, 0.0, 0.2), size=(0.6, 0.6, 0.6)
),
"person_type": "Adult",
"adult_quality_options": "Moving, Well lit, Fully visible",
},
{
"label_ref": "person_015",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0), orientation=(0.0, 0.0, 0.1), size=(0.8, 0.8, 0.8)
),
"person_type": "Other Person type",
"Specify Person type": "Person walking a dog",
},
],
14: [
{
"label_ref": "person_016",
"coordinates": CuboidCoordinates(
position=(0.5, 0.5, 0.0), orientation=(0.0, 0.0, 0.5), size=(0.3, 0.3, 0.3)
),
"person_type": "Child",
"child_quality_options": "Moving",
},
{
"label_ref": "person_014",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0), orientation=(0.0, 0.0, 0.2), size=(0.6, 0.6, 0.6)
),
"person_type": "Adult",
"adult_quality_options": "Moving, Well lit, Fully visible",
},
{
"label_ref": "person_017",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0), orientation=(0.0, 0.0, 0.1), size=(0.8, 0.8, 0.8)
),
"person_type": "Other Person type",
"Specify Person type": "Person walking a dog",
},
],
15: [
{
"label_ref": "person_016",
"coordinates": CuboidCoordinates(
position=(0.5, 0.5, 0.0), orientation=(0.0, 0.0, 0.5), size=(0.1, 0.1, 0.1)
),
"person_type": "Child",
"child_quality_options": "Moving",
},
{
"label_ref": "person_014",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0), orientation=(0.0, 0.0, 0.2), size=(0.6, 0.6, 0.6)
),
"person_type": "Adult",
"adult_quality_options": "Moving, Well lit, Fully visible",
},
{
"label_ref": "person_017",
"coordinates": CuboidCoordinates(
position=(0.2, 0.2, 0.0), orientation=(0.0, 0.0, 0.1), size=(0.8, 0.8, 0.8)
),
"person_type": "Other Person type",
"Specify Person type": "Person walking a dog",
},
],
},
}
# Cache initialized label rows
label_row_map = {}
# Step 1: Initialize all label rows using a bundle
with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
for data_unit in pcd_labels.keys():
label_rows = project.list_label_rows_v2(data_title_eq=data_unit)
assert isinstance(label_rows, list), f"Expected list of label rows for '{data_unit}', got {type(label_rows)}"
if not label_rows:
print(f"Skipping: No label row found for {data_unit}")
continue
label_row = label_rows[0]
label_row.initialise_labels(bundle=bundle)
assert label_row.ontology_structure is not None, f"Ontology not initialized for label row: {data_unit}"
label_row_map[data_unit] = label_row # Cache initialized label row for later use
# Step 2: Process all frames/annotations and prepare label rows to save
label_rows_to_save = []
for data_unit, frame_coordinates in pcd_labels.items():
label_row = label_row_map.get(data_unit)
if not label_row:
print(f"Skipping: No initialized label row found for {data_unit}")
continue
object_instances_by_label_ref = {}
# Loop through the frames for the current data unit
for frame_number, items in frame_coordinates.items():
assert isinstance(frame_number, int), f"Frame number must be int, got {type(frame_number)}"
if not isinstance(items, list):
items = [items]
for item in items:
label_ref = item["label_ref"]
coord = item["coordinates"]
person_type = item["person_type"]
# Check if label_ref already exists for reusability
if label_ref not in object_instances_by_label_ref:
cuboid_object_instance: ObjectInstance = cuboid_ontology_object.create_instance()
object_instances_by_label_ref[label_ref] = cuboid_object_instance
# Set the Person type: look up the radio button option by its title
person_type_option = person_type_radio_attribute.get_child_by_title(title=person_type, type_=Option)
cuboid_object_instance.set_answer(attribute=person_type_radio_attribute, answer=person_type_option)
if person_type == "Other Person type":
text_answer = item.get("Specify Person type", "")
cuboid_object_instance.set_answer(attribute=other_person_option_text_attribute, answer=text_answer)
else:
# Set the checklist answers: look up each quality option by its title
checklist_title, quality_key = quality_checklists[person_type]
checklist_attribute = cuboid_ontology_object.get_child_by_title(
title=checklist_title, type_=ChecklistAttribute
)
quality_options = [quality for quality in item.get(quality_key, "").split(", ") if quality]
checklist_answers = [
checklist_attribute.get_child_by_title(title=quality, type_=Option) for quality in quality_options
]
if checklist_answers:
cuboid_object_instance.set_answer(
attribute=checklist_attribute, answer=checklist_answers, overwrite=True
)
else:
# Reuse existing instance across frames
cuboid_object_instance = object_instances_by_label_ref[label_ref]
# Assign the object to the frame and track it
cuboid_object_instance.set_for_frames(coordinates=coord, frames=frame_number)
# Add object instances to label_row **only if they have frames assigned**
for cuboid_object_instance in object_instances_by_label_ref.values():
assert isinstance(cuboid_object_instance, ObjectInstance), "Expected ObjectInstance type"
if cuboid_object_instance.get_annotation_frames(): # Ensures it has at least one frame
label_row.add_object_instance(cuboid_object_instance)
label_rows_to_save.append(label_row)
# Step 3: Save all label rows using a bundle
with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
for label_row in label_rows_to_save:
assert label_row is not None, "Trying to save a None label row"
label_row.save(bundle=bundle)
print(f"Saved label row for {label_row.data_title}")
print("Labels with Person type radio buttons, checklist attributes, and text labels added for all data units.")
Polylines 3D
Basic This example includes the following:- Polyline 3D labeling
- Polyline 3D labeling
- Radio button options
- Checklist options
- Text input
# Import dependencies
from encord import EncordUserClient, Project
from encord.objects import Object
from encord.objects.coordinates import PointCoordinate3D, PolylineCoordinates
# User input
SSH_PATH = "/Users/chris-encord/ssh-private-key.txt" # Replace with the file path to your SSH private key
PROJECT_ID = "00000000-0000-0000-0000-000000000000" # Replace with the unique ID for the Project
BUNDLE_SIZE = 100
# Create user client using ssh key
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
# For US platform users use "https://api.us.encord.com"
domain="https://api.encord.com",
)
# Get project for which labels are to be added
project: Project = user_client.get_project(PROJECT_ID)
# Get the ontology
ontology_structure = project.ontology_structure
# Find a polyline annotation object in the project ontology
polyline_ontology_object: Object = ontology_structure.get_child_by_title(title="Object of Interest", type_=Object)
# Dictionary of labels per data unit and per frame with Object of Interest
pcd_labels = {
"scene-1094": {
0: {
"label_ref": "ooi_001",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(2.013, 2.02, 2.015),
PointCoordinate3D(3.033, 3.033, 3.033),
PointCoordinate3D(4.053, 4.023, 4.017),
PointCoordinate3D(0.043, 0.013, 0.043),
]
),
}
},
"scene-0916": {
0: [
{
"label_ref": "ooi_002",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(3.000, 2.300, 0.000),
PointCoordinate3D(3.300, 3.300, 0.000),
PointCoordinate3D(5.300, 3.300, 0.000),
PointCoordinate3D(4.300, 1.300, 0.000),
]
),
},
{
"label_ref": "ooi_003",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(4.300, 5.300, 0.000),
PointCoordinate3D(6.300, 6.300, 0.000),
PointCoordinate3D(8.300, 5.300, 0.000),
PointCoordinate3D(7.300, 4.300, 0.000),
]
),
},
{
"label_ref": "ooi_004",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(7.300, 2.300, 0.000),
PointCoordinate3D(9.300, 3.300, 0.000),
PointCoordinate3D(11.300, 2.300, 0.000),
PointCoordinate3D(10.300, 1.300, 0.000),
]
),
},
],
},
"scene-0796": {
0: {
"label_ref": "ooi_005",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(1.300, 2.300, 0.000),
PointCoordinate3D(3.300, 3.300, 0.000),
PointCoordinate3D(5.300, 2.300, 0.000),
PointCoordinate3D(4.300, 1.300, 0.000),
]
),
},
2: [
{
"label_ref": "ooi_006",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(1.300, 2.300, 0.000),
PointCoordinate3D(3.300, 3.300, 0.000),
PointCoordinate3D(5.300, 2.300, 0.000),
PointCoordinate3D(4.300, 1.300, 0.000),
]
),
},
{
"label_ref": "ooi_007",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(4.300, 5.300, 0.000),
PointCoordinate3D(6.300, 6.300, 0.000),
PointCoordinate3D(8.300, 5.300, 0.000),
PointCoordinate3D(7.300, 4.300, 0.000),
]
),
},
{
"label_ref": "ooi_008",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(7.300, 2.300, 0.000),
PointCoordinate3D(9.300, 3.300, 0.000),
PointCoordinate3D(11.300, 2.300, 0.000),
PointCoordinate3D(10.300, 1.300, 0.000),
]
),
},
],
},
"scene-1100": {
0: {
"label_ref": "ooi_009",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(1.300, 2.300, 0.000),
PointCoordinate3D(3.300, 3.300, 0.000),
PointCoordinate3D(5.300, 2.300, 0.000),
PointCoordinate3D(4.300, 1.300, 0.000),
]
),
},
3: [
{
"label_ref": "ooi_010",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(1.300, 2.300, 0.000),
PointCoordinate3D(3.300, 3.300, 0.000),
PointCoordinate3D(5.300, 2.300, 0.000),
PointCoordinate3D(4.300, 1.300, 0.000),
]
),
},
{
"label_ref": "ooi_011",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(4.300, 5.300, 0.000),
PointCoordinate3D(6.300, 6.300, 0.000),
PointCoordinate3D(8.300, 5.300, 0.000),
PointCoordinate3D(7.300, 4.300, 0.000),
]
),
},
{
"label_ref": "ooi_012",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(7.300, 2.300, 0.000),
PointCoordinate3D(9.300, 3.300, 0.000),
PointCoordinate3D(11.300, 2.300, 0.000),
PointCoordinate3D(10.300, 1.300, 0.000),
]
),
},
],
},
"scene-0655": {
103: [
{
"label_ref": "ooi_013",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(1.300, 2.300, 0.000),
PointCoordinate3D(3.300, 3.300, 0.000),
PointCoordinate3D(5.300, 2.300, 0.000),
PointCoordinate3D(4.300, 1.300, 0.000),
]
),
},
{
"label_ref": "ooi_014",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(4.300, 5.300, 0.000),
PointCoordinate3D(6.300, 6.300, 0.000),
PointCoordinate3D(8.300, 5.300, 0.000),
PointCoordinate3D(7.300, 4.300, 0.000),
]
),
},
{
"label_ref": "ooi_015",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(7.300, 2.300, 0.000),
PointCoordinate3D(9.300, 3.300, 0.000),
PointCoordinate3D(11.300, 2.300, 0.000),
PointCoordinate3D(10.300, 1.300, 0.000),
]
),
},
],
104: [
{
"label_ref": "ooi_016",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(1.300, 2.300, 0.000),
PointCoordinate3D(3.300, 3.300, 0.000),
PointCoordinate3D(5.300, 2.300, 0.000),
PointCoordinate3D(4.300, 1.300, 0.000),
]
),
},
{
"label_ref": "ooi_014",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(4.130, 5.230, 0.000),
PointCoordinate3D(6.130, 6.230, 0.000),
PointCoordinate3D(8.130, 5.230, 0.000),
PointCoordinate3D(7.130, 4.230, 0.000),
]
),
},
{
"label_ref": "ooi_017",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(7.300, 2.300, 0.000),
PointCoordinate3D(9.300, 3.300, 0.000),
PointCoordinate3D(11.300, 2.300, 0.000),
PointCoordinate3D(10.300, 1.300, 0.000),
]
),
},
],
105: [
{
"label_ref": "ooi_016",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(1.130, 2.230, 0.000),
PointCoordinate3D(3.130, 3.230, 0.000),
PointCoordinate3D(5.130, 2.230, 0.000),
PointCoordinate3D(4.130, 1.230, 0.000),
]
),
},
{
"label_ref": "ooi_014",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(4.330, 5.530, 0.000),
PointCoordinate3D(6.330, 6.530, 0.000),
PointCoordinate3D(8.330, 5.530, 0.000),
PointCoordinate3D(7.330, 4.530, 0.000),
]
),
},
{
"label_ref": "ooi_017",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(7.130, 2.230, 0.000),
PointCoordinate3D(9.130, 3.230, 0.000),
PointCoordinate3D(11.130, 2.230, 0.000),
PointCoordinate3D(10.130, 1.230, 0.000),
]
),
},
],
},
}
# Initialize label rows
label_row_map = {}
with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
for data_title in pcd_labels.keys():
rows = project.list_label_rows_v2(data_title_eq=data_title)
if not rows:
print(f"Skipping: No label row found for {data_title}")
continue
lr = rows[0]
lr.initialise_labels(bundle=bundle)
label_row_map[data_title] = lr
# Create instances
label_rows_to_save = []
for data_title, frames in pcd_labels.items():
lr = label_row_map.get(data_title)
if not lr:
continue
instances_by_ref = {}
for frame_no, items in frames.items():
# normalize to list
items = items if isinstance(items, list) else [items]
for item in items:
ref = item["label_ref"]
coords = item["coordinates"]
if ref not in instances_by_ref:
instances_by_ref[ref] = polyline_ontology_object.create_instance()
instances_by_ref[ref].set_for_frames(coordinates=coords, frames=frame_no)
# Add only instances that have at least one frame
for inst in instances_by_ref.values():
if inst.get_annotation_frames():
lr.add_object_instance(inst)
label_rows_to_save.append(lr)
# Save all label rows
with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
for lr in label_rows_to_save:
lr.save(bundle=bundle)
print(f"Saved label row for {lr.data_title}")
# Import dependencies
from pathlib import Path
from encord import EncordUserClient, Project
from encord.objects import (
ChecklistAttribute,
Object,
ObjectInstance,
Option,
RadioAttribute,
TextAttribute,
)
from encord.objects.attributes import NumericAttribute
from encord.objects.coordinates import PointCoordinate3D, PolylineCoordinates
# User input
SSH_PATH = "/Users/chris-encord/ssh-private-key.txt" # Replace with the file path to your SSH private key
PROJECT_ID = "00000000-0000-0000-0000-000000000000" # Replace with the unique ID for the Project
BUNDLE_SIZE = 100
# Create user client using ssh key
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
# For US platform users use "https://api.us.encord.com"
domain="https://api.encord.com",
)
# Get project for which labels are to be added
project: Project = user_client.get_project(PROJECT_ID)
# Get ontology structure
ontology_structure = project.ontology_structure
# Get polyline object for Object of Interest
polyline_ontology_object: Object = ontology_structure.get_child_by_title(title="Object of Interest", type_=Object)
# Look up the attributes under the Object of Interest object. get_child_by_title raises an error if a title isn't found.
ooi_type_radio_attribute = polyline_ontology_object.get_child_by_title(title="Type?", type_=RadioAttribute)
other_ooi_option_text_attribute = polyline_ontology_object.get_child_by_title(title="Specify type", type_=TextAttribute)
# For each Object of Interest type: the checklist attribute that holds its qualities, and the key for them in the data below
quality_checklists = {
"Curb": ("Qualities?", "curb_quality_options"),
"Lane divider": ("Lane divider Qualities?", "lane_divider_quality_options"),
"Zebra crossing": ("Zebra crossing Qualities?", "zebra_crossing_quality_options"),
}
# Dictionary of labels per data unit and per frame with type specified, including quality options
pcd_labels = {
"scene-1094": {
0: {
"label_ref": "ooi_001",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(2.013, 2.02, 2.015),
PointCoordinate3D(3.033, 3.033, 3.033),
PointCoordinate3D(4.053, 4.023, 4.017),
PointCoordinate3D(5.043, 5.013, 5.043),
]
),
"ooi_type": "Curb",
"curb_quality_options": "Good quality, Well lit",
}
},
"scene-0916": {
0: [
{
"label_ref": "ooi_002",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(3.000, 2.300, 0.000),
PointCoordinate3D(3.300, 3.300, 0.000),
PointCoordinate3D(5.300, 3.300, 0.000),
PointCoordinate3D(4.300, 1.300, 0.000),
]
),
"ooi_type": "Lane divider",
"lane_divider_quality_options": "Good quality, Well lit, Fully visible",
},
{
"label_ref": "ooi_003",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(4.300, 5.300, 0.000),
PointCoordinate3D(6.300, 6.300, 0.000),
PointCoordinate3D(8.300, 5.300, 0.000),
PointCoordinate3D(7.300, 4.300, 0.000),
]
),
"ooi_type": "Zebra crossing",
"zebra_crossing_quality_options": "Good quality",
},
{
"label_ref": "ooi_004",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(7.300, 2.300, 0.000),
PointCoordinate3D(9.300, 3.300, 0.000),
PointCoordinate3D(11.300, 2.300, 0.000),
PointCoordinate3D(10.300, 1.300, 0.000),
]
),
"ooi_type": "Other",
"Type": "Cane",
},
],
},
"scene-0796": {
0: {
"label_ref": "ooi_005",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(1.300, 2.300, 0.000),
PointCoordinate3D(3.300, 3.300, 0.000),
PointCoordinate3D(5.300, 2.300, 0.000),
PointCoordinate3D(4.300, 1.300, 0.000),
]
),
"ooi_type": "Curb",
"curb_quality_options": "Good quality, Well lit",
},
2: [
{
"label_ref": "ooi_006",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(1.300, 2.300, 0.000),
PointCoordinate3D(3.300, 3.300, 0.000),
PointCoordinate3D(5.300, 2.300, 0.000),
PointCoordinate3D(4.300, 1.300, 0.000),
]
),
"ooi_type": "Lane divider",
"lane_divider_quality_options": "Fully visible",
},
{
"label_ref": "ooi_007",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(4.300, 5.300, 0.000),
PointCoordinate3D(6.300, 6.300, 0.000),
PointCoordinate3D(8.300, 5.300, 0.000),
PointCoordinate3D(7.300, 4.300, 0.000),
]
),
"ooi_type": "Zebra crossing",
"zebra_crossing_quality_options": "Good quality",
},
{
"label_ref": "ooi_008",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(7.300, 2.300, 0.000),
PointCoordinate3D(9.300, 3.300, 0.000),
PointCoordinate3D(11.300, 2.300, 0.000),
PointCoordinate3D(10.300, 1.300, 0.000),
]
),
"ooi_type": "Other",
"Type": "Cane",
},
],
},
"scene-1100": {
0: {
"label_ref": "ooi_009",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(1.300, 2.300, 0.000),
PointCoordinate3D(3.300, 3.300, 0.000),
PointCoordinate3D(5.300, 2.300, 0.000),
PointCoordinate3D(4.300, 1.300, 0.000),
]
),
"ooi_type": "Curb",
"curb_quality_options": "Good quality",
},
3: [
{
"label_ref": "ooi_010",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(1.300, 2.300, 0.000),
PointCoordinate3D(3.300, 3.300, 0.000),
PointCoordinate3D(5.300, 2.300, 0.000),
PointCoordinate3D(4.300, 1.300, 0.000),
]
),
"ooi_type": "Lane divider",
"lane_divider_quality_options": "Good quality, Well lit, Fully visible",
},
{
"label_ref": "ooi_011",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(4.300, 5.300, 0.000),
PointCoordinate3D(6.300, 6.300, 0.000),
PointCoordinate3D(8.300, 5.300, 0.000),
PointCoordinate3D(7.300, 4.300, 0.000),
]
),
"ooi_type": "Zebra crossing",
"zebra_crossing_quality_options": "Good quality",
},
{
"label_ref": "ooi_012",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(7.300, 2.300, 0.000),
PointCoordinate3D(9.300, 3.300, 0.000),
PointCoordinate3D(11.300, 2.300, 0.000),
PointCoordinate3D(10.300, 1.300, 0.000),
]
),
"ooi_type": "Other",
"Type": "Cane",
},
],
},
"scene-0655": {
13: [
{
"label_ref": "ooi_013",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(1.300, 2.300, 0.000),
PointCoordinate3D(3.300, 3.300, 0.000),
PointCoordinate3D(5.300, 2.300, 0.000),
PointCoordinate3D(4.300, 1.300, 0.000),
]
),
"ooi_type": "Zebra crossing",
"zebra_crossing_quality_options": "Good quality",
},
{
"label_ref": "ooi_014",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(4.300, 5.300, 0.000),
PointCoordinate3D(6.300, 6.300, 0.000),
PointCoordinate3D(8.300, 5.300, 0.000),
PointCoordinate3D(7.300, 4.300, 0.000),
]
),
"ooi_type": "Curb",
"curb_quality_options": "Good quality, Well lit, Fully visible",
},
{
"label_ref": "ooi_015",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(7.300, 2.300, 0.000),
PointCoordinate3D(9.300, 3.300, 0.000),
PointCoordinate3D(11.300, 2.300, 0.000),
PointCoordinate3D(10.300, 1.300, 0.000),
]
),
"ooi_type": "Other",
"Type": "Cane",
},
],
14: [
{
"label_ref": "ooi_016",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(1.300, 2.300, 0.000),
PointCoordinate3D(3.300, 3.300, 0.000),
PointCoordinate3D(5.300, 2.300, 0.000),
PointCoordinate3D(4.300, 1.300, 0.000),
]
),
"ooi_type": "Zebra crossing",
"zebra_crossing_quality_options": "Good quality",
},
{
"label_ref": "ooi_014",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(4.130, 5.230, 0.000),
PointCoordinate3D(6.130, 6.230, 0.000),
PointCoordinate3D(8.130, 5.230, 0.000),
PointCoordinate3D(7.130, 4.230, 0.000),
]
),
"ooi_type": "Curb",
"curb_quality_options": "Good quality, Well lit, Fully visible",
},
{
"label_ref": "ooi_017",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(7.300, 2.300, 0.000),
PointCoordinate3D(9.300, 3.300, 0.000),
PointCoordinate3D(11.300, 2.300, 0.000),
PointCoordinate3D(10.300, 1.300, 0.000),
]
),
"ooi_type": "Other",
"Type": "Cane",
},
],
15: [
{
"label_ref": "ooi_016",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(1.130, 2.230, 0.000),
PointCoordinate3D(3.130, 3.230, 0.000),
PointCoordinate3D(5.130, 2.230, 0.000),
PointCoordinate3D(4.130, 1.230, 0.000),
]
),
"ooi_type": "Zebra crossing",
"zebra_crossing_quality_options": "Good quality",
},
{
"label_ref": "ooi_014",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(4.330, 5.530, 0.000),
PointCoordinate3D(6.330, 6.530, 0.000),
PointCoordinate3D(8.330, 5.530, 0.000),
PointCoordinate3D(7.330, 4.530, 0.000),
]
),
"ooi_type": "Curb",
"curb_quality_options": "Good quality, Well lit, Fully visible",
},
{
"label_ref": "ooi_017",
"coordinates": PolylineCoordinates(
[
PointCoordinate3D(7.130, 2.230, 0.000),
PointCoordinate3D(9.130, 3.230, 0.000),
PointCoordinate3D(11.130, 2.230, 0.000),
PointCoordinate3D(10.130, 1.230, 0.000),
]
),
"ooi_type": "Other",
"Type": "Cane",
},
],
},
}
# Cache label rows after initialization
label_row_map = {}
# Step 1: Initialize all label rows using a bundle
with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
for data_unit in pcd_labels.keys():
label_rows = project.list_label_rows_v2(data_title_eq=data_unit)
assert isinstance(label_rows, list), f"Expected list of label rows for '{data_unit}', got {type(label_rows)}"
if not label_rows:
print(f"Skipping: No label row found for {data_unit}")
continue
label_row = label_rows[0]
label_row.initialise_labels(bundle=bundle)
assert label_row.ontology_structure is not None, f"Ontology not initialized for label row: {data_unit}"
label_row_map[data_unit] = label_row # Cache the initialized label row
# Step 2: Process all frame coordinates and prepare label rows for saving
label_rows_to_save = []
for data_unit, frame_coordinates in pcd_labels.items():
label_row = label_row_map.get(data_unit)
if not label_row:
print(f"Skipping: No initialized label row found for {data_unit}")
continue
object_instances_by_label_ref = {}
for frame_number, items in frame_coordinates.items():
assert isinstance(frame_number, int), f"Frame number must be int, got {type(frame_number)}"
if not isinstance(items, list):
items = [items]
for item in items:
label_ref = item["label_ref"]
coord = item["coordinates"]
ooi_type = item["ooi_type"]
if label_ref not in object_instances_by_label_ref:
polyline_object_instance: ObjectInstance = polyline_ontology_object.create_instance()
# Set the Object of Interest type: look up the radio button option by its title
ooi_type_option = ooi_type_radio_attribute.get_child_by_title(title=ooi_type, type_=Option)
polyline_object_instance.set_answer(attribute=ooi_type_radio_attribute, answer=ooi_type_option)
if ooi_type == "Other":
text_answer = item.get("Type", "")
polyline_object_instance.set_answer(attribute=other_ooi_option_text_attribute, answer=text_answer)
else:
# Set the checklist answers: look up each quality option by its title
checklist_title, quality_key = quality_checklists[ooi_type]
checklist_attribute = polyline_ontology_object.get_child_by_title(
title=checklist_title, type_=ChecklistAttribute
)
quality_options = [q.strip() for q in item.get(quality_key, "").split(",") if q.strip()]
checklist_answers = [
checklist_attribute.get_child_by_title(title=quality, type_=Option) for quality in quality_options
]
if checklist_answers:
polyline_object_instance.set_answer(
attribute=checklist_attribute, answer=checklist_answers, overwrite=True
)
object_instances_by_label_ref[label_ref] = polyline_object_instance
else:
polyline_object_instance = object_instances_by_label_ref[label_ref]
# Assign coordinates for this frame
polyline_object_instance.set_for_frames(coordinates=coord, frames=frame_number)
# Add object instances to the label row if they have frames assigned
for polyline_object_instance in object_instances_by_label_ref.values():
assert isinstance(polyline_object_instance, ObjectInstance), "Expected ObjectInstance type"
if polyline_object_instance.get_annotation_frames():
label_row.add_object_instance(polyline_object_instance)
label_rows_to_save.append(label_row)
# Step 3: Save all label rows using a bundle
with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
for label_row in label_rows_to_save:
assert label_row is not None, "Trying to save a None label row"
label_row.save(bundle=bundle)
print(f"Saved label row for {label_row.data_title}")
print("Labels with radio buttons, checklist attributes, and text labels added for all data units.")
Keypoints 3D
Basic This example includes the following:- Keypoints 3D labeling
- Keypoint 3D labeling
- Radio button options
- Checklist options
- Text input
# Import dependencies
from encord import EncordUserClient, Project
from encord.objects import Object
from encord.objects.coordinates import PointCoordinate3D
# User input
SSH_PATH = "/Users/chris-encord/ssh-private-key.txt" # Replace with the file path to your SSH private key
PROJECT_ID = "00000000-0000-0000-0000-000000000000" # Replace with the unique ID for the Project
BUNDLE_SIZE = 100
# Create user client using ssh key
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
# For US platform users use "https://api.us.encord.com"
domain="https://api.encord.com",
)
# Get project for which labels are to be added
project: Project = user_client.get_project(PROJECT_ID)
# Create radio button attribute for Person type
ontology_structure = project.ontology_structure
# Find a keypoint annotation object in the project ontology
keypoint_ontology_object: Object = ontology_structure.get_child_by_title(title="Point of Interest", type_=Object)
# Dictionary of labels per data unit and per frame with Point of Interest
pcd_labels = {
"scene-1094": {
1: {
"label_ref": "poi_001",
"coordinates": PointCoordinate3D(x=0.01, y=0.02, z=0.03)
}
},
"scene-0916": {
1: [
{
"label_ref": "poi_002",
"coordinates": PointCoordinate3D(x=0.03, y=0.03, z=0.03)
},
{
"label_ref": "poi_003",
"coordinates": PointCoordinate3D(x=0.5, y=0.4, z=0.3)
},
{
"label_ref": "poi_004",
"coordinates": PointCoordinate3D(x=0.9, y=0.3, z=0.3)
},
],
},
"scene-0796": {
0: {
"label_ref": "poi_005",
"coordinates": PointCoordinate3D(x=0.05, y=0.02, z=0.03)
},
2: [
{
"label_ref": "poi_006",
"coordinates": PointCoordinate3D(x=0.3, y=0.3, z=0.3)
},
{
"label_ref": "poi_007",
"coordinates": PointCoordinate3D(x=0.4, y=0.5, z=0.3)
},
{
"label_ref": "poi_008",
"coordinates": PointCoordinate3D(x=0.11, y=0.2, z=0.3)
},
],
},
"scene-1100": {
0: {
"label_ref": "poi_009",
"coordinates": PointCoordinate3D(x=0.1, y=0.2, z=0.3)
},
3: [
{
"label_ref": "poi_010",
"coordinates": PointCoordinate3D(x=0.3, y=0.3, z=0.3)
},
{
"label_ref": "poi_011",
"coordinates": PointCoordinate3D(x=0.8, y=0.5, z=0.3)
},
{
"label_ref": "poi_012",
"coordinates": PointCoordinate3D(x=0.11, y=0.2, z=0.3)
},
],
},
"scene-0655": {
1: [
{
"label_ref": "poi_013",
"coordinates": PointCoordinate3D(x=0.2, y=0.1, z=0.3)
},
{
"label_ref": "poi_014",
"coordinates": PointCoordinate3D(x=0.6, y=0.6, z=0.3)
},
{
"label_ref": "poi_015",
"coordinates": PointCoordinate3D(x=0.10, y=0.1, z=0.3)
},
],
2: [
{
"label_ref": "poi_016",
"coordinates": PointCoordinate3D(x=0.4, y=0.1, z=0.3)
},
{
"label_ref": "poi_014",
"coordinates": PointCoordinate3D(x=0.8, y=0.5, z=0.3)
},
{
"label_ref": "poi_017",
"coordinates": PointCoordinate3D(x=0.11, y=0.2, z=0.3)
},
],
3: [
{
"label_ref": "poi_016",
"coordinates": PointCoordinate3D(x=0.5, y=0.2, z=0.3)
},
{
"label_ref": "poi_014",
"coordinates": PointCoordinate3D(x=0.7, y=0.4, z=0.3)
},
{
"label_ref": "poi_017",
"coordinates": PointCoordinate3D(x=0.9, y=0.3, z=0.3)
},
],
},
}
# Initialize label rows
label_row_map = {}
with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
for data_title in pcd_labels.keys():
rows = project.list_label_rows_v2(data_title_eq=data_title)
if not rows:
print(f"Skipping: No label row found for {data_title}")
continue
lr = rows[0]
lr.initialise_labels(bundle=bundle)
label_row_map[data_title] = lr
# Create instances
label_rows_to_save = []
for data_title, frames in pcd_labels.items():
lr = label_row_map.get(data_title)
if not lr:
continue
instances_by_ref = {}
for frame_no, items in frames.items():
# normalize to list
items = items if isinstance(items, list) else [items]
for item in items:
ref = item["label_ref"]
coords = item["coordinates"]
if ref not in instances_by_ref:
instances_by_ref[ref] = keypoint_ontology_object.create_instance()
instances_by_ref[ref].set_for_frames(coordinates=coords, frames=frame_no)
# Add only instances that have at least one frame
for inst in instances_by_ref.values():
if inst.get_annotation_frames():
lr.add_object_instance(inst)
label_rows_to_save.append(lr)
# Save all label rows
with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
for lr in label_rows_to_save:
lr.save(bundle=bundle)
print(f"Saved label row for {lr.data_title}")
# Import dependencies
from pathlib import Path
from encord import EncordUserClient, Project
from encord.objects import ChecklistAttribute, Object, ObjectInstance, Option, RadioAttribute, TextAttribute
from encord.objects.coordinates import PointCoordinate3D
# User input
SSH_PATH = "/Users/chris-encord/ssh-private-key.txt" # Replace with the file path to your SSH private key
PROJECT_ID = "00000000-0000-0000-0000-000000000000" # Replace with the unique ID for the Project
BUNDLE_SIZE = 100
# Create user client using ssh key
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
# For US platform users use "https://api.us.encord.com"
domain="https://api.encord.com",
)
# Get project for which labels are to be added
project: Project = user_client.get_project(PROJECT_ID)
# Get ontology structure
ontology_structure = project.ontology_structure
# Get keypoint object for Point of Interest
keypoint_ontology_object: Object = ontology_structure.get_child_by_title(title="Point of Interest", type_=Object)
# Look up the attributes under the Point of Interest object. get_child_by_title raises an error if a title isn't found.
poi_type_radio_attribute = keypoint_ontology_object.get_child_by_title(title="Type?", type_=RadioAttribute)
other_poi_option_text_attribute = keypoint_ontology_object.get_child_by_title(
title="Specify Point of Interest type", type_=TextAttribute
)
# For each Point of Interest type: the checklist attribute that holds its qualities, and the key for them in the data below
quality_checklists = {
"Sign": ("Sign Qualities?", "sign_quality_options"),
"Traffic light": ("Traffic light Qualities?", "traffic_light_quality_options"),
}
# Dictionary of labels per data unit and per frame with Point of Interest type specified, including quality options
pcd_labels = {
"scene-1094": {
1: {
"label_ref": "poi_001",
"coordinates": PointCoordinate3D(x=0.01, y=0.02, z=0.03),
"poi_type": "Sign",
"sign_quality_options": "Well positioned, Good visibility, Good condition",
}
},
"scene-0916": {
1: [
{
"label_ref": "poi_002",
"coordinates": PointCoordinate3D(x=0.03, y=0.03, z=0.03),
"poi_type": "Traffic light",
"traffic_light_quality_options": "Well positioned, Good visibility, Good condition",
},
{
"label_ref": "poi_003",
"coordinates": PointCoordinate3D(x=0.5, y=0.4, z=0.3),
"poi_type": "Traffic light",
"traffic_light_quality_options": "Good visibility",
},
{
"label_ref": "poi_004",
"coordinates": PointCoordinate3D(x=0.9, y=0.3, z=0.3),
"poi_type": "Other Point of Interest type",
"Specify Point of Interest type": "Curb",
},
],
},
"scene-0796": {
0: {
"label_ref": "poi_005",
"coordinates": PointCoordinate3D(x=0.05, y=0.02, z=0.03),
"poi_type": "Sign",
"sign_quality_options": "Well positioned, Good visibility, Good condition",
},
2: [
{
"label_ref": "poi_006",
"coordinates": PointCoordinate3D(x=0.3, y=0.3, z=0.3),
"poi_type": "Sign",
"sign_quality_options": "Good condition",
},
{
"label_ref": "poi_007",
"coordinates": PointCoordinate3D(x=0.4, y=0.5, z=0.3),
"poi_type": "Sign",
"sign_quality_options": "Good visibility",
},
{
"label_ref": "poi_008",
"coordinates": PointCoordinate3D(x=0.11, y=0.2, z=0.3),
"poi_type": "Other Point of Interest type",
"Specify Point of Interest type": "Post box",
},
],
},
"scene-1100": {
0: {
"label_ref": "poi_009",
"coordinates": PointCoordinate3D(x=0.1, y=0.2, z=0.3),
"poi_type": "Traffic light",
"traffic_light_quality_options": "Well positioned, Good visibility, Good condition",
},
3: [
{
"label_ref": "poi_010",
"coordinates": PointCoordinate3D(x=0.3, y=0.3, z=0.3),
"poi_type": "Traffic light",
"traffic_light_quality_options": "Well positioned, Good visibility, Good condition",
},
{
"label_ref": "poi_011",
"coordinates": PointCoordinate3D(x=0.8, y=0.5, z=0.3),
"poi_type": "Traffic light",
"traffic_light_quality_options": "Good condition",
},
{
"label_ref": "poi_012",
"coordinates": PointCoordinate3D(x=0.11, y=0.2, z=0.3),
"poi_type": "Other Point of Interest type",
"Specify Point of Interest type": "Post box",
},
],
},
"scene-0655": {
1: [
{
"label_ref": "poi_013",
"coordinates": PointCoordinate3D(x=0.2, y=0.1, z=0.3),
"poi_type": "Sign",
"sign_quality_options": "Good condition",
},
{
"label_ref": "poi_014",
"coordinates": PointCoordinate3D(x=0.6, y=0.6, z=0.3),
"poi_type": "Sign",
"sign_quality_options": "Well positioned, Good visibility, Good condition",
},
{
"label_ref": "poi_015",
"coordinates": PointCoordinate3D(x=0.10, y=0.1, z=0.3),
"poi_type": "Other Point of Interest type",
"Specify Point of Interest type": "Curb",
},
],
2: [
{
"label_ref": "poi_016",
"coordinates": PointCoordinate3D(x=0.4, y=0.1, z=0.3),
"poi_type": "Sign",
"sign_quality_options": "Good condition",
},
{
"label_ref": "poi_014",
"coordinates": PointCoordinate3D(x=0.8, y=0.5, z=0.3),
"poi_type": "Sign",
"sign_quality_options": "Well positioned, Good visibility, Good condition",
},
{
"label_ref": "poi_017",
"coordinates": PointCoordinate3D(x=0.11, y=0.2, z=0.3),
"poi_type": "Other Point of Interest type",
"Specify Point of Interest type": "Post box",
},
],
3: [
{
"label_ref": "poi_016",
"coordinates": PointCoordinate3D(x=0.5, y=0.2, z=0.3),
"poi_type": "Sign",
"sign_quality_options": "Good condition",
},
{
"label_ref": "poi_014",
"coordinates": PointCoordinate3D(x=0.7, y=0.4, z=0.3),
"poi_type": "Sign",
"sign_quality_options": "Well positioned, Good visibility, Good condition",
},
{
"label_ref": "poi_017",
"coordinates": PointCoordinate3D(x=0.9, y=0.3, z=0.3),
"poi_type": "Other Point of Interest type",
"Specify Point of Interest type": "Post box",
},
],
},
}
# Cache label rows after initialization
label_row_map = {}
# Step 1: Initialize all label rows using a bundle
with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
for data_unit in pcd_labels.keys():
label_rows = project.list_label_rows_v2(data_title_eq=data_unit)
assert isinstance(label_rows, list), f"Expected list of label rows for '{data_unit}', got {type(label_rows)}"
if not label_rows:
print(f"Skipping: No label row found for {data_unit}")
continue
label_row = label_rows[0]
label_row.initialise_labels(bundle=bundle)
assert label_row.ontology_structure is not None, f"Ontology not initialized for label row: {data_unit}"
label_row_map[data_unit] = label_row # Cache the initialized label row
# Step 2: Process all frame coordinates and prepare label rows for saving
label_rows_to_save = []
for data_unit, frame_coordinates in pcd_labels.items():
label_row = label_row_map.get(data_unit)
if not label_row:
print(f"Skipping: No initialized label row found for {data_unit}")
continue
object_instances_by_label_ref = {}
for frame_number, items in frame_coordinates.items():
assert isinstance(frame_number, int), f"Frame number must be int, got {type(frame_number)}"
if not isinstance(items, list):
items = [items]
for item in items:
label_ref = item["label_ref"]
coord = item["coordinates"]
poi_type = item["poi_type"]
if label_ref not in object_instances_by_label_ref:
keypoint_object_instance: ObjectInstance = keypoint_ontology_object.create_instance()
# Set the Point of Interest type: look up the radio button option by its title
poi_type_option = poi_type_radio_attribute.get_child_by_title(title=poi_type, type_=Option)
keypoint_object_instance.set_answer(attribute=poi_type_radio_attribute, answer=poi_type_option)
if poi_type == "Other Point of Interest type":
text_answer = item.get("Type", "")
keypoint_object_instance.set_answer(attribute=other_poi_option_text_attribute, answer=text_answer)
else:
# Set the checklist answers: look up each quality option by its title
checklist_title, quality_key = quality_checklists[poi_type]
checklist_attribute = keypoint_ontology_object.get_child_by_title(
title=checklist_title, type_=ChecklistAttribute
)
quality_options = [q.strip() for q in item.get(quality_key, "").split(",") if q.strip()]
checklist_answers = [
checklist_attribute.get_child_by_title(title=quality, type_=Option) for quality in quality_options
]
if checklist_answers:
keypoint_object_instance.set_answer(
attribute=checklist_attribute, answer=checklist_answers, overwrite=True
)
object_instances_by_label_ref[label_ref] = keypoint_object_instance
else:
keypoint_object_instance = object_instances_by_label_ref[label_ref]
# Assign coordinates for this frame
keypoint_object_instance.set_for_frames(coordinates=coord, frames=frame_number)
# Add object instances to the label row if they have frames assigned
for keypoint_object_instance in object_instances_by_label_ref.values():
assert isinstance(keypoint_object_instance, ObjectInstance), "Expected ObjectInstance type"
if keypoint_object_instance.get_annotation_frames():
label_row.add_object_instance(keypoint_object_instance)
label_rows_to_save.append(label_row)
# Step 3: Save all label rows using a bundle
with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
for label_row in label_rows_to_save:
assert label_row is not None, "Trying to save a None label row"
label_row.save(bundle=bundle)
print(f"Saved label row for {label_row.data_title}")
print("Labels with radio buttons, checklist attributes, and text labels added for all data units.")
Segmentations
The following script demonstrates how to add segmentation labels to point cloud data using the Encord Python SDK. It assumes that you have a project with a point cloud dataset and an ontology that includes a segmentation object titled “Sidewalk”. The script creates segmentation instances for specified ranges of point indices in the point cloud files. Each point cloud file in a Scene has its own label space. Get it withLabelRowV2.get_space(stream_id=..., event_index=..., type_="point_cloud"): stream_id is the name of the point cloud stream, and event_index is the position of the file in that stream, starting at 0. For a Scene with one point cloud per frame, such as the one in this example, the event index is the frame number.
# Import dependencies
from encord import EncordUserClient, Project
from encord.objects import Object
from encord.objects.frames import Range
from encord.objects.spaces.range_space.point_cloud_space import PointCloudFileSpace
# User input
SSH_PATH = "/Users/chris-encord/ssh-private-key.txt" # Replace with the file path to your SSH private key
PROJECT_ID = "00000000-0000-0000-0000-000000000000" # Replace with the unique ID for the Project
POINT_CLOUD_STREAM = "lidar" # Replace with the name of the point cloud stream in your Scenes
EVENT_INDEX = 0 # Replace with the position of the point cloud file in the stream (0 is the first file)
BUNDLE_SIZE = 100
# Create user client using ssh key
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
# For US platform users use "https://api.us.encord.com"
domain="https://api.encord.com",
)
# Get project for which labels are to be added
project: Project = user_client.get_project(PROJECT_ID)
# Find a point-cloud segmentation object in the project ontology
ontology_structure = project.ontology_structure
segmentation_ontology_object: Object = ontology_structure.get_child_by_title(title="Sidewalk", type_=Object)
# Point-index ranges per data unit. Each entry becomes one segmentation instance owning
# the listed (start, end) inclusive point-index ranges in the uploaded point cloud.
# Ranges must be computed against the exact file registered on the platform - re-uploading,
# reordering, or decimating the cloud afterwards shifts every index.
pcd_segmentation_labels = {
"scene-1094": [
{
"label_ref": "sidewalk_001",
"ranges": [(0, 15234), (52000, 52980)],
},
{
"label_ref": "sidewalk_002",
"ranges": [(15235, 28110)],
},
],
"scene-0916": [
{
"label_ref": "sidewalk_003",
"ranges": [(0, 40233), (40500, 61022), (70000, 70999)],
},
],
}
# Initialize label rows
label_row_map = {}
with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
for data_title in pcd_segmentation_labels.keys():
rows = project.list_label_rows_v2(data_title_eq=data_title)
if not rows:
print(f"Skipping: No label row found for {data_title}")
continue
lr = rows[0]
lr.initialise_labels(bundle=bundle)
label_row_map[data_title] = lr
# Create instances
label_rows_to_save = []
for data_title, segmentations in pcd_segmentation_labels.items():
lr = label_row_map.get(data_title)
if not lr:
continue
# Point-cloud segmentation instances live on the space of one point cloud file, not
# directly on the label row. Get the space by stream name and the file's position in
# that stream. get_space raises an error if the Scene has no such file.
space: PointCloudFileSpace = lr.get_space(
stream_id=POINT_CLOUD_STREAM, event_index=EVENT_INDEX, type_="point_cloud"
)
for segmentation in segmentations:
instance = segmentation_ontology_object.create_instance()
ranges = [Range(start=s, end=e) for s, e in segmentation["ranges"]]
space.put_object_instance(
object_instance=instance,
ranges=ranges,
confidence=1.0,
)
label_rows_to_save.append(lr)
# Save all label rows
with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
for lr in label_rows_to_save:
lr.save(bundle=bundle)
print(f"Saved label row for {lr.data_title}")

