Meet YOLO26: next-gen vision AI.

Link to this sectionSo konvertierst du COCO-Annotationen in das YOLO-Format#

Das Trainieren von Ultralytics YOLO-Modellen erfordert Annotationen im YOLO-Format, aber viele gängige Annotationstools 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 Objekterkennungs-, Instanzsegmentierungs- und Pose-Estimation-Modellen beginnst.

Möchtest du die Konvertierung überspringen?

Um direkt mit COCO JSON zu trainieren, ohne .txt-Dateien zu generieren, siehe Train YOLO on COCO JSON Without Conversion.

Link to this sectionWarum 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 erforderlich, weil:

  • YOLO-Modelle .txt-Label-Dateien benötigen, wobei eine Datei pro Bild verwendet wird, die class x_center y_center width height in normalisierten Koordinaten enthält.
  • COCO JSON Pixelkoordinaten verwendet im Format [x_min, y_min, width, height] mit einer einzigen JSON-Datei für alle Bilder.
  • Class IDs sich unterscheiden — COCO verwendet beliebige category_id-Werte, während YOLO nullbasierte Class 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 mit 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

Link to this sectionKurzanleitung#

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 den vollständigen Schritt-für-Schritt-Leitfaden unten.

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

Die Standardeinstellung cls91to80=True ist ausschließlich für den Standard-COCO-Datensatz mit 80 Objektklassen konzipiert, die 91 nicht zusammenhängende Kategorie-IDs auf 80 fortlaufende Class IDs abbildet. Für jeden benutzerdefinierten Datensatz musst du cls91to80=False setzen – andernfalls werden deine Class IDs im Hintergrund falsch zugeordnet und dein Modell lernt die falschen Klassen.

Link to this sectionSchritt-für-Schritt-Konvertierungsanleitung#

Link to this section1. 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" }
    ]
}

Link to this section2. Konvertiere Annotationen#

Verwende die Funktion convert_coco(), um deine COCO JSON-Annotationen in das YOLO .txt-Format 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 annotiertem Bild in ein labels/-Unterverzeichnis, das nach der jeweiligen JSON-Datei benannt ist, wobei das Präfix instances_ entfernt wird (daher erzeugt instances_train.json labels/train/). Bilder ohne Annotationen werden übersprungen und erhalten keine Label-Datei, daher spiegelt der labels/-Baum möglicherweise nicht jedes Bild wider:

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 bestehendes save_dir: Falls my_dataset/converted/ bereits existiert, schreibt ein erneuter Durchlauf stattdessen in my_dataset/converted-2/. Lösche die vorherige Ausgabe (oder ändere save_dir) vor dem erneuten Ausführen, da die nächsten Schritte sonst veraltete Labels einlesen.

Link to this section3. Verzeichnisstruktur organisieren#

Nach der Konvertierung müssen die Label-Dateien neben deinen Bildern platziert werden. YOLO erwartet ein labels/-Verzeichnis, das das images/-Verzeichnis 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 endgültige Datensatzstruktur sollte so aussehen:

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

Link to this section4. Erstelle dataset.yaml#

Erstelle eine dataset.yaml-Konfigurationsdatei, 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.

Link to this section5. 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 bewährte Verfahren findest du im Leitfaden zum Modelltraining.

Link to this section6. Ü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 Class IDs siehst, verwendet dein COCO JSON wahrscheinlich eine category_id, die bei 0 beginnt. Addiere 1 zu allen category_id-Werten in deinem JSON, bevor du convert_coco() ausführst, da es Class IDs als category_id - 1 zuordnet.

Link to this sectionHäufige Probleme beheben#

Link to this sectionFalsche Class IDs nach der Konvertierung#

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

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

Link to this sectionKeine Labels während des Trainings gefunden#

Wenn beim Training WARNING: No labels found oder 0 images, N backgrounds angezeigt wird, 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/ innerhalb deines Datensatzverzeichnisses.

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

Link to this sectionKeyError während der Konvertierung#

Wenn du einen KeyError: 'bbox' oder ähnliche Fehler erhältst, wenn du convert_coco() ausführst, enthält dein labels_dir wahrscheinlich JSON-Dateien ohne Instanzen (z. B. captions_train2017.json), die eine andere Annotationsstruktur haben.

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

Link to this sectionLeere Label-Dateien nach der Konvertierung#

Wenn die Konvertierung abgeschlossen ist, die .txt-Dateien aber leer oder nicht vorhanden sind, haben möglicherweise alle Annotationen iscrowd: 1 (üblich bei SAM-generierten Masken), oder die Bounding Boxes haben eine Breite oder Höhe von null.

Lösung: Überprüfe deine JSON-Annotationen auf iscrowd-Werte. Wenn du SAM-Masken verwendest, bereite das JSON so vor, dass iscrowd: 0 gesetzt ist.

Link to this sectionLücken in den Class IDs in konvertierten Labels#

Wenn die Class IDs in Label-Dateien nicht fortlaufend sind (z. B. 0, 4, 9 statt 0, 1, 2), verwendet dein Annotationstool nicht fortlaufende category_id-Werte.

Lösung: Überprüfe, ob die Class IDs in deinen .txt-Dateien mit dem names-Dictionary in dataset.yaml übereinstimmen. Weise IDs bei Bedarf fortlaufenden Werten zu.

Für vollständige API-Details und Parameterbeschreibungen siehe die convert_coco API-Referenz.

Link to this sectionFAQ#

Link to this sectionWie konvertiere ich COCO JSON-Annotationen in das YOLO-Format?#

Verwende die Funktion convert_coco() von Ultralytics, um COCO JSON-Annotationen in das YOLO .txt-Format 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 nach der Konvertierung deine Label-Dateien so, dass labels/ das images/-Verzeichnis widerspiegelt, und erstelle dann eine dataset.yaml-Datei. Siehe den Schritt-für-Schritt-Leitfaden für den vollständigen Workflow.

Link to this sectionWarum zeigt das YOLO-Training nach der COCO-Konvertierung "No labels found" an?#

Dies geschieht, weil convert_coco() Labels in einem Unterverzeichnis innerhalb von save_dir/labels/ speichert (z. B. save_dir/labels/train/), anstatt direkt in das labels/train/-Verzeichnis deines Datensatzes neben images/train/. YOLO erwartet, dass Labels parallel zu den Bildern liegen — zum Beispiel benötigt images/train/img.jpg ein labels/train/img.txt. Verschiebe deine konvertierten Labels, um dieser Struktur zu entsprechen. Siehe Anpassung der Verzeichnisstruktur.

Link to this sectionWas bewirkt cls91to80 in convert_coco()?#

Der Parameter cls91to80 steuert, wie COCO category_id-Werte auf YOLO-Klassen-IDs abgebildet werden. Wenn True (Standard), wird die Nachschlagetabelle coco91_to_coco80_class() angewendet, die für den Standard-COCO-Datensatz entwickelt wurde, welcher 80 Klassen mit nicht aufeinanderfolgenden IDs (1-90) enthält. Setze bei benutzerdefinierten Datensätzen immer cls91to80=False – dies subtrahiert einfach 1 von jeder category_id, um nullbasierte Klassen-IDs zu erstellen.

Link to this sectionKann ich YOLO direkt mit COCO JSON trainieren, ohne zu konvertieren?#

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

Link to this sectionKann ich COCO-Segmentierungs-Annotationen in das YOLO-Format konvertieren?#

Ja, verwende use_segments=True beim Aufruf von convert_coco(), um Polygon-Segmentierungsmasken in die konvertierten YOLO-Labels aufzunehmen. 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)

Link to this sectionWie konvertiere ich COCO-Keypoint-Annotationen in das YOLO-Format?#

Verwende use_keypoints=True, um COCO-Keypoint-Annotationen für das Training zur Pose Estimation 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 Keypoints in die Label-Dateien geschrieben werden — Segmente werden ignoriert.

Kommentare