Tutorial

Installation

SDK is available on PyPI:

pip install superannotate

for COCO annotation format converters support also need to install:

pip install "git+https://github.com/cocodataset/panopticapi.git"
pip install "git+https://github.com/philferriere/cocoapi.git#egg=pycocotools&subdirectory=PythonAPI"

The package officially supports Python 3.6+ and was tested under Linux and Windows (Anaconda) platforms.

For Windows based Anaconda distribution you might also need to install beforehand shapely package:

conda install shapely

and C++ build tools from Microsoft Visual Studio Tools.


Config file

To use the SDK, a config file with team specific authentication token needs to be created. The token is available to team admins on team setting page at https://app.superannotate.com/team.

Default location config file

To generate a default location (~/.superannotate/config.json) config file, CLI init can be used:

superannotatecli init

Custom config file

To create a custom config file a new JSON file with key “token” can be created:

{
  "token" : "<team token>"
}

Initialization and authorization

Include the package in your Python code:

import superannotate as sa

SDK is ready to be used if default location config file was created using the CLI init. Otherwise to authenticate SDK with the custom config file:

sa.init("<path_to_config_json>")

Creating a project

To create a new “Vector” project with name “Example Project 1” and description “test”:

project = "Example Project 1"

sa.create_project(project, "test", "Vector")

Uploading images to project

To upload all images with extensions “jpg” or “png” from the "<local_folder_path>" to the project “Example Project 1”:

sa.upload_images_from_folder_to_project(project, "<local_folder_path>")

See the full argument options for upload_images_from_folder_to_project() here.

For full list of available functions on projects, see Projects.

Note

Python SDK functions that accept project argument will accept both project name or project metadata (returned either by get_project_metadata or search_projects with argument return_metadata=True). If project name is used it should be unique in team’s project list. Using project metadata will give performance improvement.

Note

CLI command upload-images can also be used for image upload.

Working with annotation classes

An annotation class for a project can be created with SDK’s:

sa.create_annotation_class(project, "Large car", color="#FFFFAA")

To create annotation classes in bulk with SuperAnnotate export format classes.json (documentation at: https://app.superannotate.com/documentation Management Tools -> Project Workflow part):

sa.create_annotation_classes_from_classes_json(project, "<path_to_classes_json>")

All of the annotation classes of a project are downloaded (as classes/classes.json) with download_export along with annotations, but they can also be downloaded separately with:

sa.download_annotation_classes_json(project, "<path_to_local_folder>")

The classes.json file will be downloaded to "<path_to_local_folder>" folder.

Working with annotations

The SuperAnnotate format annotation JSONs have the general form:

[
  {
    "className": "Human",
    "points" : "...",
    "..." : "..."
  },
  {
    "className": "Cat",
    "points" : "...",
    "..." : "..."
  },
  {
    "..." : "..."
  }
]

the “className” fields here will identify the annotation class of an annotation object (polygon, points, etc.). The project you are uploading to should contain annotation class with that name.

To upload annotations to platform:

sa.upload_annotations_from_folder_to_project(project, "<path_to_local_dir>")

This will try uploading to the project all the JSON files in the folder that have specific file naming convention. For vector projects JSONs should be named "<image_name>___objects.json". For pixel projects JSON files should be named "<image_name>___pixel.json" and also for each JSON a mask image file should be present with the name "<image_name>___save.png". Image with <image_name> should already be present in the project for the upload to work.

You can add an annotation to local annotations JSON with:

sa.add_annotation_bbox_to_json("<path_to_json>", [10, 10, 100, 100],
                               "Human")

Exporting projects

To export the project annotations we need to prepare the export first:

export = sa.prepare_export(project, include_fuse=True)

We can download the prepared export with:

sa.download_export(project, export, "<local_folder_path>", extract_zip_contents=True)

download_export will wait until the export is finished preparing and download it to the specified folder.

Warning

Starting from version 1.9.0 download_export additionally requires project as first argument.

Converting annotation format

After exporting project annotations (in SuperAnnotate format), it is possible to convert them to other annotation formats:

sa.export_annotation_format("<input_folder>", "<output_folder>", "<dataset_format>", "<dataset_name>",
"<project_type>", "<task>", "<platform>")

Note

Right now we support only SuperAnnotate annotation format to COCO annotation format conversion, but you can convert from “COCO”, “Pascal VOC” or “LabelBox” annotation formats to SuperAnnotate annotation format.

You can find more information annotation format conversion here. We provide some examples in our GitHub repository. In the root folder of our github repository, you can run following commands to do conversions.

import superannotate as sa

 # From SA panoptic format to COCO panoptic format
 sa.export_annotation_format(
    "tests/converter_test/COCO/input/fromSuperAnnotate/cats_dogs_panoptic_segm",
    "tests/converter_test/COCO/output/panoptic",
    "COCO", "panoptic_test", "Pixel","panoptic_segmentation","Web"
 )

 # From COCO keypoints detection format to SA keypoints detection desktop application format
 sa.import_annotation_format(
    "tests/converter_test/COCO/input/toSuperAnnotate/keypoint_detection",
    "tests/converter_test/COCO/output/keypoints",
    "COCO", "person_keypoints_test", "Vector", "keypoint_detection", "Desktop"
 )

 # Pascal VOC annotation format to SA Web platform annotation format
 sa.import_annotation_format(
    "tests/converter_test/VOC/input/fromPascalVOCToSuperAnnotate/VOC2012",
    "tests/converter_test/VOC/output/instances",
    "VOC", "instances_test", "Pixel", "instance_segmentation", "Web"
 )

 # YOLO annotation format to SA Web platform annotation format
 sa.import_annotation_format(
   'tests/converter_test/YOLO/input/toSuperAnnotate',
   'tests/converter_test/YOLO/output',
   'YOLO', '', 'Vector', 'object_detection', 'Web'
   )

 # LabelBox annotation format to SA Desktop application annotation format
 sa.import_annotation_format(
    "tests/converter_test/LabelBox/input/toSuperAnnotate/",
    "tests/converter_test/LabelBox/output/objects/",
    "LabelBox", "labelbox_example", "Vector", "object_detection", "Desktop"
 )

 # Supervisely annotation format to SA Web platform annotation format
 sa.import_annotation_format(
    "tests/converter_test/Supervisely/input/toSuperAnnotate",
    "tests/converter_test/Supervisely/output",
    "Supervisely", "", "Vector", "vector_annotation", "Web"
 )

 # DataLoop annotation format to SA Web platform annotation format
 sa.import_annotation_format(
    "tests/converter_test/DataLoop/input/toSuperAnnotate",
    "tests/converter_test/DataLoop/output",
    "DataLoop", "", "Vector", "vector_annotation", "Web"
 )

 # VGG annotation format to SA Web platform annotation format
 sa.import_annotation_format(
    "tests/converter_test/VGG/input/toSuperAnnotate",
    "tests/converter_test/VGG/output",
    "VGG", "vgg_test", "Vector", "instance_segmentation", "Web"
 )

 # VoTT annotation format to SA Web platform annotation format
 sa.import_annotation_format(
    "tests/converter_test/VoTT/input/toSuperAnnotate",
    "tests/converter_test/VoTT/output",
    "VoTT", "", "Vector", "vector_annotation", "Web"
 )

 # GoogleCloud annotation format to SA Web platform annotation format
 sa.import_annotation_format(
    "tests/converter_test/GoogleCloud/input/toSuperAnnotate",
    "tests/converter_test/GoogleCloud/output",
    "GoogleCloud", "image_object_detection", "Vector", "object_detection", "Web"
 )

 # GoogleCloud annotation format to SA desktop application annotation format
 sa.import_annotation_format(
    "tests/converter_test/SageMaker/input/toSuperAnnotate",
    "tests/converter_test/SageMaker/output",
    "SageMaker", "test-obj-detect", "Vector", "object_detection", "Desktop"
 )

Working with images

To download the image one can use:

image = "example_image1.jpg"

sa.download_image(project, image, "<path_to_local_dir>")

To download image annotations:

sa.download_image_annotations(project, image, "<path_to_local_dir>")

After the image annotations are downloaded, you can add annotations to it:

sa.add_annotation_bbox_to_json("<path_to_json>", [10, 10, 100, 100],
                               "Human")

and upload back to the platform with:

sa.upload_annotations_from_json_to_image(project, image, "<path_to_json>")

Last two steps can be combined into one:

sa.add_annotation_bbox_to_image(project, image, [10, 10, 100, 100], "Human")

but if bulk changes are made to many images it is much faster to add all required annotations using add_annotation_bbox_to_json then upload them using upload_annotations_from_folder_to_project.


Working with team contributors

A team contributor can be invited to the team with:

sa.invite_contributor_to_team(email="hovnatan@superannotate.com", admin=False)

This invitation should be accepted by the contributor. After which, to share the project with the found contributor as an QA:

sa.share_project(project, "hovnatan@superannotate.com", user_role="QA")

pandas DataFrame out of project annotations and annotation instance filtering

To create a pandas DataFrame from project SuperAnnotate format annotations:

df = sa.aggregate_annotations_as_df("<path_to_project_folder>")

The created DataFrame will have columns imageName, instanceId, className, attributeGroupName, attributeName, type, error, locked, visible, trackingId, probability, pointLabels, meta (geometry information as string), commentResolved, classColor, groupId.

Example of created DataFrame:

_images/pandas_df.png

Each row represents annotation information. One full annotation with multiple attribute groups can be grouped under instanceId field.

A helper function filter_annotation_instances is available to filter annotation instances by their class, attribute, type or error fields from the DataFrame. E.g., to get annotations that have annotation class Human and attribute "height" : "tall" that are not of type polygon:

filtered_df = sa.filter_annotation_instances(df, include=[{"className" : "Human",
                                                           "attributes" : [{"groupName" : "height",
                                                                           "name" : "tall"}]
                                                         }],
                                                 exclude=[{"type" : "polygon"}])

To transform back pandas DataFrame annotations to SuperAnnotate format annotation:

sa.df_to_annotations(filtered_df, "<path_to_output_folder>")

Aggregating class distribution across multiple projects

After exporting annotations from multiple projects, it is possible to aggregate class distribution of annotated instances as follows

df = sa.class_distribution("<path_to_export_folder>", [project_names])

Aggregated distribution is returned as pandas dataframe with columns className and count. Enabling visualize flag plots histogram of obtained distribution.

df = sa.class_distribution("<path_to_export_folder>", [project_names], visualize = True)
_images/class_distribution.png

Similarly aggregation of class attributes across multiple projects can be obtained with

df = sa.attribute_distribution("<path_to_export_folder>", [project_names], visualize = True)

Here pandas DataFrame with columns identifying attribute and corresponding instance count is returned. Within visualized histogram attributes of the same class are grouped by color and sorted accordingly.

_images/attribute_distribution.png

Working with DICOM files

To convert DICOM file images to JPEG images:

df = sa.dicom_to_rgb_sequence("<path_to_dicom_file>", "<path_to_output_dir>")

JPEG images with names <dicom_file_name>_<frame_num>.jpg will be created in <path_to_output_dir>. Those JPEG images can be uploaded to SuperAnnotate platform using the regular:

sa.upload_images_from_folder_to_project(project, "<path_to_output_dir>")

Some DICOM files can have image frames that are compressed. To load them, GDCM : Grassroots DICOM library needs to be installed:

# using conda
conda install -c conda-forge gdcm

# or on Ubuntu with versions above 19.04
sudo apt install python3-gdcm

Computing consensus scores for instances between several projects

Consensus is a tool to compare the quallity of the annotations of the same image that is present in several projects. To compute the consensus scores:

res_df = sa.consensus([project_names], "<path_to_export_folder>", [image_list], "<annotation_type>")

Here pandas DataFrame with following columns is returned: creatorEmail, imageName, instanceId, className, area, attribute, projectName, score

_images/consensus_dataframe.png

Besides the pandas DataFrame there is an option to get the following plots by setting the show_plots flag to True:

  • Box plot of consensus scores for each annotators
  • Box plot of consensus scores for each project
  • Scatter plots of consensus score vs instance area for each project
sa.consensus([project_names], "<path_to_export_folder>", [image_list], "<annotation_type>", show_plots=True)

To the left of each box plot the original score points of that annotator is depicted, the box plots are colored by annotator.

_images/consensus_annotators_box.png

Analogically the box plots of consensus scores for each project are colored according to project name.

_images/consensus_projects_box.png

Scatter plot of consensus score vs instance area is separated by projects. Hovering on a point reveals its annotator and image name. The points are colored according to class name. Each annotator is represented with separate symbol.

_images/consensus_scatter.png

Computing benchmark scores for instances between ground truth project and given project list

Benchmark is a tool to compare the quallity of the annotations of the same image that is present in several projects with the ground truth annotation of the same image that is in a separate project.

To compute the benchmark scores:

res_df = sa.benchmark("<ground_truth_project_name>",[project_names], "<path_to_export_folder>", [image_list], "<annotation_type>")

Here pandas DataFrame with exactly same structure as in case of consensus computation is returned.

Besides the pandas DataFrame there is an option to get the following plots by setting the show_plots flag to True:

  • Box plot of benchmark scores for each annotators
  • Box plot of benchmark scores for each project
  • Scatter plots of benchmark score vs instance area for each project
sa.benchmark("<ground_truth_project_name>", [project_names], "<path_to_export_folder>", [image_list], "<annotation_type>", show_plots=True)

To the left of each box plot the original score points of that annotator is depicted, the box plots are colored by annotator.

_images/benchmark_annotators_box.png

Analogically the box plots of benchmark scores for each project are colored according to project name.

_images/benchmark_projects_box.png

Scatter plot of benchmark score vs instance area is separated by projects. Hovering on a point reveals its annotator and image name. The points are colored according to class name. Each annotator is represented with separate symbol.

_images/benchmark_scatter.png