YOLO Vision 2026:

So konvertierst du COCO-Annotationen in das YOLO-Format#

Das Training von Ultralytics YOLO-Modellen erfordert Annotationen im YOLO-Format, aber viele beliebte Anmerkungs-Tools exportieren stattdessen im COCO JSON-Format. Dieser Leitfaden zeigt dir, wie du deine COCO-Annotationen in das YOLO-Format konvertierst und mit dem Training von Modellen zur Objekterkennung, Instanzsegmentierung und Posenschätzung beginnst.

Möchtest du die Konvertierung überspringen?

Um direkt mit COCO JSON zu trainieren, ohne .txt-Dateien zu generieren, siehe Trainieren von YOLO mit COCO JSON ohne Konvertierung.

Warum von COCO zu YOLO konvertieren?#

Das COCO JSON-Format speichert alle Annotationen in einer einzigen Datei, während YOLO eine Textdatei pro Bild mit normalisierten Koordinaten verwendet. Die Konvertierung ist aus folgenden Gründen erforderlich:

  • YOLO-Modelle erfordern .txt-Label-Dateien mit einer Datei pro Bild, die class x_center y_center width height in normalisierten Koordinaten enthält.
  • COCO JSON verwendet Pixelkoordinaten im Format [x_min, y_min, width, height] mit einer einzigen JSON-Datei für alle Bilder.
  • Klassen-IDs unterscheiden sich — COCO verwendet beliebige category_id-Werte, während YOLO bei null beginnende Klassen-IDs erfordert.
FunktionCOCO JSONYOLO TXT
StrukturEinzelne JSON-Datei für alle BilderEine .txt-Datei pro Bild
Bbox-Format[x_min, y_min, width, height] in Pixelnclass x_center y_center width height normalisiert (0-1)
Class IDscategory_id (kann bei einer beliebigen Zahl beginnen)Nullbasiert (beginnt bei 0)
SegmentierungPolygon-Arrays im Feld segmentationPolygon-Koordinaten nach der Class ID
Keypoints[x, y, visibility, ...] in Pixeln[x, y, visibility, ...] normalisiert

Kurzanleitung#

Der schnellste Weg, um COCO-Annotationen zu konvertieren und mit dem Training zu beginnen:

from ultralytics.data.converter import convert_coco

convert_coco(
    labels_dir="my_dataset/annotations/",  # directory containing your JSON files
    save_dir="my_dataset/converted/",  # where to save converted labels
    cls91to80=False,  # set False for custom datasets (see warning below)
)

Organisiere nach der Konvertierung deine Verzeichnisstruktur, erstelle eine dataset.yaml und starte das Training. Siehe die vollständige Schritt-für-Schritt-Anleitung unten.

Benutzerdefinierte Datensätze: Verwende immer `cls91to80=False`

Der Standardwert von cls91to80=True ist nur für das Standard-COCO-Datensatz mit 80 Objektklassen konzipiert, das 91 nicht zusammenhängende Kategorie-IDs auf 80 zusammenhängende Klassen-IDs abbildet. Für jeden benutzerdefinierten Datensatz musst du cls91to80=False festlegen — andernfalls werden deine Klassen-IDs im Stillen falsch zugeordnet und dein Modell lernt falsche Klassen.

Schritt-für-Schritt-Konvertierungsanleitung#

1. Bereite deinen COCO-Datensatz vor#

Ein typischer COCO-formatierter Datensatz, der aus Annotationstools exportiert wurde, hat die folgende Struktur:

my_dataset/
├── images/
│   ├── train/
│   │   ├── img_001.jpg
│   │   ├── img_002.jpg
│   │   └── ...
│   └── val/
│       ├── img_100.jpg
│       └── ...
└── annotations/
    ├── instances_train.json
    └── instances_val.json

Jede JSON-Datei folgt der Spezifikation des COCO-Datenformats mit drei erforderlichen Feldern — images, annotations und categories:

{
    "images": [{ "id": 1, "file_name": "img_001.jpg", "width": 640, "height": 480 }],
    "annotations": [
        {
            "id": 1,
            "image_id": 1,
            "category_id": 1,
            "bbox": [100, 50, 200, 150],
            "area": 30000,
            "iscrowd": 0
        }
    ],
    "categories": [
        { "id": 1, "name": "helmet" },
        { "id": 2, "name": "vest" }
    ]
}

2. Konvertiere Annotationen#

Verwende die Funktion convert_coco(), um deine COCO JSON-Annotationen in das YOLO-Format .txt zu konvertieren:

COCO in YOLO-Format konvertieren
from ultralytics.data.converter import convert_coco

convert_coco(
    labels_dir="my_dataset/annotations/",
    save_dir="my_dataset/converted/",
    cls91to80=False,
)

convert_coco() schreibt eine .txt-Datei pro annotiertes Bild in ein Unterverzeichnis labels/, das nach jeder JSON-Datei benannt ist, wobei das Präfix instances_ entfernt wird (so erzeugt instances_train.json labels/train/). Bilder ohne Annotationen werden übersprungen und erhalten keine Label-Datei, sodass der Baum von labels/ möglicherweise nicht jedes Bild widerspiegelt:

my_dataset/converted/
└── labels/
    ├── train/   # from instances_train.json
    │   ├── img_001.txt
    │   └── ...
    └── val/     # from instances_val.json
        └── ...
Ein erneuter Durchlauf erstellt einen neuen Ausgabeordner

convert_coco() überschreibt niemals ein vorhandenes save_dir: Wenn my_dataset/converted/ bereits existiert, schreibt ein erneuter Durchlauf stattdessen in my_dataset/converted-2/. Lösche die vorherige Ausgabe (oder ändere save_dir), bevor du den Vorgang erneut ausführst, da sonst die nächsten Schritte veraltete Labels einlesen.

3. Verzeichnisstruktur organisieren#

Nach der Konvertierung müssen Label-Dateien neben deinen Bildern abgelegt werden. YOLO erwartet ein Verzeichnis labels/, das das Verzeichnis images/ widerspiegelt:

import shutil
from pathlib import Path

converted_dir = Path("my_dataset/converted/labels")
dataset_dir = Path("my_dataset")

# convert_coco names each subdirectory after its JSON file (minus the "instances_" prefix),
# so iterate the actual subdirectories instead of assuming "train"/"val".
for src in converted_dir.iterdir():
    if not src.is_dir():
        continue
    dst = dataset_dir / "labels" / src.name
    dst.mkdir(parents=True, exist_ok=True)
    for f in src.glob("*.txt"):
        shutil.move(str(f), str(dst / f.name))

Deine finale Datensatzstruktur sollte wie folgt aussehen:

my_dataset/
├── images/
│   ├── train/
│   │   ├── img_001.jpg
│   │   └── ...
│   └── val/
│       └── ...
├── labels/
│   ├── train/
│   │   ├── img_001.txt
│   │   └── ...
│   └── val/
│       └── ...
└── dataset.yaml

4. Erstelle dataset.yaml#

Erstelle eine Konfigurationsdatei dataset.yaml, die deine COCO-Kategorien auf YOLO-Klassennamen abbildet. Diese Datei teilt YOLO mit, wo sich deine Daten befinden und welche Klassen erkannt werden sollen:

import json
from pathlib import Path

import yaml

# Read categories from your COCO JSON
with open("my_dataset/annotations/instances_train.json") as f:
    coco = json.load(f)

# Build class names matching convert_coco output (category_id - 1)
categories = sorted(coco["categories"], key=lambda x: x["id"])
names = {cat["id"] - 1: cat["name"] for cat in categories}
# NOTE: convert_coco maps class IDs as category_id - 1, so category_id must
# start from 1. If your categories start from 0, add 1 to each ID first.

# Create dataset.yaml
dataset = {
    "path": str(Path("my_dataset").resolve()),
    "train": "images/train",
    "val": "images/val",
    "names": names,
}

with open("my_dataset/dataset.yaml", "w") as f:
    yaml.dump(dataset, f, default_flow_style=False)

Die resultierende YAML-Datei:

path: /absolute/path/to/my_dataset
train: images/train
val: images/val
names:
    0: helmet
    1: vest

Weitere Details zum Dataset-YAML-Format findest du im Leitfaden zur Datensatzkonfiguration.

5. Trainiere dein YOLO-Modell#

Sobald dein konvertierter Datensatz bereit ist, trainiere ein YOLO-Modell:

Auf konvertierten COCO-Daten trainieren
from ultralytics import YOLO

model = YOLO("yolo26n.pt")  # load a pretrained model
results = model.train(data="my_dataset/dataset.yaml", epochs=100, imgsz=640)

Tipps zum Training und Best Practices findest du im Modelltraining-Leitfaden.

6. Überprüfe deine Konvertierung#

Überprüfe vor dem Training stichprobenartig einige Label-Dateien, um sicherzustellen, dass Class IDs und Koordinaten korrekt sind:

from pathlib import Path

label_file = Path("my_dataset/labels/train/img_001.txt")
for line in label_file.read_text().strip().splitlines():
    parts = line.split()
    cls_id = int(parts[0])
    coords = [float(v) for v in parts[1:5]]
    assert cls_id >= 0, f"Negative class ID {cls_id} — category_id in your JSON may start from 0"
    assert all(0 <= v <= 1 for v in coords), f"Coordinates out of [0, 1] range: {coords}"
Tipp

Wenn du negative Klassen-IDs siehst, verwendet dein COCO JSON wahrscheinlich category_id beginnend bei 0. Addiere 1 zu allen category_id-Werten in deinem JSON, bevor du convert_coco() ausführst, da es Klassen-IDs als category_id - 1 abbildet.

Häufige Probleme beheben#

Falsche Class IDs nach der Konvertierung#

Wenn dein Modell trainiert, aber falsche Objektklassen erkennt, verwendest du wahrscheinlich cls91to80=True (Standard) für einen benutzerdefinierten Datensatz. Dies bildet deine category_id-Werte über die COCO-91-zu-80-Nachschlagetabelle ab, was nur für den Standard-COCO-Datensatz korrekt ist.

Lösung: Verwende für benutzerdefinierte Datensätze immer cls91to80=False.

Keine Labels während des Trainings gefunden#

Wenn das Training WARNING: No labels found oder 0 images, N backgrounds anzeigt, befinden sich deine Label-Dateien nicht im erwarteten Verzeichnis. convert_coco() speichert Labels in einem separaten Ausgabeverzeichnis (z. B. save_dir/labels/train/), aber YOLO erwartet labels/ parallel zu images/ in deinem Datensatzverzeichnis.

Lösung: Verschiebe die Label-Dateien so, dass sie der erwarteten Verzeichnisstruktur entsprechen. Stelle sicher, dass labels/train/ ein Geschwisterverzeichnis von images/train/ ist.

KeyError während der Konvertierung#

Wenn du beim Ausführen von convert_coco() den Fehler KeyError: 'bbox' oder ähnliche Fehler erhältst, enthält dein labels_dir wahrscheinlich JSON-Dateien, die keine Instanzen sind (z. B. captions_train2017.json), welche eine andere Annotationsstruktur aufweisen.

Lösung: Platziere nur Instanz-Annotations-JSON-Dateien (z. B. instances_train2017.json) in labels_dir.

Leere Label-Dateien nach der Konvertierung#

Wenn die Konvertierung abgeschlossen ist, aber die .txt-Dateien leer oder fehlen, haben alle Annotationen möglicherweise iscrowd: 1 (häufig bei von SAM generierten Masken) oder Bounding Boxes haben die Breite oder Höhe Null.

Solution: Überprüfe deine JSON-Annotationen auf iscrowd-Werte. Wenn du SAM-Masken verwendest, bereite das JSON vor, um iscrowd: 0 einzustellen.

Kasten-förmige Polygone aus Maskenannotationen#

Wenn use_segments=True den Eintrag annotations without a usable polygon protokolliert, enthalten einige Annotationen keinen segmentation-Wert oder einen Wert, der keine Liste aus mindestens drei Koordinatenpaaren ist. Die üblichen Ursachen sind Exporte, die nur Erkennungen enthalten und das Feld leer oder fehlend lassen, sowie COCO Run-Length Encoding ({"counts": ..., "size": ...}), das von Bitmasken-Exporteuren wie SAM geschrieben wird; eine flache Koordinatenliste ohne umschließende Polygonliste, Ein- und Zweipunkt-Umrisse und andere fehlerhafte Werte werden auf dieselbe Weise behandelt. Eine Annotation behält die übrig gebliebenen Polygone bei und greift auf eine Segmentzeile zurück, die wie ihre Bounding Box geformt ist, wenn keine übrig bleiben, sodass die Labels gültig bleiben, diese Zeilen jedoch keine Maskendetails enthalten.

Lösung: Exportiere die Annotationen mit Polygon-Segmentierungen erneut, decodiere die RLE-Masken vor dem Ausführen von convert_coco() in Polygone oder korrigiere fehlerhafte segmentation-Werte.

Lücken in den Class IDs in konvertierten Labels#

Wenn Klassen-IDs in Label-Dateien nicht zusammenhängend sind (z. B. 0, 4, 9 anstelle von 0, 1, 2), verwendet dein Annotationstool nicht zusammenhängende category_id-Werte.

Lösung: Überprüfe, ob die Klassen-IDs in deinen .txt-Dateien mit dem names-Wörterbuch in dataset.yaml übereinstimmen. Ordne IDs bei Bedarf wieder zusammenhängenden Werten zu.

Vollständige API-Details und Parameterbeschreibungen findest du in der convert_coco-API-Referenz.

FAQ#

  • Verwende die Funktion convert_coco() von Ultralytics, um COCO JSON-Annotationen in das YOLO-Format .txt zu konvertieren. Setze cls91to80=False für benutzerdefinierte Datensätze:

    from ultralytics.data.converter import convert_coco
    
    convert_coco(labels_dir="path/to/annotations/", save_dir="output/", cls91to80=False)

    Organisiere deine Label-Dateien nach der Konvertierung so neu, dass labels/ das Verzeichnis images/ widerspiegelt, und erstelle dann eine dataset.yaml-Datei. Siehe die Schritt-für-Schritt-Anleitung für den vollständigen Arbeitsablauf.

  • Dies geschieht, weil convert_coco() Labels in einem Unterverzeichnis innerhalb von save_dir/labels/ (z. B. save_dir/labels/train/) speichert, anstatt direkt im labels/train/ deines Datensatzes neben images/train/. YOLO erwartet, dass Labels parallel zu Bildern liegen – zum Beispiel benötigt images/train/img.jpg labels/train/img.txt. Verschiebe deine konvertierten Labels so, dass sie dieser Struktur entsprechen. Siehe Beheben der Verzeichnisstruktur.

  • Der Parameter cls91to80 steuert, wie COCO-category_id-Werte auf YOLO-Klassen-IDs abgebildet werden. Wenn True (Standard) eingestellt ist, wird die Nachschlagetabelle coco91_to_coco80_class() angewendet, die für den Standard-COCO-Datensatz entwickelt wurde, welcher 80 Klassen mit nicht zusammenhängenden IDs (1-90) aufweist. Setze für benutzerdefinierte Datensätze immer cls91to80=False – dies subtrahiert einfach 1 von jedem category_id, um bei null beginnende Klassen-IDs zu erstellen.

  • Nicht mit der aktuellen YOLO-Trainings-Pipeline – Annotationen müssen im YOLO-Format .txt mit einer Datei pro Bild vorliegen. Verwende convert_coco(), um dein COCO JSON zuerst zu konvertieren, und folge dann diesem Leitfaden zum Organisieren und Trainieren. Weitere Informationen zu unterstützten Formaten findest du unter Datensatzformate.

  • Ja, verwende use_segments=True beim Aufrufen von convert_coco(), um Polygon-Segmentierungsmasken in die konvertierten YOLO-Labels einzubeziehen. Dies erzeugt Label-Dateien, die mit YOLO-Segmentierungsmodellen kompatibel sind:

    from ultralytics.data.converter import convert_coco
    
    convert_coco(labels_dir="annotations/", save_dir="output/", use_segments=True, cls91to80=False)
  • Verwende use_keypoints=True, um COCO-Keypoint-Annotationen für das Training zur Posenschätzung zu konvertieren:

    from ultralytics.data.converter import convert_coco
    
    convert_coco(labels_dir="annotations/", save_dir="output/", use_keypoints=True, cls91to80=False)

    Beachte, dass wenn sowohl use_segments als auch use_keypoints auf True gesetzt sind, nur Schlüsselpunkte in die Label-Dateien geschrieben werden – Segmente werden stillschweigend ignoriert.

Kommentare