diff --git a/examples/annotation_import/image.ipynb b/examples/annotation_import/image.ipynb index f20b2c4ef..a196a9222 100644 --- a/examples/annotation_import/image.ipynb +++ b/examples/annotation_import/image.ipynb @@ -1,18 +1,16 @@ { - "nbformat": 4, - "nbformat_minor": 5, - "metadata": {}, "cells": [ { + "cell_type": "markdown", "metadata": {}, "source": [ "\n", " \n", "" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "\n", @@ -27,22 +25,22 @@ "\n", "" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "# Image annotation import\n", "This notebook will provide examples of each supported annotation type for image assets. \n", "\n", - "### [Model-assisted labeling (MAL)](https://docs.labelbox.com/v4/docs/model-assisted-labeling)\n", + "### [Model-assisted labeling (MAL)](https://docs.labelbox.com/docs/model-assisted-labeling)\n", "\n", "* This workflow allows you to import computer-generated predictions (or simply annotations created outside of Labelbox) as pre-labels on an asset. \n", "\n", "The imported annotations will be pre-populated in the labeling editor. However, in order to convert the pre-labels to real annotations, a human labeler will still need to open the Data Row in the Editor and submit it. This functionality is designed to speed up human labeling.\n", "\n", - "### [Import ground truth](https://docs.labelbox.com/v4/docs/import-ground-truth)\n", + "### [Import ground truth](https://docs.labelbox.com/docs/import-ground-truth)\n", "\n", "* This workflow functionality allows you to bulk import your ground truth annotations from an external or third-party labeling system into Labelbox Annotate. Using the label import API to import external data is a useful way to consolidate and migrate all annotations into Labelbox as a single source of truth.\n", "\n", @@ -62,72 +60,74 @@ "- Ability to create the payload in the NDJSON import format directly\n", "\n", "- It supports any levels of nested classification (free text / radio / checklist) under the object or classification annotation." - ], - "cell_type": "markdown" + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "## Setup" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "!pip install -q \"labelbox[data]\"" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "import uuid\n", "import numpy as np\n", "import labelbox as lb\n", "import labelbox.types as lb_types" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "## Replace with your API key\n", "\n", "Guides on [Create an API key](https://docs.labelbox.com/docs/create-an-api-key)" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "API_KEY = \"\"\n", "client = lb.Client(API_KEY)" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "## Supported annotations for image\n" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "### Radio classification" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# Python annotation\n", "radio_annotation = lb_types.ClassificationAnnotation(\n", @@ -142,21 +142,21 @@ " \"name\": \"second_radio_answer\"\n", " }\n", "}" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "### Nested radio and checklist classification\n", "\n" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "nested_radio_annotation = lb_types.ClassificationAnnotation(\n", " name=\"nested_radio_question\",\n", @@ -221,20 +221,20 @@ " }]\n", " }]\n", "}" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "### Checklist question" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# Python annotation\n", "checklist_annotation = lb_types.ClassificationAnnotation(\n", @@ -253,20 +253,20 @@ " \"name\": \"second_checklist_answer\"\n", " }]\n", "}" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "### Free form text classification" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# Python annotation\n", "text_annotation = lb_types.ClassificationAnnotation(\n", @@ -278,20 +278,20 @@ " \"name\": \"free_text\",\n", " \"answer\": \"sample text\",\n", "}" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "### Bounding box" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# Python annotation\n", "bbox_annotation = lb_types.ObjectAnnotation(\n", @@ -311,20 +311,20 @@ " \"width\": 225\n", " }\n", "}" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "### Bounding box with nested classification" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# Python annotation\n", "bbox_with_radio_subclass_annotation = lb_types.ObjectAnnotation(\n", @@ -356,20 +356,20 @@ " \"width\": 330\n", " }\n", "}" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "### Polygon" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# Python annotation\n", "polygon_annotation = lb_types.ObjectAnnotation(\n", @@ -415,20 +415,20 @@ " {\"x\": 1489.581, \"y\": 183.934}\n", " ]\n", "}" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "### Mask" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# Identifying what values in the numpy array correspond to the mask annotation\n", "color = (0, 0, 0)\n", @@ -458,20 +458,20 @@ " \"mask\": {\"instanceURI\": \"https://storage.labelbox.com/cjhfn5y6s0pk507024nz1ocys%2F1d60856c-59b7-3060-2754-83f7e93e0d01-1?Expires=1666901963361&KeyName=labelbox-assets-key-3&Signature=t-2s2DB4YjFuWEFak0wxYqfBfZA\",\n", " \"colorRGB\": (0, 0, 0)}\n", "}" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "### Point" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# Python annotation\n", "point_annotation = lb_types.ObjectAnnotation(\n", @@ -488,20 +488,20 @@ " \"y\": 1441.768\n", " }\n", "}" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "### Polyline" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# Python annotation\n", "polyline_annotation = lb_types.ObjectAnnotation(\n", @@ -560,22 +560,22 @@ " {\"x\": 90.929, \"y\": 326.412}\n", " ]\n", "}" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "### Relationship\n", "> **NOTE:** \n", "> Only supported for MAL imports" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# Python Annotation\n", "bbox_source = lb_types.ObjectAnnotation(\n", @@ -636,28 +636,28 @@ " \"type\": \"unidirectional\"\n", " }\n", "}" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "# Uploading annotations - putting it all together\n" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "## Step 1: Import data rows into catalog\n", "\n" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# send a sample image as batch to the project\n", "global_key = \"2560px-Kitano_Street_Kobe01s5s41102.jpeg\"\n", @@ -675,23 +675,23 @@ "\n", "print(f\"Errors: {task.errors}\")\n", "print(f\"Failed data rows: {task.failed_data_rows}\")" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "## Step 2: Create/select an ontology\n", "Your project should have the correct ontology setup with all the tools and classifications supported for your annotations and the tool names and classification instructions should match the `name` fields in your annotations to ensure the correct feature schemas are matched.\n", "\n", "For example, when we created the bounding box annotation above, we provided the `name` as `bounding_box`. Now, when we setup our ontology, we must ensure that the name of the bounding box tool is also `bounding_box`. The same alignment must hold true for the other tools and classifications we create in our ontology." - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "ontology_builder = lb.OntologyBuilder(\n", " classifications=[ # List of Classification objects\n", @@ -756,21 +756,21 @@ " ontology_builder.asdict(),\n", " media_type=lb.MediaType.Image\n", " )" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "## Step 3: Create a labeling project\n", "Connect the ontology to the labeling project" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# Project defaults to batch mode with benchmark quality settings if this argument is not provided\n", "# Queue mode will be deprecated once dataset mode is deprecated\n", @@ -779,20 +779,20 @@ " queue_mode=lb.QueueMode.Batch)\n", "\n", "project.setup_editor(ontology)" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "## Step 4: Send a batch of data rows to the project\n" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "batch = project.create_batch(\n", " \"image-demo-batch\", # each batch in a project must have a unique name\n", @@ -803,12 +803,10 @@ ")\n", "\n", "print(f\"Batch: {batch}\")" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "## Step 5: Create the annotations payload\n", @@ -816,20 +814,22 @@ "Create the annotations payload using the snippets of code above\n", "\n", "Labelbox support two formats for the annotations payload: NDJSON and Python Annotation types. Both are described below. If you are using Python Annotation types, compose your annotations into Labels attached to the data rows." - ], - "cell_type": "markdown" + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "### Python annotations\n", "\n", "Here we create the complete label ndjson payload of annotations only using python annotation format. There is one annotation for each reference to an annotation that we created." - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "labels = []\n", "annotations = [\n", @@ -851,21 +851,21 @@ "labels.append(\n", " lb_types.Label(data=lb_types.ImageData(global_key=global_key),\n", " annotations=annotations))" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "### NDJSON annotations\n", "Here we create the complete label ndjson payload of annotations only using NDJSON format. There is one annotation for each reference to an annotation that we created above." - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "ndjson_labels = []\n", "annotations = [\n", @@ -891,28 +891,28 @@ " },\n", " })\n", " ndjson_labels.append(annotation)" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "## Step 6: Upload annotations to a project as pre-labels or ground truth\n", "For the purpose of this tutorial only import one of the annotations payloads at the time (NDJSON or Python annotation types)." - ], - "cell_type": "markdown" + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "Option A: Upload to a labeling project as pre-labels (MAL)" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# upload MAL labels for this data row in project\n", "upload_job = lb.MALPredictionImport.create_from_objects(\n", @@ -925,20 +925,20 @@ "\n", "print(f\"Errors: {upload_job.errors}\", )\n", "print(f\"Status of uploads: {upload_job.statuses}\")" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "markdown", "metadata": {}, "source": [ "Option B: Upload to a labeling project using ground truth" - ], - "cell_type": "markdown" + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# Uncomment if relationships are not being imported. \n", "# Relationships will be supported for label import in the near future. \n", @@ -953,20 +953,24 @@ "# print(\"Errors:\", upload_job.errors)\n", "# print(\"Status of uploads: \", upload_job.statuses)\n", "# print(\" \")" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] }, { + "cell_type": "code", + "execution_count": null, "metadata": {}, + "outputs": [], "source": [ "# project.delete()\n", "# dataset.delete()" - ], - "cell_type": "code", - "outputs": [], - "execution_count": null + ] } - ] -} \ No newline at end of file + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}