Link to this sectionCOCO 어노테이션을 YOLO 형식으로 변환하는 방법#
Ultralytics YOLO 모델을 학습하려면 YOLO 형식의 어노테이션이 필요하지만, 많은 인기 어노테이션 도구는 대신 COCO JSON 형식으로 내보냅니다. 이 가이드에서는 COCO 어노테이션을 YOLO 형식으로 변환하고 객체 탐지, 인스턴스 세그멘테이션 및 포즈 추정 모델 학습을 시작하는 방법을 보여줍니다.
Link to this section왜 COCO에서 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] (픽셀 단위) | class x_center y_center width height (정규화된 0-1) |
| 클래스 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="path/to/annotations/", # directory containing your JSON files
save_dir="path/to/output/", # where to save converted labels
cls91to80=False, # IMPORTANT: set False for custom datasets
)변환 후, 디렉터리 구조를 정리하고, 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.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 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,
)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
# Paths
converted_dir = Path("my_dataset/converted/labels")
dataset_dir = Path("my_dataset")
# Move labels next to images for each split
for split in ["train", "val"]:
src = converted_dir / split # convert_coco strips "instances_" prefix from JSON filename
dst = dataset_dir / "labels" / split
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(기본값)를 사용하고 있을 가능성이 높습니다. 이는 category_id 값을 표준 COCO 데이터셋 전용인 COCO 91-to-80 조회 테이블을 통해 매핑합니다.
해결책: 커스텀 데이터셋에는 항상 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()?#
cls91to80 매개변수는 COCO category_id 값이 YOLO 클래스 ID로 매핑되는 방식을 제어합니다. True(기본값)로 설정하면 비연속적인 ID(1-90)를 가진 80개 클래스의 표준 COCO 데이터셋 전용 조회 테이블을 사용합니다. 커스텀 데이터셋의 경우 항상 cls91to80=False로 설정하세요. 이는 각 category_id에서 1을 빼서 0부터 시작하는 인덱스 클래스 ID를 만드는 작업입니다.
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 use_keypoints=True to convert COCO keypoint annotations for pose estimation training:
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로 설정하면 키포인트만 레이블 파일에 기록되며 세그먼트는 무시되니 주의하세요.