Ultralytics YOLO27: انضم إلى قائمة الانتظار.
Get Started
درّب أول نموذج YOLO لديك·البيانات·الدرس 4/10
الدرسمبتدئ

إعداد مجموعة بيانات مخصصة

رتّب الصور والتسميات بتنسيق Ultralytics YOLO، وحوّل مربعات البكسل إلى أسطر تسميات مُطبَّعة، واكتشف التسميات المعطوبة قبل التدريب.

لا يؤدي اسم مجلد خاطئ أو تسمية غير مُطبَّعة إلى إيقاف التدريب. يتجاوز Ultralytics الصور المعطوبة ويتابع العمل، فتدرّب على جزء من بياناتك وتحصل على نموذج متوسط الأداء، ثم تقضي فترة بعد الظهر في البحث عن السبب في المكان الخطأ.

يتناول هذا الدرس الجانب الإجرائي من مجموعة بيانات الكشف: المجلدات، وأسطر التسميات، والتحويل، والفحوصات. ستعمل على مجموعة بيانات الحبوب الطبية الفعلية، التي تضم 115 صورة ويستخدمها باقي هذه الدورة في التدريب. أما تحديد ما ينبغي جمعه وكيفية تسميته، فيتناوله درس أفضل ممارسات الوسم.

النتيجة

يمكنك ترتيب مجموعة بيانات بتنسيق Ultralytics YOLO، وتحويل مربعات البكسل إلى أسطر تسميات مُطبَّعة، واكتشاف التسميات المفقودة أو المعطوبة من سطر الفحص قبل التدريب.

المسار السريع
إذا كنت تعرف الأساسيات بالفعل، فإليك النسخة المختصرة.
  1. أنشئ images/{train,val} وlabels/{train,val} بأسماء ملفات متطابقة.

  2. اكتب سطرًا واحدًا من class x_center y_center width height لكل عنصر، واجعل كل قيمة بين 0 و1.

  3. حوّل مربعات البكسل بقسمة الإحداثيات على عرض الصورة وارتفاعها.

  4. ارسم ملف تسمية فوق صورته، وتحقق من أن سطر الفحص يعرض 0 corrupt.

عملي

الحصول على مجموعة بيانات التدريب#

مربع حوار «مجموعة بيانات جديدة» في منصة Ultralytics: منطقة لإفلات الصور أو مقاطع الفيديو أو مجموعات البيانات بتنسيقات YOLO وCOCO وNDJSON، ثم حقول الاسم وعنوان URL والوصف ونوع المهمة

التنسيق الموضح أدناه هو أيضًا ما يقبله مربع حوار «مجموعة بيانات جديدة» في منصة Ultralytics كملف zip، لذا سيُرفع دون تغيير أي ملف لمجموعة بيانات تُعدّها هنا. نزّل 92 إطارًا للتدريب و23 إطارًا للتحقق من صحة صور الحبوب في عبوات الشرائط، وفك ضغطها في my_dataset:

curl -L -o medical-pills.zip https://github.com/ultralytics/assets/releases/download/v0.0.0/medical-pills.zip
unzip -q medical-pills.zip -d my_dataset
my_dataset/
├── images/
│   ├── train/   Frame_0.jpg, Frame_100.jpg, ... (92 images)
│   └── val/     Frame_144.jpg, ... (23 images)
└── labels/
    ├── train/   Frame_0.txt, Frame_100.txt, ... (92 files)
    └── val/     Frame_144.txt, ... (23 files)

لا يوجد ملف بيان. يعثر Ultralytics على كل تسمية باستبدال /images/ بـ /labels/ في مسار الصورة، واستبدال الامتداد بـ .txt، ولذلك يقرأ images/val/Frame_144.jpg الملف labels/val/Frame_144.txt. وينتج عن ذلك أمران:

  • يجب تسمية المجلدين بالضبط images وlabels، ووضعهما جنبًا إلى جنب.
  • الصورة التي يحتوي ملف تسميتها على محتوى فارغ أو التي لا تملك ملف تسمية هي صورة خلفية: وهذا صالح ومفيد لتعليم النموذج ما لا ينبغي اكتشافه، لكن فقط إذا كان ذلك مقصودًا.

قراءة سطر التسمية#

ملف تسمية YOLO للصورة zidane.jpg، صف واحد لكل عنصر: فهرس الفئة، ثم مركز x وy والعرض والارتفاع مُطبَّعة

يمثل كل سطر عنصرًا واحدًا: فهرس فئة صحيح، ثم مركز مربع الإحاطة وحجمه على هيئة كسور من عرض الصورة وارتفاعها. سطر فعلي من labels/train/Frame_0.txt:

0 0.330729 0.816204 0.103125 0.121296
  • 0: فهرس الفئة 0، الذي سيُسمّيه ملف YAML pill.
  • 0.330729 0.816204: يقع مركز المربع عند 33% من عرض الصورة و82% من ارتفاعها.
  • 0.103125 0.121296: يبلغ عرض المربع نحو 10% من عرض الصورة وارتفاعه نحو 12% من ارتفاعها.

مثال تطبيقي: تحويل مربع بكسل#

غالبًا ما تُصدّر أدوات الوسم إحداثيات الزوايا بالبكسل (x1, y1, x2, y2). اقسمها على أبعاد الصورة. يمتد الشخص الواقع في أقصى اليسار في صورة bus.jpg ذات الأبعاد 810×1080 من (49, 398) إلى (240, 902):

الحقلالصيغةالقيمة
x_center(x1 + x2) / 2 / العرض(49 + 240) / 2 / 810 = 0.178395
y_center(y1 + y2) / 2 / الارتفاع(398 + 902) / 2 / 1080 = 0.601852
width(x2 − x1) / العرض191 / 810 = 0.235802
height(y2 − y1) / الارتفاع504 / 1080 = 0.466667

يمكن لمعظم أدوات الوسم، وأدوات مثل Roboflow، التصدير مباشرةً بتنسيق YOLO. بالنسبة إلى ملفات COCO JSON، اتبع دليل التدريب باستخدام COCO JSON؛ ويغطي مستودع JSON2YOLO التنسيقات الأخرى. أما ملفات Pascal VOC XML، فيمكن تطبيق الصيغة أعلاه بنص برمجي قصير:

import xml.etree.ElementTree as ET
from pathlib import Path

CLASSES = ["person", "bus"]  # index = class id; must match names in data.yaml

def voc_to_yolo(xml_file: Path, out_dir: Path) -> None:
    root = ET.parse(xml_file).getroot()
    w, h = int(root.find("size/width").text), int(root.find("size/height").text)
    lines = []
    for obj in root.iter("object"):
        name = obj.find("name").text
        if name not in CLASSES:
            continue
        box = obj.find("bndbox")
        x1, y1, x2, y2 = (float(box.find(k).text) for k in ("xmin", "ymin", "xmax", "ymax"))
        xc, yc, bw, bh = (x1 + x2) / 2 / w, (y1 + y2) / 2 / h, (x2 - x1) / w, (y2 - y1) / h
        lines.append(f"{CLASSES.index(name)} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}")
    out_dir.mkdir(parents=True, exist_ok=True)
    (out_dir / f"{xml_file.stem}.txt").write_text("\n".join(lines) + "\n")

voc_to_yolo(Path("bus.xml"), Path("labels"))
print(Path("labels/bus.txt").read_text())

عند تشغيله على bus.xml الذي يحتوي على مربعي الشخص والحافلة من الدرس السابق، يطبع المثال التطبيقي والحافلة:

0 0.178395 0.601852 0.235802 0.466667
1 0.495679 0.454167 0.991358 0.482407

تحقّق قبل التدريب#

ارسم بعض ملفات التسميات فوق صورها. فئة مزاحة أو تبديل موضعي x وy أو مربعات حول الظلال أمور واضحة بالعين ولا تظهر في المقاييس:

from ultralytics.data.utils import visualize_image_annotations

visualize_image_annotations(
    "my_dataset/images/train/Frame_0.jpg",
    "my_dataset/labels/train/Frame_0.txt",
    {0: "pill"},
)

ثم دع Ultralytics يتحقق من كل ملف. يفحص التسميات عند قراءة مجموعة البيانات للمرة الأولى، ويقرر سطرًا بسطر ما إذا كانت كل صورة صالحة للاستخدام:

يعرض سطر الفحص النتيجة: 23 images, 0 backgrounds, 0 corrupt هو الشكل المتوقع لمجموعة بيانات سليمة. وأي نتيجة أخرى تشير إلى أحد الأخطاء أدناه.

تجنّب هذه الأخطاء#

نسيان التطبيع

العَرَض: ignoring corrupt image/label: non-normalized or out of bounds coordinates [634. 881. 198. 163.] وعدد غير صفري في corrupt. السبب: استخدام قيم البكسل بدلًا من الكسور. الحل: اقسم على عرض الصورة وارتفاعها. أي قيمة تسمية أكبر من 1 تعني أن الصندوق لم يُطبّع قط.

تسمية مجلد التسميات باسم خاطئ

العَرَض: يفحص yolo val المسار 0 images, 23 backgrounds ويصدر تحذير No labels found، ثم يتوقف التدريب مع ValueError: train: No labels found — والسبب هنا أن اسم مجلد التسميات كان annotations. الحل: سمِّ المجلدين images وlabels تمامًا، مع تطابق أسماء الملفات.

تبدأ فهارس الفئات من 1

العَرَض: Label class 1 exceeds dataset class count 1. Possible class labels are 0-0. السبب: رقّمت أداة التصدير الفئات ابتداءً من 1. الحل: تبدأ فئات YOLO من 0؛ اطرح 1 في برنامج التحويل النصي أو أصلح إعداد التصدير.

الزوايا مقابل المراكز

إذا ظهرت الصناديق مزاحة إلى الأسفل واليمين بمقدار نصف صندوق، فقد كتبت x1 y1 w h بدلًا من x_center y_center w h. يكشف رسم ملف واحد المشكلة خلال ثوانٍ، ولا يستطيع أي فحص للمسح اكتشافها.

لإجراء فحوصات منهجية على مجموعة بيانات كاملة، راجع مراقبة جودة مجموعة البيانات. تُعد المجموعات المضمنة مثل coco8 وcoco128 وafrican-wildlife أمثلة جيدة على التنسيقات التي يمكنك نسخها؛ ويسرد استعراض مجموعات البيانات جميع المجموعات. يضيف المدرّب زيادة البيانات إلى تسمياتك، لذا فإن إجراء تنظيف سريع للبيانات هنا يفيد في كل حقبة تدريب.

جرّبه

نزّل مجموعة بيانات الحبوب إلى my_dataset. قدّم نتائج ثلاثة فحوصات: عدد الصور والتسميات لكل تقسيم، ومخرجات نص برمجي يطبع أي قيمة تسمية خارج النطاق 0–1 (وينبغي ألا يطبع شيئًا)، وملف تسمية واحدًا مرسومًا فوق صورته باستخدام visualize_image_annotations. إذا كانت لديك صورك الموسومة، فحوّل 10 منها إلى التنسيق نفسه وارسم واحدة منها.

متى يُعدّ مكتملًا
تكون قد أتممت الدرس عند تحقق جميع الشروط التالية.
  • يحتوي my_dataset على images/train وimages/val وlabels/train وlabels/val بأسماء ملفات وأعداد متطابقة.

  • لا يعثر نص التحقق البرمجي لديك على أي قيمة تسمية خارج النطاق 0–1.

  • لقد رسمت ملف تسمية واحدًا على الأقل فوق صورته، وتقع المربعات على الحبوب.

عرض الحل
for s in train val; do
  echo "$s: $(ls my_dataset/images/$s | wc -l) images, $(ls my_dataset/labels/$s | wc -l) labels"
done
# train: 92 images, 92 labels
# val:   23 images, 23 labels
from pathlib import Path

for txt in Path("my_dataset/labels").rglob("*.txt"):
    for line in txt.read_text().splitlines():
        values = [float(v) for v in line.split()[1:]]
        if any(v < 0 or v > 1 for v in values):
            print(txt, line)

عدم ظهور أي مخرجات من النص البرمجي يعني أن جميع الإحداثيات مُطبَّعة. وتساوي الأعداد في كل تقسيم يعني أن لكل صورة ملف تسمية؛ وسيؤكد سطر الفحص في الدرس التالي عدم وجود ملفات معطوبة.

ما الخطوة التالية

المجلدات جاهزة. بعد ذلك، اكتب ملف YAML واحدًا يخبر Ultralytics بمواقعها ومعاني الفئات.

سجّل الدخول لحفظ التقدم