رؤية YOLO لعام 2026:

كيفية تحويل تعليقات COCO التوضيحية إلى تنسيق YOLO#

يتطلب تدريب نماذج Ultralytics YOLO توفير التعليقات التوضيحية بتنسيق YOLO، ولكن العديد من أدوات التعليق التوضيحي الشائعة تصدر البيانات بتنسيق COCO JSON بدلاً من ذلك. يوضح لك هذا الدليل كيفية تحويل تعليقات COCO التوضيحية إلى تنسيق YOLO وبدء تدريب نماذج اكتشاف الكائنات، وتجزئة المثيلات، وتقدير الوضعية.

هل تفضل تخطي عملية التحويل؟

للتدريب مباشرة على COCO JSON دون إنشاء ملفات .txt، راجع تدريب YOLO على COCO JSON بدون تحويل.

لماذا التحويل من COCO إلى YOLO؟#

يخزن تنسيق COCO JSON كافة التعليقات التوضيحية في ملف واحد، بينما يستخدم YOLO ملف نصي واحد لكل صورة بإحداثيات مسواة. يُعد التحويل ضررياً للأسباب التالية:

  • تتطلب نماذج YOLO ملفات تسميات .txt بحيث يحتوي كل ملف على صورة واحدة، وتتضمن class x_center y_center width height بإحداثيات مسواة.
  • يستخدم تنسيق COCO JSON إحداثيات البكسل بتنسيق [x_min, y_min, width, height] مع ملف JSON واحد لكافة الصور.
  • تختلف معرفات الفئات — حيث يستخدم COCO قيم category_id عشوائية، بينما يتطلب YOLO معرفات فئات تبدأ من الصفر.
الميزةCOCO JSONYOLO TXT
الهيكلملف JSON واحد لجميع الصورملف .txt واحد لكل صورة
تنسيق Bbox[x_min, y_min, width, height] بالبكسلclass x_center y_center width height مسوى (0-1)
معرفات الفئاتcategory_id (يمكن أن يبدأ من أي رقم)مفهرسة من الصفر (تبدأ من 0)
التجزئة (Segmentation)مصفوفات المضلعات في حقل segmentationإحداثيات المضلع بعد معرف الفئة
النقاط الرئيسية (Keypoints)[x, y, visibility, ...] بالبكسل[x, y, visibility, ...] مسوى

بدء التشغيل السريع#

أسرع طريقة لتحويل تعليقات 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=False`

تم تصميم القيمة الافتراضية لـ cls91to80=True فقط لـ مجموعة بيانات COCO القياسية التي تحتوي على 80 فئة كائنات، والتي تربط 91 معرف فئة غير متجاور بـ 80 معرف فئة متجاور. لأي مجموعة بيانات مخصصة، يجب عليك تعيين cls91to80=False — وإلا سيتم تعيين معرفات الفئات الخاصة بك بصمت بشكل غير صحيح وسيتعلم نموذجك فئات خاطئة.

دليل التحويل خطوة بخطوة#

جهز مجموعة بيانات 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" }
    ]
}

تحويل التعليقات التوضيحية#

استخدم الدالة convert_coco() لتحويل تعليقات COCO JSON التوضيحية إلى تنسيق YOLO .txt:

تحويل COCO إلى تنسيق YOLO
from ultralytics.data.converter import convert_coco

convert_coco(
    labels_dir="my_dataset/annotations/",
    save_dir="my_dataset/converted/",
    cls91to80=False,
)

يكتب convert_coco() ملف .txt واحد لكل صورة معلّقة داخل مجلد فرعي labels/ مُسمى باسم كل ملف JSON، مع إزالة بادئة 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) قبل إعادة التشغيل، وإلا ستستقر الخطوات التالية على قراءة تسميات قديمة.

تنظيم هيكل الدليل#

بعد التحويل، يجب وضع ملفات التسميات بجوار صورك. يتوقع YOLO وجود دليل labels/ يعكس دليل images/:

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.yaml

إنشاء 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

لمزيد من التفاصيل حول تنسيق YAML لمجموعة البيانات، راجع دليل تكوين مجموعة البيانات.

تدريب نموذج YOLO الخاص بك#

مع جاهزية مجموعة بياناتك المحولة، قم بتدريب نموذج YOLO:

التدريب على بيانات COCO المحولة
from ultralytics import YOLO

model = YOLO("yolo26n.pt")  # load a pretrained model
results = model.train(data="my_dataset/dataset.yaml", epochs=100, imgsz=640)

للحصول على نصائح التدريب وأفضل الممارسات، راجع دليل تدريب النماذج.

التحقق من التحويل الخاص بك#

قبل التدريب، تحقق عشوائياً من بعض ملفات التسمية للتأكد من صحة معرفات الفئات والإحداثيات:

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 إلى 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)، أو أن مربعات الإحاطة لها عرض أو ارتفاع يساوي صفراً.

الحل: افحص تعليقات JSON التوضيحية بحثاً عن قيم iscrowd. إذا كنت تستخدم أقنعة SAM، فقم بمعالجة ملف JSON مسبقاً لتعيين iscrowd: 0.

مضلعات على شكل صندوق من تعليقات الأقنعة#

إذا سجّل use_segments=True الرسالة annotations without a usable polygon، فهذا يعني أن بعض التعليقات التوضيحية لا تحمل قيمة segmentation، أو أن القيمة ليست قائمة مكونة من ثلاثة أزواج إحداثيات على الأقل. الأسباب الشائعة هي الصادرات الخاصة بالكتشاف فقط، والتي تترك الحقل مفقوداً أو فارغاً، وترميز تشغيل الطول لـ COCO ({"counts": ..., "size": ...})، والذي تكتبه مصدّرات الأقنعة الثنائية مثل SAM؛ يتم التعامل مع قائمة الإحداثيات المسطحة التي لا تحتوي على قائمة مضلعات محيطية، والمخططات ذات النقطة الواحدة والنقطتين، وغيرها من القيم التالفة بنفس الطريقة. يحتفظ التعليق التوضيحي بأي مضلعات تتبقى، ويلجأ إلى صف تجزئة على شكل مربع الإحاطة الخاص به عندما لا تتوفر أي منها، بحيث تظل التسميات صالحة ولكن تلك الصفوف لا تحمل تفاصيل قناع.

الحل: أعد تصدير التعليقات التوضيحية باستخدام تجزئات المضلعات، أو قم بفك تشفير أقنعة RLE إلى مضلعات قبل تشغيل convert_coco()، أو صحح أي قيم segmentation تالفة.

فجوات في معرفات الفئات في التسميات المحولة#

إذا كانت معرفات الفئات في ملفات التسميات غير متجاورة (على سبيل المثال، 0، 4، 9 بدلاً من 0، 1، 2)، فإن أداة التعليق التوضيحي الخاص بك تستخدم قيم category_id غير متجاورة.

الحل: تحقق من أن معرفات الفئات في ملفات .txt تتطابق مع قاموس names في dataset.yaml. قم بإعادة تعيين المعرفات إلى قيم متجاورة إذا لزم الأمر.

للحصول على تفاصيل واجهة برمجة التطبيقات الكاملة ووصف المعلمات، راجع [مرجع واجهة برمجة التطبيقات convert_coco.

الأسئلة الشائعة#

  • استخدم دالة 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. راجع الدليل خطوة بخطوة لمعرفة سير العمل الكامل.

  • يحدث هذا لأن convert_coco() يحفظ التسميات في مجلد فرعي داخل save_dir/labels/ (على سبيل المثال، save_dir/labels/train/) بدلاً من حفظها مباشرة في labels/train/ الخاص بمجموعة البيانات بجوار images/train/. يتوقع YOLO أن توجد التسميات بشكل موازٍ للصور — على سبيل المثال، يحتاج images/train/img.jpg إلى labels/train/img.txt. انقُل التسميات المحولة لتتوافق مع هذا الهيكل. راجع إصلاح بنية الدليل.

  • تتحكم معلمة cls91to80 في كيفية تعيين قيم COCO category_id إلى معرفات فئات YOLO. عندما تكون True (الافتراضية)، فإنها تطبق جدول البحث coco91_to_coco80_class() المصمم لـ مجموعة بيانات COCO القياسية، والتي تحتوي على 80 فئة بمعرفات غير متجاورة (1-90). بالنسبة لـ مجموعات البيانات المخصصة، قم دائماً بتعيين cls91to80=False — حيث يؤدي هذا ببساطة إلى طرح 1 من كل category_id لإنشاء معرفات فئات تبدأ من الصفر.

  • لا يمكن ذلك باستخدام خط أنابيب تدريب YOLO الحالي — يجب أن تكون التعليقات التوضيحية بتنسيق YOLO .txt مع ملف واحد لكل صورة. استخدم convert_coco() لتحويل ملف COCO JSON أولاً، ثم اتبع هذا الدليل للتنظيم والتدريب. لمزيد من المعلومات حول التنسيقات المدعومة، راجع تنسيقات مجموعات البيانات.

  • نعم، استخدم 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)
  • استخدم 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، فسيتم كتابة نقاط التباين فقط في ملفات التسميات — بينما يتم تجاهل التجزئات بصمت.

التعليقات