Link to this sectionCOCOアノテーションをYOLOフォーマットに変換する方法#
Ultralytics YOLOモデルのトレーニングにはYOLOフォーマットのアノテーションが必要ですが、多くの一般的なアノテーションツールはCOCO JSONフォーマットでエクスポートされます。このガイドでは、COCOアノテーションをYOLOフォーマットに変換し、物体検出、インスタンスセグメンテーション、および姿勢推定モデルのトレーニングを開始する方法を説明します。
.txtファイルを生成せずにCOCO JSONで直接学習を行う場合は、Train YOLO on COCO JSON Without Conversionを参照してください。
Link to this sectionなぜCOCOからYOLOに変換するのか?#
COCO JSON形式はすべての注釈を単一のファイルに保存しますが、YOLOは画像ごとに1つのテキストファイルを使用し、正規化された座標を用います。変換が必要な理由は以下の通りです。
- YOLOモデルは
.txtラベルファイルを必要とします。 これは画像1枚につき1ファイルで、正規化された座標でclass x_center y_center width heightを含みます。 - COCO JSONはピクセル座標を使用します。
[x_min, y_min, width, height]フォーマットで、全画像に対して単一のJSONファイルを使用します。 - クラスIDが異なります。 COCOは任意の
category_id値を使用しますが、YOLOは0から始まるクラスIDを必要とします。
| 機能 | COCO JSON | YOLO TXT |
|---|---|---|
| 構造 | 全画像に対して単一のJSONファイル | 画像1枚につき1つの.txtファイル |
| Bboxフォーマット | ピクセル単位の[x_min, y_min, width, height] | 正規化(0-1)されたclass x_center y_center width height |
| クラスID | category_id (任意の数値から開始可能) | 0から始まるインデックス(0から開始) |
| セグメンテーション | segmentationフィールド内のポリゴン配列 | クラスIDの後のポリゴン座標 |
| キーポイント | ピクセル単位の[x, y, visibility, ...] | 正規化された[x, y, visibility, ...] |
Link to this sectionクイックスタート#
COCOアノテーションを変換してトレーニングを開始する最速の方法:
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)
)変換後、ディレクトリ構造を整理し、dataset.yamlを作成し、トレーニングを開始します。詳細なステップバイステップガイドを以下に示します。
cls91to80=Trueのデフォルト設定は、80のオブジェクトクラスを持つ標準のCOCOデータセット専用に設計されており、連続していない91のカテゴリIDを80の連続したクラスIDにマッピングします。カスタムデータセットの場合、必ずcls91to80=Falseに設定してください。設定しない場合、クラスIDが誤ってマッピングされ、モデルが誤ったクラスを学習することになります。
Link to this sectionステップバイステップ変換ガイド#
Link to this sectionCOCOデータセットの準備#
アノテーションツールからエクスポートされた一般的なCOCOフォーマットのデータセットは、以下の構造になっています:
my_dataset/
├── images/
│ ├── train/
│ │ ├── img_001.jpg
│ │ ├── img_002.jpg
│ │ └── ...
│ └── val/
│ ├── img_100.jpg
│ └── ...
└── annotations/
├── instances_train.json
└── instances_val.json各JSONファイルは、COCO data formatの仕様に従い、images、annotations、categoriesという3つの必須フィールドを含みます。
{
"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 sectionアノテーションの変換#
convert_coco()関数を使用して、COCO JSONアノテーションをYOLOの.txtフォーマットに変換します:
from ultralytics.data.converter import convert_coco
convert_coco(
labels_dir="my_dataset/annotations/",
save_dir="my_dataset/converted/",
cls91to80=False,
)convert_coco() writes one .txt file per annotated image into a labels/ subdirectory named after each JSON file, with the instances_ prefix removed (so instances_train.json produces labels/train/). Images with no annotations are skipped and get no label file, so the labels/ tree may not mirror every image:
my_dataset/converted/
└── labels/
├── train/ # from instances_train.json
│ ├── img_001.txt
│ └── ...
└── val/ # from instances_val.json
└── ...convert_coco()は既存のsave_dirを上書きすることはありません。my_dataset/converted/が既に存在する場合、再実行するとmy_dataset/converted-2/に書き出されます。再実行前に以前の出力を削除するかsave_dirを変更しないと、後続のステップで古いラベルが読み込まれてしまいます。
Link to this sectionディレクトリ構造の整理#
After conversion, label files need to be placed alongside your images. YOLO expects a labels/ directory that mirrors the images/ directory:
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))最終的なデータセット構造は以下のようになります:
my_dataset/
├── images/
│ ├── train/
│ │ ├── img_001.jpg
│ │ └── ...
│ └── val/
│ └── ...
├── labels/
│ ├── train/
│ │ ├── img_001.txt
│ │ └── ...
│ └── val/
│ └── ...
└── dataset.yamlLink to this sectiondataset.yamlの作成#
COCOカテゴリをYOLOクラス名にマッピングするdataset.yaml設定ファイルを作成します。このファイルは、データがどこにあり、どのクラスを検出するかをYOLOに伝えます:
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)作成されたYAMLファイル:
path: /absolute/path/to/my_dataset
train: images/train
val: images/val
names:
0: helmet
1: vestデータセットYAMLフォーマットの詳細については、データセット設定ガイドを参照してください。
Link to this sectionYOLOモデルのトレーニング#
変換されたデータセットの準備ができたら、YOLOモデルをトレーニングします:
from ultralytics import YOLO
model = YOLO("yolo26n.pt") # load a pretrained model
results = model.train(data="my_dataset/dataset.yaml", epochs=100, imgsz=640)トレーニングのヒントとベストプラクティスについては、モデルトレーニングガイドを参照してください。
Link to this section変換の検証#
トレーニングの前に、いくつかのラベルファイルをチェックして、クラスIDと座標が正しいことを確認してください:
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}"If you see negative class IDs, your COCO JSON likely uses category_id starting from 0. Add 1 to all category_id values in your JSON before running convert_coco(), since it maps class IDs as category_id - 1.
Link to this section一般的な問題のトラブルシューティング#
Link to this section変換後のクラスIDの誤り#
モデルのトレーニングはできるが検出するオブジェクトクラスが間違っている場合、おそらくカスタムデータセットに対してデフォルトのcls91to80=Trueを使用しています。これはCOCOの91から80へのルックアップテーブルを通じてcategory_id値をマッピングしますが、これは標準のCOCOデータセットに対してのみ正しいものです。
解決策: カスタムデータセットには必ずcls91to80=Falseを使用してください。
Link to this sectionトレーニング中にラベルが見つからない#
If training shows WARNING: No labels found or 0 images, N backgrounds, your label files are not in the expected directory. convert_coco() saves labels to a separate output directory (e.g., save_dir/labels/train/), but YOLO expects labels/ parallel to images/ inside your dataset directory.
解決策: ラベルファイルを期待されるディレクトリ構造に合わせて移動してください。labels/train/がimages/train/と兄弟ディレクトリであることを確認してください。
Link to this section変換中のKeyError#
If you get KeyError: 'bbox' or similar errors when running convert_coco(), your labels_dir likely contains non-instance JSON files (e.g., captions_train2017.json) that have a different annotation structure.
解決策: インスタンスアノテーションのJSONファイル(例:instances_train2017.json)のみをlabels_dirに配置してください。
Link to this section変換後のラベルファイルが空#
変換は完了したが.txtファイルが空か存在しない場合、すべてのアノテーションがiscrowd: 1(SAMで生成されたマスクによく見られます)であるか、バウンディングボックスの幅や高さがゼロになっている可能性があります。
解決策: JSONアノテーションのiscrowd値を検査してください。SAMマスクを使用している場合は、JSONを前処理してiscrowd: 0に設定してください。
Link to this section変換されたラベル内のクラスIDの欠落#
ラベルファイル内のクラスIDが連続していない場合(例: 0, 1, 2ではなく0, 4, 9)、使用しているアノテーションツールが連続していないcategory_id値を使用しています。
Solution: Verify the class IDs in your .txt files match the names dictionary in dataset.yaml. Remap IDs to contiguous values if needed.
APIの詳細とパラメータの説明については、convert_coco APIリファレンスを参照してください。
Link to this sectionよくある質問 (FAQ)#
Link to this sectionCOCO JSONアノテーションをYOLOフォーマットに変換するにはどうすればよいですか?#
Ultralyticsのconvert_coco()関数を使用して、COCO JSONアノテーションをYOLOの.txtフォーマットに変換します。カスタムデータセットの場合はcls91to80=Falseに設定してください。
from ultralytics.data.converter import convert_coco
convert_coco(labels_dir="path/to/annotations/", save_dir="output/", cls91to80=False)変換後、labels/がimages/ディレクトリをミラーリングするようにラベルファイルを再編成し、dataset.yamlファイルを作成します。完全なワークフローについては、ステップバイステップガイドを参照してください。
Link to this sectionなぜCOCO変換後にYOLOのトレーニングで「No labels found」と表示されるのですか?#
This happens because convert_coco() saves labels to a subdirectory inside save_dir/labels/ (e.g., save_dir/labels/train/) rather than directly into your dataset's labels/train/ alongside images/train/. YOLO expects labels to sit parallel to images — for example, images/train/img.jpg needs labels/train/img.txt. Move your converted labels to match this structure. See fixing the directory structure.
Link to this sectionWhat does cls91to80 do in convert_coco()?#
The cls91to80 parameter controls how COCO category_id values are mapped to YOLO class IDs. When True (default), it applies the coco91_to_coco80_class() lookup table designed for the standard COCO dataset, which has 80 classes with non-contiguous IDs (1-90). For custom datasets, always set cls91to80=False — this simply subtracts 1 from each category_id to create zero-indexed class IDs.
Link to this section変換せずにCOCO JSONで直接YOLOをトレーニングできますか?#
現在のYOLOトレーニングパイプラインではできません。アノテーションは画像1枚につき1ファイルであるYOLOの.txtフォーマットである必要があります。最初にconvert_coco()を使用してCOCO JSONを変換し、このガイドに従って整理とトレーニングを行ってください。サポートされているフォーマットの詳細については、データセットフォーマットを参照してください。
Link to this sectionCOCOセグメンテーションアノテーションをYOLOフォーマットに変換できますか?#
Yes, use use_segments=True when calling convert_coco() to include polygon segmentation masks in the converted YOLO labels. This produces label files compatible with YOLO segmentation models:
from ultralytics.data.converter import convert_coco
convert_coco(labels_dir="annotations/", save_dir="output/", use_segments=True, cls91to80=False)Link to this sectionCOCOキーポイントアノテーションをYOLOフォーマットに変換するにはどうすればよいですか?#
use_keypoints=Trueを使用して、姿勢推定トレーニング用のCOCOキーポイントアノテーションを変換します。
from ultralytics.data.converter import convert_coco
convert_coco(labels_dir="annotations/", save_dir="output/", use_keypoints=True, cls91to80=False)use_segmentsとuse_keypointsの両方がTrueに設定されている場合、キーポイントのみがラベルファイルに書き込まれ、セグメントは無視されることに注意してください。