كيفية تحويل تسميات COCO إلى تنسيق YOLO
تدريب نماذج Ultralytics YOLO يتطلب تسميات بتنسيق YOLO، ولكن العديد من أدوات التسمية الشائعة تصدر البيانات بتنسيق COCO JSON بدلاً من ذلك. يوضح هذا الدليل كيفية تحويل تسميات COCO الخاصة بك إلى تنسيق YOLO وبدء تدريب اكتشاف الكائنات, تجزئة النماذج (instance segmentation)، و تقدير الوضع (pose estimation) المدربة جيداً.
لماذا نقوم بالتحويل من COCO إلى YOLO؟
يخزن تنسيق COCO JSON جميع التسميات في ملف واحد، بينما يستخدم YOLO ملف نصي واحد لكل صورة بإحداثيات طبيعية. التحويل ضروري للأسباب التالية:
- تتطلب نماذج YOLO ملفات
.txtتسميات تحتوي على ملف واحد لكل صورة، متضمنةclass x_center y_center width heightبإحداثيات طبيعية. - يستخدم COCO JSON تنسيق إحداثيات البكسل في
[x_min, y_min, width, height]مع ملف JSON واحد لجميع الصور. - تختلف معرفات الفئات (Class IDs) — يستخدم COCO قيم
category_idعشوائية، بينما يتطلب YOLO معرفات فئات تبدأ من الصفر.
| الميزة | COCO JSON | YOLO TXT |
|---|---|---|
| الهيكل | ملف JSON واحد لجميع الصور | ملف .txt واحد لكل صورة |
| تنسيق Bbox | [x_min, y_min, width, height] بالبكسل | class x_center y_center width height طبيعي (0-1) |
| معرفات الفئات | category_id (يمكن أن تبدأ من أي رقم) | تبدأ من الصفر (Zero-indexed) |
| التجزئة (Segmentation) | مصفوفات المضلعات في segmentation الحقل | إحداثيات المضلع بعد معرف الفئة |
| Keypoints | [x, y, visibility, ...] بالبكسل | [x, y, visibility, ...] طبيعية |
بداية سريعة
أسرع طريقة لتحويل تسميات 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 الإعداد الافتراضي مصمم فقط لمعيار مجموعة بيانات COCO الذي يحتوي على 80 فئة كائنات، والذي يربط 91 معرف فئة غير متسلسل بـ 80 معرف فئة متسلسل. لأي مجموعة بيانات مخصصة، يجب عليك تعيين بشكل إلزامي اضبط cls91to80=False — وإلا سيتم ربط معرفات الفئات الخاصة بك بشكل غير صحيح تلقائياً وسيتعلم نموذجك فئات خاطئة.
دليل التحويل خطوة بخطوة
1. تجهيز مجموعة بيانات COCO الخاصة بك
تحتوي مجموعة بيانات بتنسيق COCO نموذجية يتم تصديرها من أدوات التسمية على الهيكل التالي:
my_dataset/
├── images/
│ ├── train/
│ │ ├── img_001.jpg
│ │ ├── img_002.jpg
│ │ └── ...
│ └── val/
│ ├── img_100.jpg
│ └── ...
└── annotations/
├── instances_train.json
└── instances_val.jsonيتبع كل ملف JSON مواصفات تنسيق بيانات COCO مع ثلاثة حقول مطلوبة — images, annotations، و 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. تحويل التسميات
استخدم أمر 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,
)3. تنظيم هيكل الدليل
بعد التحويل، يجب وضع ملفات التسميات بجانب صورك. يتوقع YOLO وجود دليل labels/ يعكس دليل images/ الخاص بك:
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.yaml4. إنشاء dataset.yaml
إنشاء ملف dataset.yaml ملف تكوين يربط فئات COCO الخاصة بك بأسماء فئات YOLO. يخبر هذا الملف 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لمزيد من التفاصيل حول تنسيق dataset YAML، راجع دليل تكوين مجموعة البيانات.
5. تدريب نموذج 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)للحصول على نصائح التدريب وأفضل الممارسات، راجع دليل تدريب النماذج.
6. التحقق من عملية التحويل
قبل التدريب، تحقق من بعض ملفات التسميات للتأكد من صحة معرفات الفئات والإحداثيات:
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}"إذا رأيت معرفات فئات سالبة، فمن المحتمل أن ملف COCO JSON الخاص بك يستخدم category_id تبدأ من 0. أضف 1 إلى جميع قيم category_id في ملف JSON الخاص بك قبل تشغيل convert_coco()، حيث يقوم بتعيين معرفات الفئات كـ category_id - 1.
استكشاف المشكلات الشائعة وإصلاحها
معرفات فئات خاطئة بعد التحويل
إذا كان نموذجك يتدرب ولكنه يكتشف فئات كائنات خاطئة، فمن المحتمل أنك تستخدم cls91to80=True (افتراضي) على مجموعة بيانات مخصصة. هذا يربط قيم category_id الخاصة بك من خلال جدول البحث COCO 91-to-80، وهو صحيح فقط للمعايير مجموعة بيانات COCO.
الحل: استخدم دائماً cls91to80=False لمجموعات البيانات المخصصة.
لم يتم العثور على تسميات أثناء التدريب
إذا أظهر التدريب WARNING: No labels found أو 0 images, N backgrounds، فهذا يعني أن ملفات التسميات الخاصة بك ليست في الدليل المتوقع. convert_coco() يحفظ التسميات في دليل إخراج منفصل (على سبيل المثال، save_dir/labels/train/)، لكن YOLO يتوقع labels/ موازياً لـ images/ داخل دليل مجموعة البيانات الخاصة بك.
الحل: انقل ملفات التسميات لتطابق هيكل الدليل المتوقع. تأكد من labels/train/ هو شقيق لـ images/train/.
خطأ KeyError أثناء التحويل
إذا واجهت KeyError: 'bbox' أو أخطاء مشابهة عند تشغيل convert_coco()، فمن المحتمل أن يحتوي labels_dir الخاص بك على ملفات JSON لا تمثل حالات (مثلاً: captions_train2017.json) والتي تمتلك بنية توضيحية مختلفة.
الحل: ضع فقط ملفات JSON الخاصة بتوضيحات الحالات (مثلاً: instances_train2017.json) داخل labels_dir.
ملفات تصنيف فارغة بعد التحويل
إذا اكتمل التحويل ولكن ملفات .txt كانت فارغة أو مفقودة، فقد تكون جميع التوضيحات تمتلك iscrowd: 1 (أمر شائع مع الأقنعة الناتجة عن SAM)، أو أن صناديق التحديد (bounding boxes) تمتلك عرضاً أو ارتفاعاً يساوي صفراً.
الحل: افحص توضيحات JSON بحثاً عن قيم iscrowd. إذا كنت تستخدم أقنعة SAM، فقم بمعالجة JSON مسبقاً لتعيين iscrowd: 0.
فجوات في معرفات الفئات في الملصقات المحولة
إذا كانت معرفات الفئات في ملفات الملصقات غير متصلة (مثلاً: 0، 4، 9 بدلاً من 0، 1، 2)، فإن أداة التوضيح الخاصة بك تستخدم قيم category_id غير متصلة.
الحل: تحقق من أن معرفات الفئات في ملفات .txt الخاصة بك تطابق قاموس names في dataset.yaml. أعد تعيين المعرفات إلى قيم متصلة إذا لزم الأمر.
للحصول على تفاصيل API الكاملة وأوصاف المعلمات، راجع convert_coco مرجع API.
الأسئلة الشائعة
كيف يمكنني تحويل توضيحات COCO JSON إلى تنسيق YOLO؟
استخدم أمر convert_coco() دالة من Ultralytics لتحويل توضيحات 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. راجع الدليل التفصيلي لسير العمل الكامل.
لماذا يظهر تدريب YOLO رسالة "No labels found" بعد التحويل من COCO؟
يحدث هذا لأن convert_coco() يحفظ الملصقات في دليل فرعي داخل save_dir/labels/ (على سبيل المثال، save_dir/labels/train/) بدلاً من وضعها مباشرة في labels/train/ بجانب images/train/ الخاص بمجموعة بياناتك. يتوقع YOLO أن تكون الملصقات موازية للصور - على سبيل المثال، images/train/img.jpg يحتاج إلى labels/train/img.txt. انقل الملصقات المحولة لتطابق هذا الهيكل. راجع إصلاح هيكل الدليل.
ماذا يفعل cls91to80 في convert_coco()?
يمكن تهيئة الوسيط cls91to80 تتحكم المعلمة في كيفية تعيين قيم COCO category_id إلى معرفات فئات YOLO. عندما تكون True (الافتراضي)، فإنها تستخدم جدول بحث مصمماً لـ مجموعة بيانات COCO القياسي، والذي يحتوي على 80 فئة ذات معرفات غير متصلة (1-90). بالنسبة لـ مجموعات البيانات المخصصة، قم دائماً بتعيين cls91to80=False — هذا ببساطة يطرح 1 من كل category_id لإنشاء معرفات فئات تبدأ من الصفر.
هل يمكنني تدريب YOLO مباشرة على COCO JSON دون تحويل؟
ليس مع خط أنابيب تدريب YOLO الحالي — يجب أن تكون التوضيحات بتنسيق YOLO .txt مع ملف واحد لكل صورة. استخدم convert_coco() لتحويل COCO JSON أولاً، ثم اتبع هذا دليلنا للتنظيم والتدريب. للمزيد حول التنسيقات المدعومة، راجع تنسيقات مجموعات البيانات.
هل يمكنني تحويل توضيحات تجزئة COCO إلى تنسيق YOLO؟
نعم، استخدم use_segments=True عند استدعاء convert_coco() لتضمين أقنعة تجزئة المضلع في ملصقات YOLO المحولة. هذا ينتج ملفات ملصقات متوافقة مع نماذج تجزئة YOLO:
from ultralytics.data.converter import convert_coco
convert_coco(labels_dir="annotations/", save_dir="output/", use_segments=True, cls91to80=False)كيف يمكنني تحويل توضيحات النقاط الرئيسية لـ COCO إلى تنسيق YOLO؟
استخدم use_keypoints=True لتحويل توضيحات النقاط الرئيسية لـ COCO لتدريب تقدير الوضع (pose estimation):
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، فسيتم كتابة النقاط الرئيسية فقط في ملفات الملصقات — يتم تجاهل التجزئات بصمت.