> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.ovalbee.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.ovalbee.com/_mcp/server.

# Transform annotations

> Writes a dataset's images with transformed annotations into another dataset: keeps selected classes, keeps a single label shape, and renames classes.

## Overview

Writes a dataset's images into another dataset with transformed annotations. You pick any combination of three changes:

* keep only the classes you select
* keep only labels drawn with one shape
* rename classes, merging the ones that end up sharing a name

Reach for this node when one object carries several shapes at once, such as a mask, a polygon, and a box, and your training, prediction, or evaluation step needs one shape per class.

```mermaid
flowchart LR
  n1["Dataset"] --> n2["Transform annotations"] --> n3["Dataset"]
```

## Prerequisites

| Requirement          | What you need                                                                                                                    |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| **Annotated images** | Existing image dataset whose images already carry annotations, from the [Dataset](/node-library/nodes/dataset-ops-dataset) node. |

## How it works

Reads the dataset and resolves the selected classes, shape, and class mapping.

Removes labels of unselected classes, then labels drawn with another shape, then renames the classes that remain.

Gives every remaining class the one shape its labels still use, so a class filtered down to boxes is declared as a box class rather than a mixed one.

Adds the source images and the new annotations to the output dataset, leaving the source dataset untouched.

Adds the remaining class names to the output dataset's class list and ontology, then refreshes its statistics.

## FAQ

#### Which shape should I keep for my task?

Bounding box prepares a dataset for object detection, mask or polygon for segmentation, and keypoints for pose estimation. Each option is exactly one shape, so masks and polygons are kept separately rather than together.

#### What happens to a class that carries several shapes at once?

Only the labels of the selected shape stay. Take a class that holds a mask, a polygon, and a bounding box for the same object: with Keep shape set to Bounding box, the box survives and the other two labels are removed.

#### What happens to a class that has no labels of the selected shape?

Its labels are removed like any other non-matching shape, and because nothing is left, the class also drops out of the dataset class list.

#### In what order do the three transformations run?

Classes first, then shape, then renaming. Keep classes and Keep shape therefore refer to the original class names, which is what the pickers show.

#### What happens to the source dataset?

Nothing. The images and the transformed annotations go to the output dataset, and the original annotations stay where they are. Selecting the source dataset as the output fails, because every image would then carry both the original and the transformed annotations.

#### What happens when I leave all three changes empty?

The run fails and asks you to select at least one of Keep classes, Keep shape, or Rename classes.

#### What happens to an image whose labels are all removed?

It keeps an annotation with no labels and stays in the dataset. Images without objects are valid negative samples for training and evaluation.

#### What happens when two classes end up sharing a name?

They merge into one, which is the point of the input: `Resestor = Resistor` folds a misspelled class into the correct one. The same holds for several classes renamed to one name. The surviving class keeps the color of the class that already carried the name, and it claims every shape its labels now use, so a merge of a box class and a mask class stops naming one concrete shape.

#### What happens when the node runs twice into the same output dataset?

The images are added once, but each run writes a new annotation for every image, so an image can end up with several annotation sets. The node warns when the output dataset already holds annotations. Point it at an empty dataset when you want a single set of results.

#### What does this node not support?

Video annotations are not supported, and the node cannot convert one shape into another, so it removes masks rather than turning them into boxes.

## Inputs

**`Dataset`** `dataset` — required

Dataset containing the image assets and annotations to transform. Key: `DATASET`.

---

**`Output dataset`** `dataset` — required

Destination dataset for the images and the transformed annotations. It must differ from the source dataset. Key: `OUTPUT_DATASET`.

---

**`Keep classes`** `ontology`

Classes to keep - annotations of every other class are removed. Leave empty to keep all classes. Values come from `DATASET`. Key: `CLASSES`.

---

**`Keep shape`** `select`

Shape to keep - annotations drawn with any other shape are removed. Leave empty to keep every shape. Key: `KEEP_SHAPE`.

Options:

* Bounding box (`bbox`)
* Polygon (`polygon`)
* Mask (`mask`)
* Polyline (`line`)
* Point (`point`)
* Keypoints (`graph`)

---

**`Rename classes`** `string`

Pairs of old and new class name, for example: blue = red, yellow = green. Classes you leave out keep their name, and renaming runs after the class and shape filters, so both of those refer to the original names. Renaming a class onto a name another class already uses merges the two, which is how a misspelled class is folded into the correct one. Placeholder: `blue = red, yellow = green`. Key: `CLASS_MAPPING`.

---

## Outputs

**`Output Dataset`** `dataset`

Dataset holding the source images and the transformed annotations. Shown as an artifact. Key: `OUTPUT_DATASET`.

---

**`Count`** `string`

Number of annotations written and labels removed. Shown on the node as a badge. Selecting the badge opens `OUTPUT_DATASET`. Key: `COUNT`.

---

## JSON config

Machine-readable node interface for automation and advanced usage.

#### Show JSON

```json
{
  "name": "Transform annotations",
  "description": "Writes a dataset's images with transformed annotations into another dataset: keeps selected classes, keeps a single label shape, and renames classes.\n",
  "category": "Assets",
  "namespace": "ovalbee",
  "templateKey": "asset_ops/transform_annotations",
  "version": "v1",
  "inputs": [
    {
      "key": "DATASET",
      "label": "Dataset",
      "type": "dataset",
      "description": "Dataset containing the image assets and annotations to transform.",
      "required": true,
      "default": null,
      "visibleWhen": null,
      "options": {
        "creatable": false
      }
    },
    {
      "key": "OUTPUT_DATASET",
      "label": "Output dataset",
      "type": "dataset",
      "description": "Destination dataset for the images and the transformed annotations. It must differ from the source dataset.\n",
      "required": true,
      "default": null,
      "visibleWhen": null
    },
    {
      "key": "CLASSES",
      "label": "Keep classes",
      "type": "ontology",
      "description": "Classes to keep - annotations of every other class are removed. Leave empty to keep all classes.",
      "required": false,
      "default": null,
      "visibleWhen": null,
      "options": {
        "ref": "DATASET",
        "selectable": true
      }
    },
    {
      "key": "KEEP_SHAPE",
      "label": "Keep shape",
      "type": "select",
      "description": "Shape to keep - annotations drawn with any other shape are removed. Leave empty to keep every shape.",
      "required": false,
      "default": null,
      "visibleWhen": null,
      "options": {
        "options": [
          {
            "label": "Bounding box",
            "value": "bbox"
          },
          {
            "label": "Polygon",
            "value": "polygon"
          },
          {
            "label": "Mask",
            "value": "mask"
          },
          {
            "label": "Polyline",
            "value": "line"
          },
          {
            "label": "Point",
            "value": "point"
          },
          {
            "label": "Keypoints",
            "value": "graph"
          }
        ]
      }
    },
    {
      "key": "CLASS_MAPPING",
      "label": "Rename classes",
      "type": "string",
      "description": "Pairs of old and new class name, for example: blue = red, yellow = green. Classes you leave out keep their name, and renaming runs after the class and shape filters, so both of those refer to the original names. Renaming a class onto a name another class already uses merges the two, which is how a misspelled class is folded into the correct one.\n",
      "required": false,
      "default": null,
      "visibleWhen": null,
      "options": {
        "placeholder": "blue = red, yellow = green"
      }
    }
  ],
  "outputs": [
    {
      "key": "OUTPUT_DATASET",
      "label": "Output Dataset",
      "type": "dataset",
      "description": "Dataset holding the source images and the transformed annotations.\n",
      "artifact": true,
      "badge": false,
      "badgeOpens": null,
      "hidden": false
    },
    {
      "key": "COUNT",
      "label": "Count",
      "type": "string",
      "description": "Number of annotations written and labels removed.",
      "artifact": false,
      "badge": true,
      "badgeOpens": "OUTPUT_DATASET",
      "hidden": false
    }
  ]
}
```