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 sectionCOCO에서 YOLO로 변환해야 하는 이유는 무엇인가요?#
COCO JSON 형식은 모든 주석을 단일 파일에 저장하는 반면, YOLO는 정규화된 좌표를 사용하여 이미지당 하나의 텍스트 파일을 사용합니다. 변환이 필요한 이유는 다음과 같습니다:
- YOLO 모델은
.txt레이블 파일이 필요하며, 이미지당 하나의 파일에 정규화된 좌표로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 파일 | 이미지당 하나의 .txt 파일 |
| Bbox 형식 | 픽셀 단위의 [x_min, y_min, width, height] | 정규화된(0-1) class x_center y_center width height |
| 클래스 ID | category_id (어떤 숫자에서든 시작 가능) | 0부터 시작하는 인덱스 (0에서 시작) |
| 분할(Segmentation) | segmentation 필드의 다각형 배열 | 클래스 ID 뒤에 오는 다각형 좌표 |
| 키포인트(Keypoints) | 픽셀 단위의 [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 section1. COCO 데이터셋 준비#
어노테이션 도구에서 내보낸 일반적인 COCO 형식 데이터셋은 다음과 같은 구조를 가집니다:
my_dataset/
├── images/
│ ├── train/
│ │ ├── img_001.jpg
│ │ ├── img_002.jpg
│ │ └── ...
│ └── val/
│ ├── img_100.jpg
│ └── ...
└── annotations/
├── instances_train.json
└── instances_val.jsonEach JSON file follows the COCO data format specification with three required fields — images, annotations, and 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. 어노테이션 변환#
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()는 주석이 달린 이미지당 하나의 .txt 파일을 각 JSON 파일의 이름을 딴 labels/ 하위 디렉토리에 작성하며, instances_ 접두사는 제거됩니다(예: instances_train.json은 labels/train/을 생성). 주석이 없는 이미지는 건너뛰고 라벨 파일이 생성되지 않으므로, labels/ 트리가 모든 이미지와 일치하지 않을 수 있습니다:
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 section3. 디렉터리 구조 정리#
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 section4. dataset.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 section5. YOLO 모델 학습#
변환된 데이터셋이 준비되면 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 section6. 변환 확인#
학습 전에 몇 개의 레이블 파일을 검사하여 클래스 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(기본값)를 사용하고 있을 가능성이 큽니다. 이는 category_id 값을 COCO 91-to-80 조회 테이블을 통해 매핑하는데, 이는 표준 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 생성 마스크에서 흔함), 바운딩 박스의 너비나 높이가 0일 수 있습니다.
해결책: 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 sectionFAQ#
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 sectionCOCO 변환 후 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 학습 파이프라인으로는 불가능합니다. 어노테이션은 이미지당 하나의 파일인 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로 설정하면 키포인트만 레이블 파일에 기록되며 세그먼트는 무시된다는 점에 유의하십시오.