Export labels

The Encord SDK is designed to offer a versatile and targeted approach to accessing label information. This approach allows for a more customized handling of label information, catering to various needs and scenarios in data processing.

The following table describes all values exported by the scripts on this page.

KeyDescription
objectHashThe unique ID of the object instance. Two instances of the same object have different object hashes
Object nameThe name of the object as defined in the Ontology. For example "Chicken".
featureHashThe unique ID of the Ontology element. For example, the object "Chicken" in the Ontology. All instances have the same featureHash.
uidThe unique identifier for the object instance. Two instances of the same object have different uids.
Object colorThe color used to label the object, as defined in the Ontology and seen in the Encord platform.
Ontology shapeThe shape used to label the object, as defined in the Ontology. For example, polygon.
Classification nameThe name of the Classification, as defined in the Ontology. For example "Day or night?"
Classification answerThe value of the Classification, as defined in the Ontology. For example "Day"
classificationHashThe unique identifier for the Classification instance.
Classification answer hashThe unique identifier for the Classification value
Attribute nameThe name of the attribute, as defined in the Ontology. For example "Standing or sitting?"
Attribute answerThe name of the attribute value, as defined in the Ontology. For example "Sitting"
Attribute answer featureHashThe unique identifier for the attribute value.

Export labels as JSON

The following script prints a JSON file containing all the labels in your Project.

Make sure you substitute:

  • The <private_key_path> with the full path to your private key.
  • The <project_hash> with the hash of your Project.
# Import dependencies
from encord import EncordUserClient
import json

# Instantiate client. Replace <private_key_path> with the path to the file containing your private key.
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path="<private_key_path>"
)

# Specify Project. Replace <project_hash> with the hash of the Project you want to export labels for.
project = client.get_project("<project_hash>")

# Get label rows for your Project.
label_rows = project.list_label_rows_v2()

for label_row in label_rows:

    # Download label information
    label_row.initialise_labels()
    print (json.dumps(label_row.to_encord_dict()))

Export attributes

The following scripts get the attributes for all labels in a Project, as well as the frames that the attributes appear on. Single images only have a single frame.

In the following scripts, ensure that that you:

  • Replace <private_key_path> with the full path to your private key.
  • Replace <project_hash> with the hash of the Project you want to export attributes for.
  • Replace <task_name> with the name of the data unit you want to export attributes for. Remove data_title_eq="<task_name>" if you want to export attributes for all tasks.

❗️

CRITICAL INFORMATION

We recommend using the script for exporting all attributes if the Project uses an Ontology with nested attributes.

# Import dependencies
from encord import EncordUserClient
from encord.objects.attributes import Attribute, TextAttribute
from encord.objects import ObjectInstance

# Instantiate Encord client by substituting the path to your private key
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path="<private_key_path>"
)

# Replace <project_hash> with the hash of your Project
project = user_client.get_project("<project_hash>")

# A function to extract and print essential information for all attributes, specifically handling text attributes
def print_attributes(attribute: Attribute, object_instance: ObjectInstance, frame_number: int):
    if isinstance(attribute, TextAttribute):
        print(f"Frame {frame_number+1}:")
        print(f"Text Attribute name: {attribute.title}")
        print(f"Text Attribute hash: {attribute.feature_node_hash}")

        # Retrieve text directly from object instance for the specific frame
        text_answer = object_instance.get_answer(attribute)
        print(f"Text Attribute Answer: {text_answer}")

for label_row in project.list_label_rows_v2(data_title_eq="<task_name>"):
    label_row.initialise_labels()

    for object_instance in label_row.get_object_instances():
        for annotation in object_instance.get_annotations():
            # Now calling print_attributes per frame
            for attribute in object_instance.ontology_item.attributes:
                print_attributes(attribute, object_instance, annotation.frame)

# Import dependencies
from encord import EncordUserClient
from encord.objects.attributes import Attribute, RadioAttribute
from encord.objects import ObjectInstance

def print_attributes(attribute: Attribute, object_instance: ObjectInstance, frame_number: int):
    if isinstance(attribute, RadioAttribute):
        print(f"Frame {frame_number+1}:")
        print(f"Radio Attribute name: {attribute.title}")
        print(f"Radio Attribute hash: {attribute.feature_node_hash}")

        # Get the answers directly, can be single or multiple depending on configuration
        attribute_answers = object_instance.get_answer(attribute)
        
        # Make sure attribute_answers is iterable
        if not isinstance(attribute_answers, list):
            attribute_answers = [attribute_answers]

        for answer in attribute_answers:
            print(f"Attribute answer: {answer.title}")
            print(f"Attribute answer hash: {answer.feature_node_hash}")
            
            # Check for nested attributes if present and handle them recursively
            if hasattr(answer, 'attributes') and answer.attributes:
                for nested_attribute in answer.attributes:
                    print(f"Attribute answer \"{answer.title}\" has nested attribute \"{nested_attribute.title}\"")
                    print(f"Nested Attribute hash: {nested_attribute.feature_node_hash}")
                    print_attributes(nested_attribute, object_instance, frame_number)

for label_row in project.list_label_rows_v2(data_title_eq="<task_name>"):
    label_row.initialise_labels()

    for object_instance in label_row.get_object_instances():
        for annotation in object_instance.get_annotations():
            # Now calling print_attributes per frame for all attributes
            for attribute in object_instance.ontology_item.attributes:
                print_attributes(attribute, object_instance, annotation.frame)
# Import dependencies
from encord import EncordUserClient
from encord.objects.attributes import Attribute, ChecklistAttribute
from encord.objects import ObjectInstance

# Instantiate Encord client by substituting the path to your private key
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path="<private_key_path>"
)

# Replace <project_hash> with the hash of your Project
project = user_client.get_project("<project_hash>")

def print_attributes(attribute: Attribute, object_instance: ObjectInstance, frame_number: int):
    if isinstance(attribute, ChecklistAttribute):
        print(f"Frame {frame_number+1}:")
        print(f"Checklist Attribute name: {attribute.title}")
        print(f"Checklist Attribute hash: {attribute.feature_node_hash}")

        # Get the answers directly, can be single or multiple
        attribute_answers = object_instance.get_answer(attribute)
        
        # Make sure attribute_answers is iterable
        if not isinstance(attribute_answers, list):
            attribute_answers = [attribute_answers]

        for answer in attribute_answers:
            print(f"Checklist answer: {answer.title}")
            print(f"Checklist answer hash: {answer.feature_node_hash}")

for label_row in project.list_label_rows_v2(data_title_eq="<task_name>"):
    label_row.initialise_labels()

    for object_instance in label_row.get_object_instances():
        for annotation in object_instance.get_annotations():
            # Call print_attributes per frame for all attributes
            for attribute in object_instance.ontology_item.attributes:
                print_attributes(attribute, object_instance, annotation.frame)
from collections.abc import Iterable  # For checking if an object is iterable
from encord import EncordUserClient
from encord.objects.attributes import Attribute, TextAttribute, RadioAttribute, ChecklistAttribute
from encord.objects import ObjectInstance

# Instantiate Encord client by substituting the path to your private key
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path="<private_key_path>"
)

# Replace <project_hash> with the hash of your Project
project = user_client.get_project("<project_hash>")

def print_attributes(attribute: Attribute, object_instance: ObjectInstance, frame_number: int):
    # Determine the type of attribute
    attribute_type = ''
    if isinstance(attribute, TextAttribute):
        attribute_type = 'Text Attribute'
    elif isinstance(attribute, RadioAttribute):
        attribute_type = 'Radio Button Attribute'
    elif isinstance(attribute, ChecklistAttribute):
        attribute_type = 'Checklist Attribute'

    # Print general attribute info
    print(f"Frame {frame_number + 1}: {attribute_type} name: {attribute.title}")
    print(f"{attribute_type} hash: {attribute.feature_node_hash}")

    # Handle TextAttribute directly
    if isinstance(attribute, TextAttribute):
        text_answer = object_instance.get_answer(attribute)
        if text_answer:
            print(f"{attribute_type} Answer: {text_answer}")
        else:
            print(f"{attribute_type} Answer: No attribute answer")

    # Handle RadioAttribute which may have nested attributes
    elif isinstance(attribute, RadioAttribute):
        attribute_answer = object_instance.get_answer(attribute)
        if attribute_answer:
            print(f"{attribute_type} answer: {attribute_answer.title}")
            print(f"{attribute_type} answer hash: {attribute_answer.feature_node_hash}")
            # Check for nested attributes
            if hasattr(attribute_answer, 'attributes') and attribute_answer.attributes:
                for nested_attribute in attribute_answer.attributes:
                    print(f"Nested attribute \"{attribute_answer.title}\" -> \"{nested_attribute.title}\" ({nested_attribute.feature_node_hash})")
                    print_attributes(nested_attribute, object_instance, frame_number)
        else:
            print(f"{attribute_type} answer: No attribute answer")

    # Handle ChecklistAttribute separately which may have multiple answers
    elif isinstance(attribute, ChecklistAttribute):
        checklist_answers = object_instance.get_answer(attribute)
        # Check if any answers are available
        if checklist_answers:
            if not isinstance(checklist_answers, Iterable):
                checklist_answers = [checklist_answers]  # Wrap the single answer in a list
            for answer in checklist_answers:
                print(f"{attribute_type} answer: {answer.title}")
                print(f"{attribute_type} answer hash: {answer.feature_node_hash}")
        else:
            print(f"{attribute_type} answer: No attribute answer")

# Iterate over all label rows in the project
for label_row in project.list_label_rows_v2(data_title_eq="<task_name>"):
    label_row.initialise_labels()

    for object_instance in label_row.get_object_instances():
        for annotation in object_instance.get_annotations():
            # Now calling print_attributes per frame for all attributes
            for attribute in object_instance.ontology_item.attributes:
                print_attributes(attribute, object_instance, annotation.frame)

Export objects and classifications

🚧

Caution

The following scripts do not support Ontologies with text classifications, or nested classifications. The scripts serve as a template for exporting object labels only.

The following script shows how to access and print essential label information for all object and classification instances, and all attributes in a Project. The example for videos, image groups, image sequences and DICOM outputs the frame numbers of each object, classification and attribute.

Make sure you substitute:

  • The <private_key_path> with the full path to your private key.
  • The <project_hash> with the hash of your Project.
# Import dependencies
from encord import EncordUserClient
from encord.objects.ontology_element import OntologyElement
from encord.objects.attributes import Attribute
from encord.objects import ObjectInstance

# Instantiate Encord client by substituting the path to your private key
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path="<private_key_path>"
)

# Replace <project_hash> with the hash of your Project
project = user_client.get_project("<project_hash>")

# A function to extract and print essential information for all attributes
def print_attributes(attribute: Attribute, object_instance: ObjectInstance):
    print(f"Attribute name: {attribute.title}")
    print(f"Attribute hash: {attribute.feature_node_hash}")
    for answer_for_frames in object_instance.get_answer(attribute):
        print(f"Attribute answer \"{answer_for_frames.answer.title}\" is present on frames {answer_for_frames.ranges}")
        print ("Attribute answer hash " + answer_for_frames.answer.feature_node_hash)
        for attribute in answer_for_frames.answer.attributes:
            print(f"Attribute answer \"{answer_for_frames.answer.title}\" has nested attribute \"{attribute.title}\"")
            print_attributes(attribute, object_instance)


# Specify the label row you want to edit labels for. This example loops through all label rows
for label_row in project.list_label_rows_v2():

    # Download all labels
    label_row.initialise_labels()
    
    # Print essential label information for all objects
    for object_instance in label_row.get_object_instances():
        print ("objectHash: " + object_instance.object_hash)
        print ("Object name: " + object_instance.object_name)
        print ("featureHash: " + object_instance.feature_hash)
        print ("uid: " + str(object_instance.ontology_item.uid))
        print ("Object color: " + object_instance.ontology_item.color)
        print ("Ontology shape: " + object_instance.ontology_item.shape)

        # Print the frame number and the location of the object on the frame
        for annotation in object_instance.get_annotations():
            print(f"Frame {annotation.frame} -> {annotation.coordinates}")

        # Print all attributes 
        for attribute in object_instance.ontology_item.attributes:
            print_attributes(attribute, object_instance)

    # Print all essential classification information
    for classification_instance in label_row.get_classification_instances():
        print ("classificationHash: " + classification_instance.classification_hash)
        print ("Classification name: " + classification_instance.classification_name)
        print ("featureHash: " + classification_instance.feature_hash)
        print ("Classification answer: " + classification_instance.get_answer().value)
        print ("Classification answer hash: " + classification_instance.get_answer().feature_node_hash)


        # Print the frame number(s) that a classification appears on
        for annotation in classification_instance.get_annotations():
            print("Classification appears on frame " + str(annotation.frame))
from encord import EncordUserClient
from encord.objects.ontology_element import OntologyElement
from encord.objects.attributes import Attribute
from encord.objects import ObjectInstance

# Instantiate Encord client by substituting the path to your private key
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path="<private_key_path>"
)

# Replace <project_hash> with the hash of your Project
project = user_client.get_project("<project_hash>")

# Print essential info for all attributes
def print_attributes(attribute: Attribute, object_instance: ObjectInstance):
    print(f"Attribute name: {attribute.title}")
    print(f"Attribute hash: {attribute.feature_node_hash}")
    for attribute_answer in object_instance.get_answer(attribute):
        print(f"Attribute answer: {attribute_answer.answer.title}")
        print ("Attribute answer hash " + attribute_answer.answer.feature_node_hash)
        for attribute in attribute_answer.answer.attributes:
            print(f"Attribute answer \"{attribute_answer.answer.title}\" has nested attribute \"{attribute.title}\"")
            print ("Attribute answer hash " + attribute_answer.answer.feature_node_hash)
            print_attributes(attribute, object_instance)


# Specify the label row you want to edit labels for. This example loops through all label rows
for label_row in project.list_label_rows_v2():

    # Download all labels
    label_row.initialise_labels()
    
    # Print essential label information for all objects
    for object_instance in label_row.get_object_instances():
        print ("objectHash: " + object_instance.object_hash)
        print ("Object name: " + object_instance.object_name)
        print ("featureHash: " + object_instance.feature_hash)
        print ("uid: " + str(object_instance.ontology_item.uid))
        print ("Object color: " + object_instance.ontology_item.color)
        print ("Ontology shape: " + object_instance.ontology_item.shape)

        for annotation in object_instance.get_annotations():
            print(f"Frame {annotation.frame} -> {annotation.coordinates}")

        for attribute in object_instance.ontology_item.attributes:
            print_attributes(attribute, object_instance)

    for classification_instance in label_row.get_classification_instances():
        print ("classificationHash: " + classification_instance.classification_hash)
        print ("Classification name: " + classification_instance.classification_name)
        print ("featureHash: " + classification_instance.feature_hash)

        for annotation in classification_instance.get_annotations():
            print("Classification on frame " + str(annotation.frame))

objectHash: HI5408US
Object name: Chicken
featureHash: p6T5NeQ4
uid: 1
Object color: #D33115
Ontology Shape: bounding_box
Frame 101 -> BoundingBoxCoordinates(height=0.526, width=0.2514, top_left_x=0.5826, top_left_y=0.2431)
Frame 102 -> BoundingBoxCoordinates(height=0.5365, width=0.256, top_left_x=0.578, top_left_y=0.2413)
Frame 103 -> BoundingBoxCoordinates(height=0.5469, width=0.2615, top_left_x=0.5752, top_left_y=0.2378)
Frame 104 -> BoundingBoxCoordinates(height=0.5365, width=0.256, top_left_x=0.5798, top_left_y=0.2396)
Frame 105 -> BoundingBoxCoordinates(height=0.5365, width=0.256, top_left_x=0.5661, top_left_y=0.2396)
Frame 106 -> BoundingBoxCoordinates(height=0.5469, width=0.2615, top_left_x=0.5633, top_left_y=0.2361)
Frame 107 -> BoundingBoxCoordinates(height=0.5365, width=0.256, top_left_x=0.5532, top_left_y=0.2361)
Frame 108 -> BoundingBoxCoordinates(height=0.526, width=0.2514, top_left_x=0.556, top_left_y=0.2413)
Attribute name: Walking or Sitting?
featureHash: pHXXPbuc
Attribute answer "Walking" is present on frames [(101:104)]
Attribute answer featureHash: 6qeufh3l
Attribute answer "Sitting" is present on frames [(105:108)]
Attribute answer featureHash: hkInN4Sd
classificationHash: gffOkg9l
Classification name: Day or Night?
featureHash: FA6pAde3
Classification answer: Day
Classification answer hash: gasjasd
Classification appears on frame 352

Export objects, classifications, and attributes by frame

🚧

Caution

Videos with variable frame rates can result in misplaced labels.

Range of consecutive frames

The following scripts download and print the labels for a specified range of frames in videos.

Make sure you substitute:

  • The <private_key_path> with the full path to your private key.
  • The <project_hash> with the hash of your Project.
  • The <task_name> with the name of the task you want to export labels for (if using the task-specific script).
  • The <start_frame_number> with the first frame of the range you want to export labels for.
  • The <end_frame_number> with the last frame of the range you want to export labels for.

👍

Tip

To export labels for a single frame, make the <start_frame_number> the same as the <end_frame_number>. For example, to export labels on the 13th frame set <start_frame_number> = 13, and <end_frame_number> = 13.

# Import dependencies
from encord import EncordUserClient
from encord.objects.ontology_element import OntologyElement
from encord.objects.attributes import Attribute, Option
from encord.objects import ObjectInstance
from collections.abc import Iterable

# Instantiate Encord client by substituting the path to your private key
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path="<private_key_path>"
)

# Replace <project_hash> with the hash of your Project
project = user_client.get_project("<project_hash>")

# A function to extract and print essential information for all attributes
def print_attributes(attribute: Attribute, object_instance: ObjectInstance):
    print(f"Attribute name: {attribute.title}")
    print(f"Attribute hash: {attribute.feature_node_hash}")
    print(f"Attribute answer: {object_instance.get_answer(attribute)}")


# Specify the label row you want to edit labels for.
start_frame_number = <start_frame_number>  # Set the start of your desired frame range
end_frame_number = <end_frame_number>   # Set the end of your desired frame range

# Specify which task you want to export labels for
for label_row in project.list_label_rows_v2(data_title_eq="<task_name>"):

    # Download all labels
    label_row.initialise_labels()
    
    # Print essential label information for all objects
    for object_instance in label_row.get_object_instances():
        for annotation in object_instance.get_annotations():
            if start_frame_number <= annotation.frame <= end_frame_number:
                print ("Frame: " + str(annotation.frame))
                print ("objectHash: " + object_instance.object_hash)
                print ("Object name: " + object_instance.object_name)
                print ("featureHash: " + object_instance.feature_hash)
                print ("uid: " + str(object_instance.ontology_item.uid))
                print ("Object color: " + object_instance.ontology_item.color)
                print ("Ontology shape: " + object_instance.ontology_item.shape)
                print (f"Label location: {annotation.coordinates}")

            # Print all attributes
            for attribute in object_instance.ontology_item.attributes:
                print_attributes(attribute, object_instance)

    # Print all essential classification information on specified frames
    for classification_instance in label_row.get_classification_instances():
        for annotation in classification_instance.get_annotations():
            if start_frame_number <= annotation.frame <= end_frame_number:
                print("Classification hash: " + classification_instance.classification_hash)
                print("Classification name: " + classification_instance.classification_name)
                print("Feature hash: " + classification_instance.feature_hash)
                print("Classification value: " + classification_instance.get_answer().value)
                print("Classification answer hash: " + classification_instance.get_answer().feature_node_hash)
# Import dependencies
from encord import EncordUserClient
from encord.objects.ontology_element import OntologyElement
from encord.objects.attributes import Attribute, Option
from encord.objects import ObjectInstance
from collections.abc import Iterable

# Instantiate Encord client by substituting the path to your private key
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path="<private_key_path>"
)

# Replace <project_hash> with the hash of your Project
project = user_client.get_project("<project_hash>")

# A function to extract and print essential information for all attributes
def print_attributes(attribute: Attribute, object_instance: ObjectInstance):
    print(f"Attribute name: {attribute.title}")
    print(f"Attribute hash: {attribute.feature_node_hash}")
    print(f"Attribute answer: {object_instance.get_answer(attribute)}")


start_frame_number = <start_frame_number>  # Set the start of your desired frame range
end_frame_number = <end_frame_number>   # Set the end of your desired frame range

for label_row in project.list_label_rows_v2():

    # Download all labels
    label_row.initialise_labels()
    
    # Print essential label information for all objects
    for object_instance in label_row.get_object_instances():
        for annotation in object_instance.get_annotations():
            if start_frame_number <= annotation.frame <= end_frame_number:
                print ("Frame: " + str(annotation.frame))
                print ("objectHash: " + object_instance.object_hash)
                print ("Object name: " + object_instance.object_name)
                print ("featureHash: " + object_instance.feature_hash)
                print ("uid: " + str(object_instance.ontology_item.uid))
                print ("Object color: " + object_instance.ontology_item.color)
                print ("Ontology shape: " + object_instance.ontology_item.shape)
                print (f"Label location: {annotation.coordinates}")

            # Print all attributes
            for attribute in object_instance.ontology_item.attributes:
                print_attributes(attribute, object_instance)

    # Print all essential classification information on specified frames
    for classification_instance in label_row.get_classification_instances():
        for annotation in classification_instance.get_annotations():
            if start_frame_number <= annotation.frame <= end_frame_number:
                print("Classification hash: " + classification_instance.classification_hash)
                print("Classification name: " + classification_instance.classification_name)
                print("Feature hash: " + classification_instance.feature_hash)
                print("Classification value: " + classification_instance.get_answer().value)
                print("Classification answer hash: " + classification_instance.get_answer().feature_node_hash)
Frame: 0
objectHash: U88+HXj4
Object name: Person
featureHash: AaaPMAgE
uid: 1
Object color: #15d3bc
Ontology shape: bounding_box
Label location: BoundingBoxCoordinates(height=0.519561557605036, width=0.15380023056653513, top_left_x=0.43242033102766797, top_left_y=0.0028114478114478862)
Attribute name: Man or woman
Attribute hash: X0Xhz9ip
Attribute answer: NestableOption(feature_node_hash='MN57hMep', uid=[1, 1, 1], label='Man', value='Man', nested_options=[])
Frame: 44
objectHash: nZWuD66O
Object name: Person
featureHash: AaaPMAgE
uid: 1
Object color: #15d3bc
Ontology shape: bounding_box
Label location: BoundingBoxCoordinates(height=0.46671424388815697, width=0.1688282279314888, top_left_x=0.37747550230566534, top_left_y=0.07887095593617346)
Attribute name: Man or woman
Attribute hash: X0Xhz9ip
Attribute answer: None
Classification hash: biZZZov4
Classification name: Day or Night?
Feature hash: T+P+wwjw
Classification value: Day
Classification answer hash: t+QtqkFp

List of non-consecutive frames

The following scripts download and print the labels for specific frames in videos.

Make sure you substitute:

  • The <private_key_path> with the full path to your private key.
  • The <project_hash> with the hash of your Project.
  • The <task_name> with the name of the file (in Encord) you want to export labels for (if using the task-specific script).
  • Replace the numbers in the list [10, 20, 30, 40] with the frames you want to export labels for.
# Import dependencies
from encord import EncordUserClient
from encord.objects.ontology_element import OntologyElement
from encord.objects.attributes import Attribute, Option
from encord.objects import ObjectInstance
from collections.abc import Iterable

# Instantiate Encord client
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path="<private_key_path>"
)

# Replace with the hash of your Project
project = user_client.get_project("<project_hash>")

# Function to extract and print essential information for all attributes
def print_attributes(attribute: Attribute, object_instance: ObjectInstance):
    print(f"Attribute name: {attribute.title}")
    print(f"Attribute hash: {attribute.feature_node_hash}")
    print(f"Attribute answer: {object_instance.get_answer(attribute)}")

# List of specific frames to be exported
specific_frames = [10, 20, 30, 40]  # Replace with your specific frame numbers

for label_row in project.list_label_rows_v2(data_title_eq="<task_name>"):

    # Download all labels
    label_row.initialise_labels()
    
    # Print essential label information for all objects
    for object_instance in label_row.get_object_instances():
        for annotation in object_instance.get_annotations():
            if annotation.frame in specific_frames:
                print("Frame: " + str(annotation.frame))
                print("objectHash: " + object_instance.object_hash)
                print("Object name: " + object_instance.object_name)
                print("featureHash: " + object_instance.feature_hash)
                print("uid: " + str(object_instance.ontology_item.uid))
                print("Object color: " + object_instance.ontology_item.color)
                print("Ontology shape: " + object_instance.ontology_item.shape)
                print(f"Label location: {annotation.coordinates}")

                # Print all attributes
                for attribute in object_instance.ontology_item.attributes:
                    print_attributes(attribute, object_instance)

    # Print essential classification information on specified frames
    for classification_instance in label_row.get_classification_instances():
        for annotation in classification_instance.get_annotations():
            if annotation.frame in specific_frames:
                print("Classification hash: " + classification_instance.classification_hash)
                print("Classification name: " + classification_instance.classification_name)
                print("Feature hash: " + classification_instance.feature_hash)
                print("Classification value: " + classification_instance.get_answer().value)
                print("Classification answer hash: " + classification_instance.get_answer().feature_node_hash)

# Import dependencies
from encord import EncordUserClient
from encord.objects.ontology_element import OntologyElement
from encord.objects.attributes import Attribute, Option
from encord.objects import ObjectInstance
from collections.abc import Iterable

# Instantiate Encord client
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path="<private_key_path>"
)

# Replace with the hash of your Project
project = user_client.get_project("<project_hash>")

# Function to extract and print essential information for all attributes
def print_attributes(attribute: Attribute, object_instance: ObjectInstance):
    print(f"Attribute name: {attribute.title}")
    print(f"Attribute hash: {attribute.feature_node_hash}")
    print(f"Attribute answer: {object_instance.get_answer(attribute)}")

# List of specific frames
specific_frames = [10, 20, 30, 40]  # Replace with your specific frame numbers

for label_row in project.list_label_rows_v2():

    # Download all labels
    label_row.initialise_labels()
    
    # Print essential label information for all objects
    for object_instance in label_row.get_object_instances():
        for annotation in object_instance.get_annotations():
            if annotation.frame in specific_frames:
                print("Frame: " + str(annotation.frame))
                print("objectHash: " + object_instance.object_hash)
                print("Object name: " + object_instance.object_name)
                print("featureHash: " + object_instance.feature_hash)
                print("uid: " + str(object_instance.ontology_item.uid))
                print("Object color: " + object_instance.ontology_item.color)
                print("Ontology shape: " + object_instance.ontology_item.shape)
                print(f"Label location: {annotation.coordinates}")

                # Print all attributes
                for attribute in object_instance.ontology_item.attributes:
                    print_attributes(attribute, object_instance)

    # Print essential classification information on specified frames
    for classification_instance in label_row.get_classification_instances():
        for annotation in classification_instance.get_annotations():
            if annotation.frame in specific_frames:
                print("Classification hash: " + classification_instance.classification_hash)
                print("Classification name: " + classification_instance.classification_name)
                print("Feature hash: " + classification_instance.feature_hash)
                print("Classification value: " + classification_instance.get_answer().value)
                print("Classification answer hash: " + classification_instance.get_answer().feature_node_hash)
Frame: 10
objectHash: U88+HXj4
Object name: Person
featureHash: AaaPMAgE
uid: 1
Object color: #15d3bc
Ontology shape: bounding_box
Label location: BoundingBoxCoordinates(height=0.519561557605036, width=0.15380023056653513, top_left_x=0.43242033102766797, top_left_y=0.0028114478114478862)
Attribute name: Man or woman
Attribute hash: X0Xhz9ip
Attribute answer: NestableOption(feature_node_hash='MN57hMep', uid=[1, 1, 1], label='Man', value='Man', nested_options=[])
Frame: 20
objectHash: nZWuD66O
Object name: Person
featureHash: AaaPMAgE
uid: 1
Object color: #15d3bc
Ontology shape: bounding_box
Label location: BoundingBoxCoordinates(height=0.46671424388815697, width=0.1688282279314888, top_left_x=0.37747550230566534, top_left_y=0.07887095593617346)
Attribute name: Man or woman
Attribute hash: X0Xhz9ip
Attribute answer: None
Classification hash: biZZZov4
Classification name: Day or Night?
Feature hash: T+P+wwjw
Classification value: Day
Classification answer hash: t+QtqkFp

Saving frames with labels on them

ffmpeg can be used to save all frames with labels as an image, to be used in machine learning applications. The script below shows how this is done when exporting a list of non-consecutive frames from a specific video.

ℹ️

Note

ffmpeg must be installed for this script to work.

Make sure you substitute:

  • The <output_folder_path> with the full path to the output folder you want the output image files to be saved.
  • The <private_key_path> with the full path to your private key.
  • The <project_hash> with the hash of your Project.
  • The <task_name> with the name of the file in Encord you want to export labels for..
  • The <path_to_your_video_file> with the full path to the video file you are exporting labels for.
  • Replace the numbers in the list [10, 20, 30, 40] with the frames you want to export labels for.
# Import dependencies
from encord import EncordUserClient
from encord.objects.ontology_element import OntologyElement
from encord.objects.attributes import Attribute, Option
from encord.objects import ObjectInstance
from collections.abc import Iterable
import subprocess
import os

# Specify the output folder path. Replace with your desired folder path
output_folder = "<output_folder_path>" 

# Create the output folder if it doesn't exist
if not os.path.exists(output_folder):
    os.makedirs(output_folder)

def extract_frame_to_image(video_file, frame_number, output_file):
    """
    Uses FFmpeg to extract a specific frame from a video and saves it as an image.
    """
    ffmpeg_command = [
        'ffmpeg', '-i', video_file, '-vf', f'select=eq(n\,{frame_number})',
        '-vframes', '1', output_file
    ]
    subprocess.run(ffmpeg_command, check=True)

# Instantiate Encord client
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path="<private_key_path>"
)

# Replace with the hash of your Project
project = user_client.get_project("<project_hash>")

# Function to extract and print essential information for all attributes
def print_attributes(attribute: Attribute, object_instance: ObjectInstance):
    print(f"Attribute name: {attribute.title}")
    print(f"Attribute hash: {attribute.feature_node_hash}")
    print(f"Attribute answer: {object_instance.get_answer(attribute)}")

# List of specific frames to be exported. Replace with your specific frame numbers
specific_frames = [10, 20, 30, 40] 

# Path to the video file you are exporting labels for
video_path = "<path_to_your_video_file>" 

for label_row in project.list_label_rows_v2(data_title_eq="<task_name>"):

    # Download all labels
    label_row.initialise_labels()
    
    # Print essential label information for all objects
    for object_instance in label_row.get_object_instances():
        for annotation in object_instance.get_annotations():
            if annotation.frame in specific_frames:
                print("Frame: " + str(annotation.frame))
                print("objectHash: " + object_instance.object_hash)
                print("Object name: " + object_instance.object_name)
                print("featureHash: " + object_instance.feature_hash)
                print("uid: " + str(object_instance.ontology_item.uid))
                print("Object color: " + object_instance.ontology_item.color)
                print("Ontology shape: " + object_instance.ontology_item.shape)
                print(f"Label location: {annotation.coordinates}")

                # Define the output path for the image
                output_image_path = os.path.join(output_folder, f"frame_{annotation.frame}.png")
                
                # Extract and save the specific frame as an image
                extract_frame_to_image(video_path, annotation.frame, output_image_path)

                # Print all attributes
                for attribute in object_instance.ontology_item.attributes:
                    print_attributes(attribute, object_instance)

    # Print essential classification information on specified frames
    for classification_instance in label_row.get_classification_instances():
        for annotation in classification_instance.get_annotations():
            if annotation.frame in specific_frames:
                print("Classification hash: " + classification_instance.classification_hash)
                print("Classification name: " + classification_instance.classification_name)
                print("Feature hash: " + classification_instance.feature_hash)
                print("Classification value: " + classification_instance.get_answer().value)
                print("Classification answer hash: " + classification_instance.get_answer().feature_node_hash)

Label editor coordinates

All label locations are exported as normalized coordinates ranging from 0 to 1. This means that the corners of the frame or image correspond to the coordinates (1,1), (1,0), (0,0), (0,1) regardless of frame dimensions.

To get the pixel values of any normalized coordinates, multiply them by the width or height of the label (given in pixels).

  • "x" and "h" coordinates of a label should be multiplied by the pixel height.
  • "y" and "w" coordinates of a label should be multiplied by the pixel width.

Export all Consensus labels

Consensus Projects introduce the concept of BRANCHES within the task workflow. A Consensus annotation task consists of a MAIN branch and one sub-branch for each Annotator. Each time an annotator saves or submits a task, the annotator creates their own branch on a task. The MAIN branch remains empty of labels until a reviewer specifies that a task is in consensus. When consensus is reached, the labels that are the best representative set move to the MAIN branch. To export all labels (labels generated for every branch on every data unit) from your Consensus Project, use include_all_branches=True.

Make sure you:

  • Substitute the <private_key_path> with the full path to your private key.
  • Substitute the <project_hash> with the hash of your Project.
  • If you only want to export the MAIN branch, remove include_all_label_branches=True.
# Import dependencies

from encord import EncordUserClient

# Instantiate client. Replace <private_key_path> with the path to the file containing your private key.
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path="<private_key_path>"
)

# Specify Project. Replace <project_hash> with the hash of the Project you want to export labels for.
project = client.get_project("<project_hash>")

# Downloads a local copy of all the labels
# Without the include_all_label_branches flag only the MAIN branch labels export
label_rows = project.list_label_rows_v2(include_all_label_branches=True) 

for label_row in label_rows:
    # Here we have the label row for the branch, but without labels themselves downloaded
    print(f"Title: {label_row.data_title}, branch: {label_row.branch_name}")

    # And now we download the label content itself (bounding boxes and stuff)
    label_row.initialise_labels()

    # Print essential label information for all objects
    for object_instance in label_row.get_object_instances():
        print (f"objectHash: {object_instance.object_hash}")
        print (f"Object name: {object_instance.object_name}")
        print (f"featureHash: {object_instance.feature_hash}")
        print (f"uid: {object_instance.ontology_item.uid}")
        print (f"Object color: {object_instance.ontology_item.color}")
        print (f"Ontology shape: {object_instance.ontology_item.shape}")

        # Print the frame number and the location of the object on the frame
        for annotation in object_instance.get_annotations():
            print(f"Frame {annotation.frame} -> {annotation.coordinates}")

        # Print all attributes 
        for attribute in object_instance.ontology_item.attributes:
            print_attributes(attribute, object_instance)

    # Print all essential classification information
    for classification_instance in label_row.get_classification_instances():
        print (f"classificationHash: {classification_instance.classification_hash}")
        print (f"Classification name: {classification_instance.classification_name}")
        print (f"featureHash: {classification_instance.feature_hash}")
        print (f"Classification answer: {classification_instance.get_answer().value}")
        print (f"Classification answer hash: {classification_instance.get_answer().feature_node_hash}")


        # Print the frame number(s) that a classification appears on
        for annotation in classification_instance.get_annotations():
            print(f"Classification appears on frame: {annotation.frame}")

Export labels in bulk

Use the bundle function to significantly improve export performance.

❗️

CRITICAL INFORMATION

We strongly recommend NOT bundling more than 100 operations at once, because bundling more than 100 operations can reduce performance instead of improving performance.


# Import dependencies
from pathlib import Path

from encord import EncordUserClient, Project
from encord.objects import (
    Object,
    ObjectInstance,
    OntologyStructure,
)
from encord.objects.coordinates import BoundingBoxCoordinates

SSH_PATH = "<file-path-to-ssh-private-key>"
PROJECT_HASH = "<unique-project-hash>"

user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(ssh_private_key_path=SSH_PATH)

# Gets Project to export labels. This Project already exists in Encord.
project: Project = user_client.get_project(PROJECT_HASH)

BATCH_SIZE = 100 # Batch size to split
label_rows = project.list_label_rows_v2()

label_row_batches = [label_rows[i:i+BATCH_SIZE] for i in range(0, len(label_rows), BATCH_SIZE)] # This code splits the label_rows into batches of size BATCH_SIZE
for labels_batch in label_row_batches:
    
    bundle_init = project.create_bundle()
    for label_row in labels_batch:
        label_row.initialise_labels(bundle=bundle_init) 

    # Fill the bundle with operations

    # Execute the bundle
    bundle_init.execute()