COCO Anotasyonlarını YOLO Formatına Dönüştürme#
Ultralytics YOLO modellerini eğitmek için YOLO formatında anotasyonlar gerekir, ancak birçok popüler anotasyon aracı bunun yerine COCO JSON formatında dışa aktarım yapar. Bu kılavuz, COCO anotasyonlarını YOLO formatına nasıl dönüştüreceğini ve nesne algılama, örnek segmentasyonu ve poz tahmini modellerini eğitmeye nasıl başlayacağını gösterir.
.txt dosyaları oluşturmadan doğrudan COCO JSON üzerinde eğitim yapmak için Dönüştürme Olmadan COCO JSON Üzerinde YOLO Eğitimi bölümüne bak.
COCO'dan YOLO'ya Neden Dönüştürme Yapılır?#
COCO JSON formatı tüm anotasyonları tek bir dosyada saklarken YOLO, her görüntü için normalize edilmiş koordinatlara sahip bir metin dosyası kullanır. Dönüştürme şu nedenlerle gereklidir:
- YOLO modelleri
.txtetiket dosyaları gerektirir; her görüntü için bir dosyada, normalize edilmiş koordinatlardaclass x_center y_center width heightbulunur. - COCO JSON piksel koordinatlarını kullanır; tüm görüntüler için tek bir JSON dosyasıyla
[x_min, y_min, width, height]formatındadır. - Sınıf kimlikleri farklıdır — COCO rastgele
category_iddeğerleri kullanırken YOLO, sıfır tabanlı sınıf kimlikleri gerektirir.
| Özellik | COCO JSON | YOLO TXT |
|---|---|---|
| Yapı | Tüm görüntüler için tek JSON dosyası | Görüntü başına bir .txt dosyası |
| BBox formatı | Piksel cinsinden [x_min, y_min, width, height] | Normalize edilmiş class x_center y_center width height (0-1) |
| Sınıf kimlikleri | category_id (herhangi bir sayıdan başlayabilir) | Sıfır tabanlı (0'dan başlar) |
| Segmentasyon | segmentation alanındaki çokgen dizileri | Sınıf kimliğinden sonra çokgen koordinatları |
| Anahtar noktalar | Piksel cinsinden [x, y, visibility, ...] | Normalize edilmiş [x, y, visibility, ...] |
Hızlı Başlangıç#
COCO anotasyonlarını dönüştürüp eğitime başlamanın en hızlı yolu:
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)
)Dönüştürmeden sonra dizin yapını düzenle, bir dataset.yaml dosyası oluştur ve eğitime başla. Aşağıdaki tam adım adım kılavuza bak.
cls91to80=True varsayılanı, yalnızca 80 nesne sınıfına sahip standart COCO veri kümesi için tasarlanmıştır; 91 bitişik olmayan kategori kimliğini 80 bitişik sınıf kimliğine eşler. Herhangi bir özel veri kümesi için cls91to80=False değerini mutlaka ayarlamalısın — aksi takdirde sınıf kimliklerin sessizce yanlış eşlenir ve modelin yanlış sınıfları öğrenir.
Adım Adım Dönüştürme Kılavuzu#
1. COCO Veri Kümeni Hazırla#
Anotasyon araçlarından dışa aktarılan tipik bir COCO formatlı veri kümesi aşağıdaki yapıya sahiptir:
my_dataset/
├── images/
│ ├── train/
│ │ ├── img_001.jpg
│ │ ├── img_002.jpg
│ │ └── ...
│ └── val/
│ ├── img_100.jpg
│ └── ...
└── annotations/
├── instances_train.json
└── instances_val.jsonHer JSON dosyası, üç gerekli alan içeren COCO veri formatı belirtimini izler — images, annotations ve 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. Anotasyonları Dönüştür#
COCO JSON anotasyonlarını YOLO .txt formatına dönüştürmek için convert_coco() işlevini kullan:
from ultralytics.data.converter import convert_coco
convert_coco(
labels_dir="my_dataset/annotations/",
save_dir="my_dataset/converted/",
cls91to80=False,
)convert_coco(), her anotasyonlu görüntü için bir .txt dosyasını, her JSON dosyasının adını taşıyan labels/ alt dizinine yazar; instances_ öneki kaldırılır (böylece instances_train.json, labels/train/ oluşturur). Anotasyonu olmayan görüntüler atlanır ve etiket dosyası almaz; bu nedenle labels/ ağacı her görüntüyü yansıtmayabilir:
my_dataset/converted/
├── images/ # created but left empty
└── labels/
├── train/ # from instances_train.json
│ ├── img_001.txt
│ └── ...
└── val/ # from instances_val.json
└── ...convert_coco(), mevcut bir save_dir dosyasının üzerine asla yazmaz: my_dataset/converted/ zaten varsa yeniden çalıştırma bunun yerine my_dataset/converted-2/ konumuna yazar. Yeniden çalıştırmadan önce önceki çıktıyı sil veya save_dir değerini değiştir; aksi takdirde sonraki adımlar güncel olmayan etiketleri okur.
3. Dizin Yapısını Düzenle#
Dönüştürmeden sonra etiket dosyalarının görüntülerinin yanına yerleştirilmesi gerekir. YOLO, images/ dizinini yansıtan bir labels/ dizini bekler:
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))Son veri kümesi yapın şu şekilde görünmelidir:
my_dataset/
├── images/
│ ├── train/
│ │ ├── img_001.jpg
│ │ └── ...
│ └── val/
│ └── ...
├── labels/
│ ├── train/
│ │ ├── img_001.txt
│ │ └── ...
│ └── val/
│ └── ...
└── dataset.yaml4. dataset.yaml Dosyası Oluştur#
COCO kategorilerini YOLO sınıf adlarına eşleyen bir dataset.yaml yapılandırma dosyası oluştur. Bu dosya YOLO'ya verilerinin nerede olduğunu ve hangi sınıfları algılayacağını bildirir:
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)Ortaya çıkan YAML dosyası:
path: /absolute/path/to/my_dataset
train: images/train
val: images/val
names:
0: helmet
1: vestVeri kümesi YAML formatı hakkında daha fazla ayrıntı için veri kümesi yapılandırma kılavuzuna bak.
5. YOLO Modelini Eğit#
Dönüştürülmüş veri kümen hazır olduğunda bir YOLO modelini eğit:
from ultralytics import YOLO
model = YOLO("yolo26n.pt") # load a pretrained model
results = model.train(data="my_dataset/dataset.yaml", epochs=100, imgsz=640)Eğitim ipuçları ve en iyi uygulamalar için model eğitimi kılavuzuna bak.
6. Dönüştürmeni Doğrula#
Eğitimden önce, sınıf kimliklerinin ve koordinatların doğru olduğunu doğrulamak için birkaç etiket dosyasını rastgele kontrol et:
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}"Negatif sınıf kimlikleri görüyorsan COCO JSON dosyan muhtemelen 0'dan başlayan category_id değerlerini kullanıyordur. convert_coco() komutunu çalıştırmadan önce JSON dosyandaki tüm category_id değerlerine 1 ekle; çünkü bu komut sınıf kimliklerini category_id - 1 olarak eşler.
Yaygın Sorunları Giderme#
Dönüştürme Sonrası Yanlış Sınıf Kimlikleri#
Modelin eğitiliyor ancak yanlış nesne sınıflarını algılıyorsa özel bir veri kümesinde muhtemelen cls91to80=True (varsayılan) kullanıyorsun. Bu, category_id değerlerini yalnızca standart COCO veri kümesi için doğru olan COCO 91'den 80'e arama tablosu üzerinden eşler. COCO-80 karşılığı olmayan bir category_id, hiçbir şeye eşlenmez ve yanlış etiketler üretmek yerine dönüştürme sırasında TypeError: must be real number, not NoneType hatası verir.
Çözüm: Özel veri kümeleri için her zaman cls91to80=False kullan.
Eğitim Sırasında Etiket Bulunamadı#
Etiket taraması 0 images, N backgrounds bildiriyor ve eğitim ardından ValueError: train: No labels found in .../labels/train.cache ile duruyorsa etiket dosyaların beklenen dizinde değildir. convert_coco(), etiketleri ayrı bir çıktı dizinine (ör. save_dir/labels/train/) kaydeder, ancak YOLO veri kümesi dizinin içinde images/ dizinine paralel bir labels/ bekler.
Çözüm: Etiket dosyalarını beklenen dizin yapısına uyacak şekilde taşı. labels/train/ dizininin images/train/ diziniyle aynı seviyede olduğundan emin ol.
Dönüştürme Sırasında KeyError#
convert_coco() çalıştırılırken KeyError: 'bbox' veya benzeri hatalar alıyorsan labels_dir muhtemelen farklı bir anotasyon yapısına sahip örnek dışı JSON dosyaları (ör. captions_train2017.json) içeriyordur.
Çözüm: labels_dir içine yalnızca örnek anotasyonu JSON dosyaları (ör. instances_train2017.json) yerleştir.
Dönüştürme Sonrası Boş Etiket Dosyaları#
Dönüştürme tamamlandığında .txt dosyaları boş veya eksikse tüm anotasyonlarda iscrowd: 1 bulunuyor olabilir (SAM tarafından oluşturulan maskelerde yaygındır) ya da sınırlayıcı kutuların genişliği veya yüksekliği sıfırdır. use_keypoints=True ile yalnızca algılama içeren bir dışa aktarım üzerinde çalıştırmak da aynı sonucu verir; çünkü keypoints alanı olmayan anotasyonlar tamamen atlanır.
Çözüm: JSON anotasyonlarında iscrowd değerlerini incele. SAM maskeleri kullanıyorsan iscrowd: 0 değerini ayarlamak için JSON dosyasını önceden işle. use_keypoints=True ilettiysen anotasyonlarında gerçekten keypoints bulunduğunu doğrula.
Maske Anotasyonlarından Kutu Biçimli Çokgenler#
use_segments=True, annotations without a usable polygon günlüğünü kaydediyorsa bazı anotasyonlarda segmentation değeri yoktur veya bu değer en az üç koordinat çifti içeren bir liste değildir. Bunun yaygın nedenleri, alanı eksik veya boş bırakan yalnızca algılama içeren dışa aktarımlar ile SAM gibi bit maskesi dışa aktarıcılarının yazdığı COCO çalışma uzunluğu kodlamasıdır ({"counts": ..., "size": ...}); çevreleyen çokgen listesi olmayan düz koordinat listeleri, bir ve iki noktalı ana hatlar ve diğer hatalı biçimlendirilmiş değerler de aynı şekilde işlenir. Bir anotasyon, geriye kalan çokgenleri korur ve hiçbiri kalmadığında sınırlayıcı kutusu şeklinde bir segment satırına geri döner; böylece etiketler geçerli kalır, ancak bu satırlarda maske ayrıntısı bulunmaz.
Çözüm: Anotasyonları çokgen segmentasyonlarıyla yeniden dışa aktar, convert_coco() komutunu çalıştırmadan önce RLE maskelerini çokgenlere dönüştür veya hatalı segmentation değerlerini düzelt.
Dönüştürülen Etiketlerde Sınıf Kimliği Boşlukları#
Etiket dosyalarındaki sınıf kimlikleri bitişik değilse (ör. 0, 1, 2 yerine 0, 4, 9), anotasyon aracın bitişik olmayan category_id değerleri kullanıyordur.
Çözüm: .txt dosyalarındaki sınıf kimliklerinin dataset.yaml içindeki names sözlüğüyle eşleştiğini doğrula. Gerekirse kimlikleri bitişik değerlere yeniden eşle.
Tam API ayrıntıları ve parametre açıklamaları için convert_coco API referansına bak.
SSS#
COCO JSON anotasyonlarını YOLO
.txtformatına dönüştürmek için Ultralytics'tekiconvert_coco()işlevini kullan. Özel veri kümeleri içincls91to80=Falsedeğerini ayarla:from ultralytics.data.converter import convert_coco convert_coco(labels_dir="path/to/annotations/", save_dir="output/", cls91to80=False)Dönüştürmeden sonra etiket dosyalarını
labels/,images/dizinini yansıtacak şekilde yeniden düzenle ve ardından birdataset.yamldosyası oluştur. İş akışının tamamı için adım adım kılavuza bak.Bunun nedeni
convert_coco()etiketlerisave_dir/labels/içinde bir alt dizine (ör.save_dir/labels/train/) kaydederken bunları veri kümeninlabels/train/dizinine,images/train/dizininin yanına doğrudan kaydetmemesidir. YOLO, etiketlerin görüntülere paralel olmasını bekler — örneğinimages/train/img.jpgiçinlabels/train/img.txtgerekir. Dönüştürülen etiketlerini bu yapıya uyacak şekilde taşı. Dizin yapısını düzeltme bölümüne bak.cls91to80parametresi, COCOcategory_iddeğerlerinin YOLO sınıf kimliklerine nasıl eşleneceğini denetler.True(varsayılan) olduğunda standart COCO veri kümesi için tasarlanmışcoco91_to_coco80_class()arama tablosunu uygular; bu veri kümesinde bitişik olmayan kimliklere (1-90) sahip 80 sınıf bulunur. Özel veri kümeleri için her zamancls91to80=Falsedeğerini ayarla — bu işlem, sıfır tabanlı sınıf kimlikleri oluşturmak için hercategory_iddeğerinden yalnızca 1 çıkarır.Özel kod olmadan yapamazsın. Varsayılan eğitim işlem hattı, her görüntü için bir dosya olacak şekilde YOLO
.txtetiketlerini bekler; bu nedenle yaconvert_coco()komutunu çalıştırıp bu adım adım kılavuzu izle ya da COCO JSON dosyasını anında ayrıştırmak için veri kümesi sınıfını alt sınıflandır — Dönüştürme Olmadan COCO JSON Üzerinde YOLO Eğitimi bölümüne bak. Desteklenen formatlar hakkında daha fazla bilgi için veri kümesi formatlarına bak.Evet, dönüştürülen YOLO etiketlerine çokgen segmentasyon maskelerini eklemek için
convert_coco()çağrılırkenuse_segments=Truekullan. Bu işlem YOLO segmentasyon modelleri ile uyumlu etiket dosyaları oluşturur:from ultralytics.data.converter import convert_coco convert_coco(labels_dir="annotations/", save_dir="output/", use_segments=True, cls91to80=False)Poz tahmini eğitimi için COCO anahtar noktası anotasyonlarını dönüştürmek üzere
use_keypoints=Truekullan:from ultralytics.data.converter import convert_coco convert_coco(labels_dir="annotations/", save_dir="output/", use_keypoints=True, cls91to80=False)Hem
use_segmentshem deuse_keypointsTrueolarak ayarlanırsa etiket dosyalarına yalnızca anahtar noktaların yazılacağını unutma — segmentler sessizce yok sayılır.