اجمع بيانات عالية الجودة وممثّلة للواقع
اجمع الصور من ظروف النشر الفعلية، وأدرج بيانات الالتقاط الوصفية في كل اسم ملف، وتتبّع التغطية مقارنةً بالمواصفات، وخذ عينات من الفيديو دون إغراق مجموعة البيانات بالصور.
معظم إخفاقات مجموعات البيانات سببها إخفاقات في الجمع. يلتقط الفريق أمثلة واضحة من كاميرا واحدة خلال أسبوع واحد، فتبدو نتائج التحقق ممتازة، ثم ينهار أداء النموذج في الموقع الثاني. يضع الجمع سقف الأداء: فلا جودة الوسوم ولا زيادة البيانات ولا المعلمات الفائقة تستطيع تعليم النموذج عن مشهد لم تتضمنه مجموعة البيانات قط.
عملي
التنوع يتفوق على الحجم#
قارن مجموعتي البيانات الموجهتين إلى النشر نفسه:
| مجموعة البيانات | نتيجة التحقق | في الإنتاج |
|---|---|---|
| 10,000 إطار شبه متطابق، من كاميرا واحدة، وقت الظهيرة فقط | مرتفعة: إطارات التحقق تشبه إطارات التدريب | يتراجع الأداء مع كاميرا مختلفة وعند الغسق |
| 1,500 إطار موزعة على 12 سيناريو من المواصفات | أكثر تواضعًا | يصمد الأداء، لأن ظروف الإنتاج تشبه البيانات |
لا ترتفع نتيجة التحقق لمجموعة البيانات الأولى إلا لأن التحقق يقيس الحالة الوحيدة التي تغطيها. في الإنتاج، لا يتجاوز أداء النموذج مستوى أسوأ سيناريو من حيث التغطية يواجهه. أعطِ الأولوية لتغطية المواصفات عند جمع البيانات، ثم للحجم.
اختر المصادر بالترتيب الصحيح#
ينبغي أن يأتي معظم مجموعة البيانات من إعداد الإنتاج الفعلي. يتناول دليل جمع البيانات ووسمها كل مصدر بمزيد من التفصيل:
| المصدر | متى يكون مفيدًا | متى يكون ضارًا |
|---|---|---|
| كاميرات الإنتاج، بث مباشر | الأقرب إلى ظروف النشر | بطيء؛ وقد يتطلب اتفاقيات بيانات |
| كاميرات الإنتاج، أرشيفية | تنوع كبير في وقت قصير | قد لا تتطابق اللقطات القديمة مع الإعداد الحالي |
| مجموعات البيانات العامة (COCO، Open Images، VOC) | البدء بفئات شائعة | اختلاف المجال عن مشاهدك |
| لقطات مُعدّة | حالات حدّية محددة عند الطلب | نظيفة أكثر من اللازم؛ يسهل الاعتماد عليها بإفراط |
| صور اصطناعية أو مولّدة | مخاطر وأعطال نادرة لا يمكنك انتظار وقوعها | قد يتعلم النموذج أسلوب المولّد |
| استخراج الصور من الويب | تنوع منخفض التكلفة | جودة غير متسقة ومخاطر الترخيص |
استخدم الصور المُعدّة والعامة والاصطناعية لسدّ نواقص محددة ومسمّاة في المواصفات، وتتبّع نسبتها في مجموعة البيانات كي تتمكن من قياس مدى فائدتها. في Ultralytics Platform، تضيف ميزة إنشاء صور مشابهة تنويعات مولّدة لصورة موجودة إلى مجموعة البيانات، دون وسوم وجاهزة للتوسيم.
أدرج البيانات الوصفية في اسم الملف#
يحتاج كل ملف صورة إلى معرّف كاميرا واحد على الأقل، ويوم الالتقاط، ورقم إطار أو مقطع. من دون هذه المعلومات، لن تتمكن لاحقًا من التقسيم حسب المجموعة، أو تتبّع مشكلة تراجعية وصولًا إلى مصدرها، أو جمع مزيد من البيانات لسيناريو ناقص التمثيل. واسم الملف هو الوسيلة الأكثر موثوقية لحمل هذه المعلومات: إذ يبقى cam2_2026-05-01_000124.jpg محفوظًا في كل أداة وتصدير وتحميل. يتيح البحث في مجموعات البيانات على Ultralytics Platform البحث بأسماء الملفات والبيانات الوصفية المخصصة، لذلك تظل هذه المفاتيح قابلة للبحث بعد التحميل.
ينشئ هذا البرنامج النصي مجموعة بيانات التدريب العملي التي يستخدمها باقي المقرر. ينسخ الصور الموسومة من COCO128 ويعيد تسميتها كما لو أن أربع كاميرات التقطتها على مدار أربعة أيام، مع زيادة جمع cam1 بالطريقة المعتادة مع الكاميرا المتاحة بسهولة:
import shutil
from pathlib import Path
from ultralytics.data.utils import check_det_dataset, img2label_paths
data = check_det_dataset("coco128.yaml") # 128 COCO images stand in for your camera captures
out = Path("datasets/practice")
(out / "images").mkdir(parents=True, exist_ok=True)
(out / "labels").mkdir(parents=True, exist_ok=True)
for i, image in enumerate(sorted(Path(data["train"]).glob("*.jpg"))):
camera = ("cam1", "cam1", "cam2", "cam3", "cam4")[i % 5] # cam1 over-collected, like a real site
name = f"{camera}_2026-05-0{i // 32 + 1}_{i:06d}" # camera, capture day, frame number
shutil.copy(image, out / "images" / f"{name}.jpg")
label = Path(img2label_paths([str(image)])[0])
if label.exists():
shutil.copy(label, out / "labels" / f"{name}.txt")
print(len(list((out / "images").glob("*.jpg"))), "images written to", out)128 images written to datasets/practice
يحافظ التحميل إلى Ultralytics Platform على أسماء الملفات هذه. ويقبل مربع حوار التحميل أيضًا مقاطع الفيديو ومجموعات البيانات كاملة، وتتضمن إعداداته تمويه الوجوه لحماية الخصوصية.
تتبّع التغطية مقارنةً بالمواصفات#
مع وجود البيانات الوصفية في أسماء الملفات، يصبح قياس التغطية مسألة عدّ. حدّد الحصص وفقًا لمواصفاتك، ودع البرنامج النصي يحدد ما ينبغي جمعه بعد ذلك:
from collections import Counter
from pathlib import Path
QUOTA = {"cam1": 30, "cam2": 30, "cam3": 30, "cam4": 30} # images per camera, from your spec
images = sorted(Path("datasets/practice/images").glob("*.jpg"))
cameras = Counter(p.stem.split("_")[0] for p in images)
days = Counter(p.stem.split("_")[1] for p in images)
for camera, quota in QUOTA.items():
gap = quota - cameras[camera]
print(f"{camera}: {cameras[camera]:3d} / {quota} {'ok' if gap <= 0 else f'collect {gap} more'}")
print("days:", dict(sorted(days.items())))cam1: 52 / 30 ok
cam2: 26 / 30 collect 4 more
cam3: 25 / 30 collect 5 more
cam4: 25 / 30 collect 5 more
days: {'2026-05-01': 32, '2026-05-02': 32, '2026-05-03': 32, '2026-05-04': 32}قاعدة اتخاذ القرار: توقف عن الجمع من أي مصدر تجاوز حصته، ووجّه الجهد إلى النواقص. هنا، تضم cam1 بالفعل 40% من الصور. وسيؤدي قضاء أسبوع آخر في جمع لقطاتها إلى زيادة الحجم، لا إلى إضافة تغطية جديدة.
خذ عينات من الفيديو دون إغراق مجموعة البيانات#
الفيديو هو أقل المصادر تكلفةً وأسهلها إساءةً في الاستخدام. فعند 30 إطارًا في الثانية، تنتج الدقيقة الواحدة 1,800 إطار شبه متطابق، كما أن وسم اللحظة نفسها مرتين يكلّف المال ويضخّم المقاييس. احتفظ بإطار فقط عندما يكون المشهد قد تغيّر منذ آخر إطار احتفظت به:
from pathlib import Path
import cv2
from ultralytics.utils.downloads import safe_download
video = "solutions_ci_demo.mp4" # a short public demo clip; swap in your own footage
safe_download(f"https://github.com/ultralytics/assets/releases/download/v0.0.0/{video}")
Path("frames").mkdir(exist_ok=True)
cap = cv2.VideoCapture(video)
fps = cap.get(cv2.CAP_PROP_FPS)
read = kept = 0
last = None
while True:
ok, frame = cap.read()
if not ok:
break
thumb = cv2.cvtColor(cv2.resize(frame, (64, 64)), cv2.COLOR_BGR2GRAY).astype(float)
if last is None or abs(thumb - last).mean() > 10: # keep a frame only when the scene has changed
cv2.imwrite(f"frames/clip01_{read:06d}.jpg", frame) # the clip ID stays in the filename
kept, last = kept + 1, thumb
read += 1
print(f"{read} frames at {fps:.0f} FPS -> {kept} kept")62 frames at 30 FPS -> 6 keptيحتوي المقطع الذي تبلغ مدته ثانيتين على 62 إطارًا، لكن فيه 6 لحظات متميزة بصريًا فقط. يقارن البرنامج النصي صورًا مصغرة صغيرة بتدرّج الرمادي، لذا فهو سريع عند معالجة ساعات من اللقطات. ارفع عتبة 10 للاحتفاظ بعدد أقل من الإطارات من الكاميرات الثابتة، واخفضها للمشاهد سريعة الحركة. وزّع الميزانية على المقاطع أيضًا: فـ20 إطارًا من كل واحد من 50 مقطعًا أفضل من 1,000 إطار من مقطع واحد.
يشترك إطاران يفصل بينهما ثانية واحدة في الإضاءة والخلفية، وعادةً في الكائنات نفسها. إذا وُضعا في مجموعتي التدريب والتحقق، فسيُقيّم التحقق على صور سبق للنموذج أن رآها فعليًا. احتفظ بمعرّف المقطع في كل اسم ملف حتى يتمكن تقسيم مجموعة البيانات على نحو صحيح من إبقاء المقطع متماسكًا.
تجنّب مزالق جمع البيانات#
| المأزق | العَرَض | الحل |
|---|---|---|
| جمع البيانات خلال أسبوع واحد | قيمة mAP مرتفعة على بيانات التحقق، مع إخفاقات في فصول أو نوبات أخرى | وزّع عمليات الالتقاط على أسابيع أو أشهر |
| كاميرا واحدة | يفشل النموذج مع الكاميرا الثانية | التقط صورًا من كل نوع كاميرا تنشره |
| بيانات مُعدّة فقط | يفشل النموذج في التعامل مع الفوضى الواقعية | اجعل الصور المُعدّة أقلية صغيرة ومُتابَعة |
| إطارات مكررة | مقاييس مضخّمة وهدر في أعمال وضع الوسوم | خذ عينات عند تغيّر المشهد؛ وتتخطى Ultralytics Platform أيضًا النسخ المطابقة تمامًا عند الرفع |
| مشغّل واحد أو وردية واحدة | مظاهر غير مخطط لها واختلال توازن الفئات | خذ عينات من ورديات ومواقع وأشخاص مختلفين |
| غياب الحالات النادرة | يفوّت النموذج أحداث السلامة الأهم | التقاط موجّه أو إعداد مشاهد أو استكمال اصطناعي |
التحيز والموافقة#
التحيز مشكلة في جمع البيانات، لا في النمذجة: فلا توجد قيمة للمعاملات الفائقة تعالج غياب مجموعة لم تتضمنها البيانات أصلًا. يسرد دليل جمع البيانات أربعة عوامل مؤثرة: تنوّع المصادر، والتمثيل المتوازن، وإعادة تدقيق التغطية بانتظام، والتخفيف من التحيز بوسائل مثل زيادة أخذ العينات من المجموعات الأقل تمثيلًا.
إذا كانت الصور تتضمن وجوهًا أو لوحات تسجيل أو بيانات شخصية أخرى، فأنت بحاجة إلى موافقة وسياسة للاحتفاظ بالبيانات قبل بدء الجمع. يُعد مدخل خصوصية البيانات في المسرد نقطة بداية جيدة، ويتناول الخصوصية والمناطق والامتثال كيفية إبقاء البيانات ضمن النطاق القضائي المناسب باستخدام dataRegion.
عرض الحل
بالنسبة إلى مجموعة التدريب العملي، يقدّم تقرير التغطية خطة مباشرة:
| المصدر | العدد / الحصة | الإجراء |
|---|---|---|
cam1 | 52 / 30 | أوقف الجمع؛ فقد بلغت النسبة 40% من إجمالي الصور بالفعل |
cam2 | 26 / 30 | اجمع 4 صور أخرى |
cam3 | 25 / 30 | اجمع 5 صور أخرى |
cam4 | 25 / 30 | اجمع 5 صور أخرى |
تغطي كل كاميرا الأيام الأربعة كلها، لذا فالفجوات تخص كل كاميرا، لا كل يوم. وزّع الصور الـ14 الجديدة على يومين جديدين على الأقل، كي تضيف ظروفًا جديدة بدلًا من تكرار مشاهد فترة ما بعد الظهر نفسها. إذا تعذّر على كاميرا ما توفير حصتها (كاميرا لا ترى سوى المشاهد الليلية)، فأضف صفًا في المواصفات للظرف المفقود، وسجّل ما إذا كانت الصور المُعدّة أو المُولّدة ستسد هذه الفجوة، حتى يتسنى قياس أثرها لاحقًا.