Link to this sectionفهم الاكتشاف من الطرف إلى الطرف في Ultralytics YOLO26#
Link to this sectionمقدمة#
إذا كنت تقوم بالترقية إلى YOLO26 من طراز سابق مثل YOLOv8 أو YOLO11، فإن أحد أكبر التغييرات التي ستلاحظها هو إزالة كبح الحد الأقصى غير الأولي (NMS). تنتج نماذج YOLO التقليدية آلاف التوقعات المتداخلة التي تحتاج إلى خطوة معالجة لاحقة منفصلة باستخدام NMS لتصفيتها وصولاً إلى الاكتشافات النهائية. وهذا يضيف زمن انتقال، ويعقد رسوم بيانية للتصدير، ويمكن أن يتصرف بشكل غير متسق عبر منصات الأجهزة المختلفة.
يتبع YOLO26 نهجاً مختلفاً. فهو يخرج الاكتشافات النهائية مباشرة من النموذج، ولا يتطلب أي تصفية خارجية. يُعرف هذا باسم اكتشاف الكائنات من الطرف إلى الطرف، وهو مفعل افتراضياً في جميع نماذج YOLO26. النتيجة هي خط أنابيب نشر أبسط، وزمن انتقال أقل، وأداء أسرع بنسبة تصل إلى 43% في الاستدلال على وحدات المعالجة المركزية (CPUs).
يرشدك هذا الدليل عبر ما تغير، وما إذا كنت بحاجة إلى تحديث الكود الخاص بك، وتنسيقات التصدير التي تدعم الاستدلال من الطرف إلى الطرف، وكيفية الترحيل بسلاسة من نماذج YOLO القديمة.
لإلقاء نظرة أعمق على الدافع وراء هذا التحول المعماري، راجع منشور مدونة Ultralytics حول سبب إزالة YOLO26 لـ NMS وكيف يغير ذلك النشر.
- هل تستخدم واجهة برمجة تطبيقات Ultralytics أو CLI؟ لا حاجة لإجراء تغييرات - فقط قم بتبديل اسم النموذج الخاص بك إلى
yolo26n.pt. - هل تستخدم كود استدلال مخصص (ONNX Runtime، TensorRT، إلخ)؟ قم بتحديث المعالجة اللاحقة الخاصة بك - مخرج الاكتشاف الآن هو
(N, 300, 6)بتنسيقxyxy، ولا يتطلب NMS. تضيف المهام الأخرى بيانات إضافية (معاملات القناع، أو النقاط الرئيسية، أو الزاوية). - هل تقوم بالتصدير؟ تدعم معظم التنسيقات مخرج الطرف إلى الطرف أصلياً. ومع ذلك، تعود بعض التنسيقات (NCNN، وRKNN، وPaddlePaddle، وExecuTorch، وIMX، وEdge TPU، وQNN) تلقائياً إلى المخرج التقليدي بسبب قيود المشغل غير المدعومة (على سبيل المثال،
torch.topk). يتم تجميع سير عمل Hailo HEF من ONNX باستخدام نصوص برمجية خاصة بـ Hailo، لذا تحقق من رأس الاكتشاف وتكوين NMS لنموذجك.
Link to this sectionكيف يعمل الاكتشاف من الطرف إلى الطرف#
يستخدم YOLO26 معمارية مزدوجة الرأس أثناء التدريب. يتشارك كلا الرأسين في نفس العمود الفقري والعنق، لكنهما ينتجان المخرجات بطرق مختلفة:
| الرأس | الغرض | مخرج الاكتشاف | المعالجة اللاحقة |
|---|---|---|---|
| واحد لواحد (افتراضي) | استدلال من الطرف إلى الطرف | (N, 300, 6) | عتبة الثقة فقط |
| واحد لكثير | مخرج YOLO التقليدي | (N, nc + 4, 8400) | يتطلب NMS |
الأشكال أعلاه مخصصة لـ الاكتشاف. توسع المهام الأخرى مخرج الواحد لواحد ببيانات إضافية لكل اكتشاف:
| المهمة | مخرج الطرف إلى الطرف | بيانات إضافية |
|---|---|---|
| الاكتشاف | (N, 300, 6) | — |
| تجزئة النسخ | (N, 300, 6 + nm) + proto (N, nm, H, W) | معاملات القناع nm (افتراضي 32) |
| الوضعية | (N, 300, 57) | 17 نقطة رئيسية × 3 (x، y، الرؤية) |
| OBB | (N, 300, 7) | زاوية الدوران |
أثناء التدريب، يعمل كلا الرأسين في وقت واحد - يوفر رأس الواحد لكثير إشارة تعلم أغنى، بينما يتعلم رأس الواحد لواحد إنتاج توقعات نظيفة وغير متداخلة. أثناء الاستدلال والتصدير، يكون رأس الواحد لواحد فقط هو النشط افتراضياً، حيث ينتج ما يصل إلى 300 اكتشاف لكل صورة بتنسيق [x1, y1, x2, y2, confidence, class_id].
عند استدعاء model.fuse()، فإنه يقوم بدمج طبقات Conv + BatchNorm لاستدلال أسرع، وفي نماذج الطرف إلى الطرف، يزيل أيضاً رأس الواحد لكثير - مما يقلل حجم النموذج وعمليات FLOPs. لمزيد من التفاصيل حول المعمارية مزدوجة الرأس، راجع صفحة نموذج YOLO26.
Link to this sectionهل أحتاج إلى تغيير الكود الخاص بي؟#
Link to this sectionاستخدام واجهة برمجة تطبيقات Python الخاصة بـ Ultralytics أو CLI#
لا حاجة لإجراء تغييرات. إذا كنت تستخدم واجهة برمجة تطبيقات Python الخاصة بـ Ultralytics القياسية أو CLI، فكل شيء يعمل تلقائياً - التنبؤ، والتحقق، والتصدير كلها تتعامل مع نماذج الطرف إلى الطرف بشكل مباشر.
from ultralytics import YOLO
# Load a YOLO26 model
model = YOLO("yolo26n.pt")
# Predict — no NMS step, no code changes
results = model.predict("image.jpg")Link to this sectionاستخدام كود استدلال مخصص#
نعم، تنسيق المخرج مختلف. إذا كتبت منطق معالجة لاحقة مخصصاً لـ YOLOv8 أو YOLO11 (على سبيل المثال، عند تشغيل الاستدلال باستخدام ONNX Runtime أو TensorRT)، فستحتاج إلى تحديثه للتعامل مع شكل المخرج الجديد:
| YOLOv8 / YOLO11 | YOLO26 (من الطرف إلى الطرف) | |
|---|---|---|
| مخرج الاكتشاف | (N, nc + 4, 8400) | (N, 300, 6) |
| تنسيق الصندوق | xywh (مركز x، مركز y، العرض، الارتفاع) | xyxy (أعلى يسار x، أعلى يسار y، أسفل يمين x، أسفل يمين y) |
| التخطيط | إحداثيات الصندوق + درجات الفئة لكل مرساة | [x1, y1, x2, y2, conf, class_id] |
| يتطلب NMS | نعم | لا |
| المعالجة اللاحقة | NMS + مرشح الثقة | مرشح الثقة فقط |
بالنسبة لمهام التجزئة، والوضعية، وOBB، يضيف YOLO26 بيانات خاصة بالمهمة إلى كل اكتشاف - راجع جدول أشكال المخرج أعلاه.
حيث N هو حجم الدفعة وnc هو عدد الفئات (على سبيل المثال، 80 لـ COCO).
مع نماذج الطرف إلى الطرف، تصبح المعالجة اللاحقة أبسط بكثير - على سبيل المثال، عند استخدام ONNX Runtime:
import onnxruntime as ort
# Load and run the exported end-to-end model
session = ort.InferenceSession("yolo26n.onnx")
output = session.run(None, {session.get_inputs()[0].name: input_tensor})
# End-to-end output: (batch, 300, 6) → [x1, y1, x2, y2, confidence, class_id]
detections = output[0][0] # first image in batch
detections = detections[detections[:, 4] > conf_threshold] # confidence filter — that's it!Link to this sectionالتبديل إلى رأس الواحد لكثير#
إذا كنت بحاجة إلى تنسيق مخرج YOLO التقليدي (على سبيل المثال، لإعادة استخدام كود المعالجة اللاحقة القائم على NMS)، يمكنك التبديل إلى رأس الواحد لكثير في أي وقت عن طريق ضبط end2end=False:
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
# Prediction with NMS (traditional behavior)
results = model.predict("image.jpg", end2end=False)
# Validation with NMS
metrics = model.val(data="coco.yaml", end2end=False)
# Export without end-to-end
model.export(format="onnx", end2end=False)Link to this sectionتوافق تنسيق التصدير#
تدعم معظم تنسيقات التصدير الاستدلال من الطرف إلى الطرف بشكل مباشر، بما في ذلك ONNX، وTensorRT، وCoreML، وOpenVINO، وTFLite، وTF.js، وMNN.
التنسيقات التالية لا تدعم الطرف إلى الطرف وتعود تلقائياً إلى رأس الواحد لكثير: NCNN، وRKNN، وPaddlePaddle، وExecuTorch، وIMX، وEdge TPU، وQualcomm QNN.
بالنسبة لـ Hailo HEF، تحدث خطوة التجميع خارج model.export(format=...) بعد تصدير ONNX. استخدم سجلات Hailo DFC، ونص برمجي للنموذج .alls، وJSON الخاص بـ NMS الذي يطابق نموذج الاكتشاف الدقيق الخاص بك؛ إذا لم يكن رسم YOLO26 من الطرف إلى الطرف مدعوماً بواسطة سلسلة أدوات Hailo الخاصة بك، فقم بتصدير نموذج ONNX مع end2end=False وقم بتجميع رأس الاكتشاف التقليدي.
يدعم TensorRT الطرف إلى الطرف، لكن يتم تعطيله تلقائياً عند التصدير باستخدام int8=True على TensorRT ≤10.3.0.
Link to this sectionمقايضات الدقة والسرعة#
يوفر الاكتشاف من الطرف إلى الطرف مزايا نشر كبيرة مع الحد الأدنى من التأثير على الدقة:
| المقياس | من الطرف إلى الطرف (افتراضي) | واحد لكثير + NMS (end2end=False) |
|---|---|---|
| سرعة الاستدلال على CPU | أسرع بنسبة تصل إلى 43% | الأساس |
| تأثير mAP | ~0.5 mAP أقل | يطابق أو يتجاوز YOLO11 |
| المعالجة اللاحقة | مرشح الثقة فقط | خط أنابيب NMS كامل |
| تعقيد النشر | الحد الأدنى | يتطلب تنفيذ NMS |
بالنسبة لمعظم التطبيقات الواقعية، فإن فرق ~0.5 mAP لا يذكر، خاصة عند النظر في مكاسب السرعة والبساطة. إذا كانت الدقة القصوى هي أولويتك القصوى، فيمكنك دائماً العودة إلى رأس الواحد لكثير باستخدام end2end=False.
راجع مقاييس أداء YOLO26 للحصول على معايير مفصلة عبر جميع أحجام النماذج (n, s, m, l, x).
Link to this sectionالترحيل من YOLOv8 أو YOLO11#
إذا كنت تقوم بترقية مشروع موجود إلى YOLO26، فإليك قائمة تحقق سريعة لضمان انتقال سلس:
- مستخدمو واجهة برمجة تطبيقات Ultralytics / CLI: لا حاجة لإجراء تغييرات - فقط قم بتحديث اسم النموذج إلى
yolo26n.pt(أوyolo26n-seg.pt، أوyolo26n-pose.pt، أوyolo26n-obb.pt) - كود المعالجة اللاحقة المخصص: قم بالتحديث للتعامل مع أشكال المخرج الجديدة -
(N, 300, 6)للاكتشاف، بالإضافة إلى بيانات خاصة بالمهمة لـ التجزئة، والوضعية، وOBB. لاحظ أيضاً تغيير تنسيق الصندوق منxywhإلىxyxy - خطوط أنابيب التصدير: تحقق من قسم توافق التنسيق أعلاه للحصول على تنسيقك المستهدف
- TensorRT + INT8: تحقق من أن إصدار TensorRT الخاص بك أكبر من 10.3.0 لدعم الآلية الشاملة (end-to-end).
- تصديرات FP16: إذا كنت بحاجة إلى جميع المخرجات بتنسيق FP16، فقم بالتصدير باستخدام
end2end=False— راجع لماذا تظل output0 بتنسيق FP32. - iOS / CoreML: الآلية الشاملة مدعومة بالكامل. إذا كنت بحاجة إلى دعم Xcode Preview، استخدم
end2end=Falseمعnms=True. - أجهزة الحافة (NCNN, RKNN): تعتمد هذه التنسيقات تلقائياً على نظام (one-to-many)، لذا قم بتضمين NMS في خط أنابيب المعالجة على الجهاز.
Link to this sectionالأسئلة الشائعة#
Link to this sectionهل يمكنني استخدام end2end=True و nms=True معاً؟#
لا. هذان الخياران متنافيان. إذا قمت بضبط nms=True على نموذج شامل أثناء التصدير، فسيتم فرض nms=False تلقائياً مع ظهور تحذير. يتعامل الرأس الشامل داخلياً مع تصفية التكرارات، لذا فإن NMS الخارجية غير ضرورية.
ومع ذلك، فإن end2end=False مقترناً بـ nms=True يعد إعداداً صالحاً — حيث يقوم بدمج NMS التقليدي في مخطط التصدير. قد يكون هذا مفيداً لتصديرات CoreML لأنه يتيح لك استخدام وظيفة المعاينة في Xcode مع نموذج الكشف مباشرة.
Link to this sectionما الذي يتحكم فيه المعامل max_det في النماذج الشاملة؟#
يحدد المعامل max_det (الافتراضي: 300) الحد الأقصى لعدد الكشوفات التي يمكن للرأس (one-to-one) إخراجها لكل صورة. يمكنك ضبطه في وقت الاستدلال أو التصدير:
model.predict("image.jpg", max_det=100) # fewer detections, slightly faster
model.export(format="onnx", max_det=500) # more detections for dense scenesلاحظ أن نقاط التحقق الافتراضية في YOLO26 تم تدريبها باستخدام max_det=300. على الرغم من أنه يمكنك زيادة هذه القيمة، إلا أن الرأس (one-to-one) تم تحسينه أثناء التدريب لإنتاج ما يصل إلى 300 كشف دقيق، لذا قد تكون الكشوفات التي تتجاوز هذا الحد أقل جودة. إذا كنت بحاجة إلى أكثر من 300 كشف لكل صورة، ففكر في إعادة التدريب باستخدام قيمة max_det أعلى.
Link to this sectionنموذج ONNX الخاص بي يخرج (1, 300, 6) — هل هذا صحيح؟#
نعم، هذا هو تنسيق المخرجات الشامل المتوقع للكشف: batch size يساوي 1، بما يصل إلى 300 كشف، يحتوي كل منها على 6 قيم [x1, y1, x2, y2, confidence, class_id]. ما عليك سوى التصفية حسب عتبة الثقة وستنتهي — لا حاجة إلى NMS.
بالنسبة للمهام الأخرى، يختلف شكل المخرجات:
| المهمة | شكل المخرجات | الوصف |
|---|---|---|
| الكشف | (1, 300, 6) | [x1, y1, x2, y2, conf, class_id] |
| التجزئة (Segmentation) | (1, 300, 38) + (1, 32, 160, 160) | 6 قيم للصندوق + 32 معامل قناع، بالإضافة إلى مصفوفة قناع أولية (prototype mask tensor) |
| الوضعية (Pose) | (1, 300, 57) | 6 قيم للصندوق + 17 نقطة رئيسية × 3 (x, y, الرؤية) |
| OBB | (1, 300, 7) | 6 قيم للصندوق + زاوية دوران واحدة |
Link to this sectionكيف أتحقق مما إذا كان النموذج المصدر الخاص بي شاملاً؟#
يمكنك التحقق باستخدام Ultralytics Python API أو عن طريق فحص بيانات تعريف نموذج ONNX المصدر مباشرة:
from ultralytics import YOLO
model = YOLO("yolo26n.onnx")
model.predict(verbose=False) # run predict to setup predictor first
print(model.predictor.model.end2end) # True if end-to-end is enabledبدلاً من ذلك، تحقق من شكل المخرجات — نماذج الكشف الشاملة تخرج (1, 300, 6)، بينما تخرج النماذج التقليدية (1, nc + 4, 8400). لأشكال المهام الأخرى، راجع الأسئلة الشائعة حول أشكال المخرجات.
Link to this sectionهل الآلية الشاملة مدعومة لمهام تجزئة المثيلات، والوضعية، و OBB؟#
نعم. متغيرات مهام YOLO26 بأسلوب الكشف — الكشف، تجزئة المثيلات، تقدير الوضعية، والكشف عن الأشياء الموجهة (OBB) — تدعم الاستدلال الشامل افتراضياً. خيار end2end=False متاح عبر هذه المهام أيضاً.
توسع كل مهمة مخرجات الكشف الأساسية ببيانات خاصة بالمهمة:
| المهمة | النموذج | مخرج الطرف إلى الطرف |
|---|---|---|
| الكشف | yolo26n.pt | (N, 300, 6) |
| تجزئة المثيلات | yolo26n-seg.pt | (N, 300, 38) + proto (N, 32, 160, 160) |
| الوضعية (Pose) | yolo26n-pose.pt | (N, 300, 57) |
| OBB | yolo26n-obb.pt | (N, 300, 7) |