Meet YOLO26: next-gen vision AI.

Link to this sectionتصدير Hailo لنماذج Ultralytics YOLO#

ليس تنسيق تصدير مباشر من Ultralytics

ملف Hailo HEF غير مدعوم حاليًا كوجهة مباشرة لـ Ultralytics model.export(format="hailo"). سير العمل أدناه هو إجراء بديل يدوي يتضمن التصدير إلى ONNX أولاً، ثم استخدام مجموعة أدوات المترجم Dataflow Compiler الخارجية من Hailo لإنتاج ملف .hef. يجب أن يوفر سير عمل Ultralytics المتكامل دعم Hailo من خلال نفس واجهة برمجة تطبيقات التصدير Python وCLI المتاحة لتنسيقات الأجهزة الأخرى.

تستخدم سلسلة أدوات Hailo ملفات HEF للمنصات المدمجة بما في ذلك Raspberry Pi AI Kit و AI HAT+، والكاميرات الصناعية، وبوابات الحافة (edge gateways)، وأجهزة الكمبيوتر المزودة بـ AI.

يرشدك هذا الدليل خلال تصدير نماذج Ultralytics YOLO مختارة إلى تنسيق HEF (تنسيق Hailo القابل للتنفيذ) الخاص بـ Hailo باستخدام حزمة تطوير البرامج Hailo Dataflow Compiler (DFC). يبدأ سير العمل من نموذج YOLO .pt ويقوم بالتصدير إلى ONNX، ثم يتم تجميعه باستخدام أدوات Hailo لإنتاج ملف .hef جاهز للمعالجات المسرّعة من Hailo المدعومة.

Link to this sectionمتى تستخدم Hailo HEF#

HEF هو العنصر المجمّع الذي تستهلكه HailoRT على أجهزة Hailo المستهدفة. استخدم هذا الدليل اليدوي فقط عندما تتطلب أجهزة النشر الخاصة بك تنسيق Hailo HEF تحديدًا قبل توفر دعم التصدير المباشر لـ Hailo في Ultralytics.

يعد HEF مشابهاً في دوره أثناء النشر لتنسيقات خاصة بالأجهزة مثل RKNN لمسرعات Rockchip NPUs، و IMX500 لكاميرات Raspberry Pi AI، و Qualcomm QNN لمسرعات Snapdragon NPUs، ولكنه لا يتم إنتاجه حالياً مباشرة بواسطة Ultralytics.

يكون سير العمل هذا مناسباً عندما تحتاج إلى:

  • توافق Raspberry Pi AI Kit: يتم استخدام Hailo-8L في المجموعات الرسمية Raspberry Pi AI Kit و AI HAT+.
  • المعالجة اللاحقة بواسطة HailoRT: يمكن لـ HailoRT تضمين non-maximum suppression الخاص بـ YOLO في مسار الاستدلال المجمع.
  • التجميع بتنسيق INT8: يقوم Hailo DFC بعملية تكميم (quantization) للنموذج باستخدام صور معايرة تمثيلية لإنتاج رسم بياني INT8 لأجهزة Hailo. تعرف على المزيد حول model quantization.

Link to this sectionتنسيق تصدير Hailo HEF#

HEF هو ملف قابل للتنفيذ خاص بالأجهزة يتم إنتاجه بواسطة Hailo Dataflow Compiler. يحتوي على الرسم البياني للنموذج المكمم، وتخصيص الذاكرة، والجدولة، والمعالجة اللاحقة الاختيارية المهيأة لبنية Hailo المستهدفة. على عكس تنسيقات Export mode القياسية في YOLO التي يتم إنتاجها مباشرة بواسطة model.export(format=...) ، يستخدم تجميع HEF حالياً مساراً من مرحلتين:

  1. تصدير YOLO إلى ONNX باستخدام Ultralytics.
  2. استخدام أدوات Hailo DFC لتحليل وتحسين وتكميم وتجميع نموذج ONNX إلى HEF.

يتوسع سير العمل الكامل ليشمل المسار التالي:

YOLO (.pt) -> ONNX -> HAR (parse) -> HAR (optimize/quantize) -> HEF (compile)
  1. التصدير إلى ONNX باستخدام Export mode من Ultralytics
  2. تحليل نموذج ONNX إلى تنسيق HAR الوسيط الخاص بـ Hailo
  3. تحميل نص برمجي للنموذج (.alls) مع توجيهات التطبيع والمعالجة اللاحقة
  4. المعايرة والتكميم باستخدام صور تمثيلية
  5. التجميع إلى ملف HEF قابل للنشر

Link to this sectionالمهام المدعومة#

يركز المثال اليدوي الحالي على اكتشاف الكائنات في YOLO11 لأن برنامج نموذج Hailo وتكوين المعالجة اللاحقة مخصصان لرأس الاكتشاف. يجب أن يجعل تطبيق model.export(format="hailo") المباشر في المستقبل تصدير Hailo يبدو كأي تنسيق تصدير آخر في Ultralytics، مع دعم للمهام مقيد برأس النموذج وتوافق مترجم Hailo بدلاً من خطوات سير العمل الخارجية.

المهمةوجهة التصدير المباشر لـ Hailoملاحظات
اكتشاف الكائنات✅ الوجهة الأساسيةيجب أن يكون مسار التصدير المباشر الأول لـ YOLOv8 وYOLO11 وYOLO26 مخصصاً للاكتشاف.
تجزئة المثيلات✅ الوجهةتتطلب عمليات التجزئة في YOLOv8 وYOLO11 وYOLO26 معالجة مخرجات القناع والتحقق منها بشكل خاص للمهمة.
التجزئة الدلالية⚠️ تحققتحتاج التجزئة الدلالية في YOLO26 إلى مترجم مخصص ومسار للتحقق من المخرجات.
تقدير الوضع⚠️ تحققتتطلب الوضعية (Pose) معالجة مخرجات النقاط الرئيسية بخلاف مسار NMS للاكتشاف.
OBB Detection⚠️ تحققتتطلب OBB معالجة مخرجات الصناديق الدوارة بخلاف مسار NMS القياسي للاكتشاف.
التصنيف⚠️ تحققيحتوي التصنيف على رأس مخرجات أبسط، ولكنه لا يزال يحتاج إلى تجميع Hailo والتحقق من وقت التشغيل.

إلى أن يتم تنفيذ التصدير المباشر لـ Hailo في Ultralytics، يتم توثيق سير عمل ONNX-to-HEF اليدوي أدناه فقط.

Link to this sectionإصدارات Hailo SDK#

يجب أن يأخذ التصدير المباشر لـ Hailo في الاعتبار تقسيم أجهزة Hailo وإصدارات SDK الخاصة بها:

  • Hailo-8 و Hailo-8L: استخدم Hailo Dataflow Compiler v3.x. هذا هو المسار ذو الصلة لنشر Raspberry Pi AI Kit و 13 TOPS AI HAT+.
  • Hailo-10 و Hailo-15: استخدم Hailo Dataflow Compiler v5.x.

يؤثر تقسيم الإصدار هذا على واجهات برمجة تطبيقات المترجم، والمعماريات المدعومة، وتوافق ملفات HEF المولدة، وقيم hw_arch التي يجب أن يعرضها المصدّر المباشر. لا ينبغي التعامل مع دعم المهام على جيل أجهزة Hailo واحد كدعم على جيل آخر دون التحقق من إصدار DFC المستهدف و hw_arch.

Link to this sectionملاحظات التوافق#

يعتمد توافق تصدير Hailo على رأس النموذج، وحجم صورة الإدخال، وعدد الفئات، ومعمارية Hailo، وبرنامج النموذج المُنشأ (.alls)، وتكوين المعالجة اللاحقة. التكوينات الثابتة ليست قوالب عالمية. على سبيل المثال، فإن JSON الخاص بـ NMS الذي تم إنشاؤه لنموذج YOLO11n المكون من 80 فئة COCO ليس صحيحاً لنموذج مخصص مكون من 3 فئات أو لـ imgsz ثابت مختلف.

النطاقالدعم المتوقعملاحظات
اكتشاف YOLOv8 / YOLO11✅ جيدرأس اكتشاف مشترك ومنفصل؛ لا تزال توجيهات .alls، وعقد النهاية، وتكوين NMS بحاجة إلى مطابقة الرسم البياني المُصدّر و imgsz الثابت.
كشف YOLOv8 / YOLO11 مخصص✅ ممكنيتطلب تكوين NMS لكل نموذج يتم إنشاؤه بناءً على عدد الفئات، والخطوات (strides)، وتخطيط رأس الاكتشاف؛ لن تتطابق ملفات JSON الثابتة.
اكتشاف YOLO26✅ الوجهةتحتاج المعمارية الخالية من NMS إلى مسار منفصل للمترجم/المعالجة اللاحقة؛ لا تعد استخدام سير عمل NMS لـ YOLO11/YOLOv8 أدناه مع YOLO26.
تجزئة المثيل في YOLO26✅ الوجهةتحتاج إلى معالجة مخرجات القناع والتحقق من الدقة الخاصة بتجزئة YOLO26.
YOLO26 التجزئة الدلالية، الوضعية، OBB، التصنيف⚠️ بحثتحتاج هذه المهام إلى مترجم مخصص والتحقق من وقت التشغيل قبل أن يتم الإعلان عنها كمدعومة مباشرة.
أحجام صور ديناميكية أو عشوائية❌ غير مدعوميستخدم تجميع Hailo شكل إدخال ثابت؛ يجب أن تتطابق إعدادات .alls والمعالجة اللاحقة مع imgsz المُصدّر.

Link to this sectionالتثبيت#

Link to this sectionالخطوة 1: تثبيت Ultralytics#

pip install ultralytics

Link to this sectionالخطوة 2: تثبيت Hailo DFC SDK#

يعتبر Hailo DFC مطلوباً للتحليل والتحسين والتجميع. قم بتنزيل ملف Python wheel من Hailo Developer Zone (يتطلب تسجيلاً مجانياً) وقم بتثبيته:

pip install /path/to/hailo_dataflow_compiler-*.whl
ملاحظة

تتطلب حزمة Hailo DFC SDK جهاز Linux x86_64. لا يمكن تنفيذ التصدير والتجميع على أجهزة ARM مثل Raspberry Pi. انسخ ملف .hef الناتج إلى جهازك الذي يعمل بنظام Hailo للنشر باستخدام HailoRT.

Link to this sectionمثال على تصدير YOLO11n HEF#

يقوم النص البرمجي أدناه بتجميع نموذج كشف YOLO11n من .pt إلى .hef بحجم إدخال ثابت يبلغ 640 بكسل. يتم التصدير إلى ONNX باستخدام Ultralytics، ثم التجميع باستخدام Hailo DFC باستخدام COCO128 كمجموعة بيانات معايرة صغيرة.

قبل تشغيل البرنامج النصي، قدم ملف NMS JSON الخاص بـ Hailo يطابق بدقة رسم التصدير الخاص بـ YOLO11n، وعدد الفئات، والخطوات، وحجم الإدخال الثابت. أعد استخدام هذا البرنامج النصي كنقطة بداية معروفة لـ YOLO11n؛ تحتاج النماذج المخصصة إلى عقد نهاية مطابقة، وتوجيهات .alls، وإعدادات NMS.

يستخدم YOLO26 مسار Hailo مختلف

نماذج YOLO26 خالية من NMS. يحتاج مصدر Ultralytics Hailo المباشر إلى مسار مخصص لتجميع YOLO26 والمعالجة اللاحقة للاكتشاف أو تجزئة المثيل بدلاً من مثال NMS لـ YOLO11 أدناه.

المسار الكامل
import ast
import random
from pathlib import Path

import numpy as np
import onnx
from hailo_sdk_client import ClientRunner
from PIL import Image

from ultralytics import YOLO
from ultralytics.data.utils import check_det_dataset
from ultralytics.utils import DATASETS_DIR, YAML

# Configuration
MODEL = "yolo11n"
HW_ARCH = "hailo8"  # hailo8 | hailo8l | hailo15h
IMGSZ = 640
CALIB_IMAGES = 128
NMS_CONFIG = "yolo11n_nms_config.json"  # Download or generate for your exact model.
OUT_DIR = Path(f"{MODEL}_hailo_model")  # deploy folder (mirrors Ultralytics <model>_<format>_model exports)
OUT_DIR.mkdir(exist_ok=True)

# YOLO11 detection head end nodes. See "Supported Models and End Nodes" for YOLOv8 and other families.
END_NODES = [
    "/model.23/cv2.0/cv2.0.2/Conv",
    "/model.23/cv3.0/cv3.0.2/Conv",
    "/model.23/cv2.1/cv2.1.2/Conv",
    "/model.23/cv3.1/cv3.1.2/Conv",
    "/model.23/cv2.2/cv2.2.2/Conv",
    "/model.23/cv3.2/cv3.2.2/Conv",
]

# Step 1: Export to ONNX, then move it into the deploy folder to keep the working directory tidy
model = YOLO(f"{MODEL}.pt")
onnx_path = Path(model.export(format="onnx", imgsz=IMGSZ, opset=11))
onnx_path = onnx_path.rename(OUT_DIR / onnx_path.name)

# Copy the metadata Ultralytics embedded in the ONNX into the standard metadata.yaml sidecar.
# The HEF stores no class names, so inference reads them from this file.
meta = {p.key: p.value for p in onnx.load(onnx_path, load_external_data=False).metadata_props}
for k in ("stride", "batch", "channels"):
    if k in meta:
        meta[k] = int(meta[k])
for k in ("imgsz", "names", "args", "end2end"):
    if k in meta:
        meta[k] = ast.literal_eval(meta[k])
YAML.save(OUT_DIR / "metadata.yaml", meta)

# Step 2: Parse ONNX with Hailo DFC
# The DFC prints the detected end nodes after parsing; use them if unsure.
runner = ClientRunner(hw_arch=HW_ARCH)
runner.translate_onnx_model(str(onnx_path), end_node_names=END_NODES)

# Step 3: Load model script (normalization + HailoRT NMS)
# The conv layer names are generated by DFC and can change for other model sizes/families.
model_script = (
    "normalization1 = normalization([0.0, 0.0, 0.0], [255.0, 255.0, 255.0])\n"
    "change_output_activation(conv54, sigmoid)\n"
    "change_output_activation(conv65, sigmoid)\n"
    "change_output_activation(conv80, sigmoid)\n"
    f'nms_postprocess("{NMS_CONFIG}", meta_arch=yolov8, engine=cpu)\n'
    "allocator_param(width_splitter_defuse=disabled)"
)
runner.load_model_script(model_script)

# Step 4: Build calibration dataset (auto-downloads COCO128)
check_det_dataset("coco128.yaml")
calib_dir = DATASETS_DIR / "coco128" / "images" / "train2017"
image_files = list(calib_dir.glob("*.jpg")) + list(calib_dir.glob("*.png"))
if not image_files:
    raise FileNotFoundError(f"No calibration images found in {calib_dir}")

calibset = np.zeros((CALIB_IMAGES, IMGSZ, IMGSZ, 3), dtype=np.float32)
for i in range(CALIB_IMAGES):
    img = Image.open(random.choice(image_files)).convert("RGB").resize((IMGSZ, IMGSZ))
    calibset[i] = np.array(img, dtype=np.float32)

# Step 5: Optimize and quantize
runner.optimize(calibset)
runner.save_har(str(OUT_DIR / f"{MODEL}.o.har"))  # optional intermediate HAR

# Step 6: Compile to HEF
hef = runner.compile()
hef_path = OUT_DIR / f"{MODEL}.hef"
with open(hef_path, "wb") as f:
    f.write(hef)

# Note: the Hailo SDK writes *.log files (acceleras.log, allocator.log, hailo_sdk.client.log,
# hailo_sdk.core.log) to the working directory. They are diagnostic scratch, safe to ignore or delete.
print(f"Compiled HEF saved to: {hef_path}")

ينظم برنامج التصدير الملحقات والسجلات كما يلي:

  • مجلد النشر: يتم حفظ الملحقات في yolo11n_hailo_model/ مما يعكس تخطيط <model>_<format>_model/ القياسي المستخدم في عمليات تصدير Ultralytics الأخرى.
  • الملفات المطلوبة: الملفان اللازمان للنشر هما yolo11n.hef المترجم وmetadata.yaml المصاحب له.
  • البيانات الوصفية: يحتوي metadata.yaml على حقول أساسية (names وimgsz وtask وstride إلخ) مستخرجة من البيانات الوصفية لـ ONNX. تقوم نصوص الاستدلال بتحميل أسماء الفئات من هذا الملف نظرًا لأن تنسيق HEF لا يخزنها.
  • الملفات الوسيطة: يحتوي مجلد التصدير أيضًا على نقاط التحقق الوسيطة yolo11n.onnx وyolo11n.o.har.
  • ملفات السجل: يُنشئ Hailo SDK العديد من سجلات التشخيص (على سبيل المثال، acceleras.log وallocator.log وhailo_sdk.client.log وhailo_sdk.core.log) في دليل العمل؛ يمكن تجاهل هذه الملفات أو حذفها بأمان.
  • Raspberry Pi AI Kit: بالنسبة لهذا الجهاز المحدد، تأكد من تعيين HW_ARCH = "hailo8l" قبل تشغيل خطوة الترجمة.

Link to this sectionتفصيل خطوة بخطوة#

يعمل البرنامج النصي الكامل أعلاه من البداية إلى النهاية. يشرح هذا القسم ما تقوم به كل مرحلة والتفاصيل الخاصة بالنموذج التي يجب مراعاتها عند تكييفه مع نموذجك الخاص.

Link to this sectionالخطوة 1: التصدير إلى ONNX وحفظ البيانات الوصفية#

تقوم Ultralytics بتصدير نموذجك المدرب إلى تنسيق ONNX، والذي يستقبله Hailo DFC كمدخل. توفر opset=11 توافقية واسعة مع DFC، ويتم نقل ملف ONNX إلى مجلد النشر yolo11n_hailo_model/ (مما يعكس تخطيط <model>_<format>_model/ لعمليات تصدير Ultralytics الأخرى) للحفاظ على ترتيب دليل العمل.

لا يقوم HEF بتخزين أي أسماء فئات، لذا يتم نسخ البيانات الوصفية التي تضمنها Ultralytics في ONNX إلى ملف metadata.yaml مصاحب قياسي بجانبه. هذا هو نفس ملف metadata.yaml الذي تنتجه تنسيقات التصدير الأخرى (names وimgsz وtask وstride والمزيد)، ويقوم الاستدلال بقراءة أسماء الفئات منه، لذا يعمل سير العمل للنماذج المخصصة دون الحاجة إلى ترميز أي تسميات برمجياً.

Link to this sectionالخطوة 2: تحليل نموذج ONNX#

تقوم runner.translate_onnx_model(...) بتحويل رسم ONNX البياني إلى تمثيل HAR الوسيط الخاص بـ Hailo. تخبر قائمة end_node_names نظام DFC بمكان قطع الرسم البياني قبل NMS حتى يتمكن Hailo من إرفاق معالجة الأجهزة اللاحقة الخاصة به.

العثور على العقد النهائية

يطبع DFC اقتراحاً بعد التحليل:

[info] In order to use HailoRT post-processing capabilities, these end node names should be used: ...

انسخ أسماء العقد تلك إذا لم تكن متأكداً من أي منها تستخدم، أو إذا كنت تعمل مع بنية مخصصة أو أقل شيوعاً.

Link to this sectionالخطوة 3: تحميل نص النموذج#

يقوم نص النموذج (.alls) بتهيئة تطبيع الإدخال، وتنشيط المخرجات، والمعالجة اللاحقة NMS. ينطبق إعداد meta_arch=yolov8 على كل من YOLOv8 و YOLO11 نظراً لمشاركتهما نفس تخطيط رأس الكشف.

MODEL = "yolo11n"
NMS_CONFIG = "yolo11n_nms_config.json"
model_script = (
    "normalization1 = normalization([0.0, 0.0, 0.0], [255.0, 255.0, 255.0])\n"
    "change_output_activation(conv54, sigmoid)\n"
    "change_output_activation(conv65, sigmoid)\n"
    "change_output_activation(conv80, sigmoid)\n"
    f'nms_postprocess("{NMS_CONFIG}", meta_arch=yolov8, engine=cpu)\n'
    "allocator_param(width_splitter_defuse=disabled)"
)
runner.load_model_script(model_script)
ملاحظة

يتم تعيين أسماء طبقات change_output_activation (conv54، conv65، conv80) بواسطة DFC أثناء التحليل وهي خاصة بكل نموذج. إذا كنت تقوم بتجميع حجم أو معمارية نموذج مختلفة، فتحقق من مخرجات DFC لمعرفة الأسماء الصحيحة أو أنشئ توجيهات .alls من الرسم البياني المُصدّر.

ملف NMS_CONFIG خاص أيضاً بكل نموذج. استخدم تكويناً يطابق النموذج المُصدّر الخاص بك تماماً.

يقوم engine=cpu بتشغيل NMS عبر HailoRT على وحدة المعالجة المركزية المضيفة. استخدم engine=nn_core فقط لمجموعات النماذج/النصوص التي توثق Hailo أنها مدعومة من قبل الأجهزة المستهدفة وإصدار SDK.

احذف سطر nms_postprocess إذا كنت تفضل تشغيل NMS بالكامل في كود تطبيقك. إذا قمت بذلك، فقم بتحديث محلل الاستدلال لأن HEF سيخرج مصفوفات (tensors) رأس الكشف الأولية بدلاً من اكتشافات NMS المجمعة.

Link to this sectionالخطوة 4: بناء مجموعة بيانات المعايرة#

تتطلب كمية INT8 مجموعة تمثيلية من الصور مكدسة في مصفوفة (N, imgsz, imgsz, 3) بنوع float32. يستخدم البرنامج النصي COCO128، الذي تقوم Ultralytics بتنزيله تلقائيًا عبر check_det_dataset.

نصيحة

استخدم 64 صورة على الأقل للمعايرة. تعمل المزيد من الصور عموماً على تحسين جودة التكميم. للحصول على أفضل النتائج، استخدم صوراً من مجال النشر الخاص بك بدلاً من COCO128.

Link to this sectionالخطوة 5: التحسين والتكميم#

تطبق runner.optimize(calibset) الضبط الدقيق المدرك للكمية وتحليل ضجيج الطبقة، ثم تكتب runner.save_har(...) نقطة تحقق وسيطة اختيارية. يوصى بشدة باستخدام GPU؛ فبدونه قد تستغرق هذه الخطوة عدة ساعات.

Link to this sectionالخطوة 6: التجميع إلى HEF#

تنتج runner.compile() ملف HEF النهائي، المكتوب في yolo11n_hailo_model/yolo11n.hef. وهو الآن موجود بجانب ملف metadata.yaml الخاص به، جاهز للنسخ إلى الجهاز للاستدلال.

Link to this sectionالنماذج المدعومة والعقد النهائية#

بالنسبة لنماذج الكشف، تحدد end_node_names مخرجات رأس الكشف في ONNX التي يجب على Hailo تجميعها قبل إرفاق معالجة NMS اللاحقة. تختلف هذه الأسماء حسب البنية ويمكن أن تتغير عند تغير الرسم البياني المصدر.

تنطبق أمثلة عقدة النهاية أدناه على نماذج اكتشاف YOLOv8 وYOLO11 التي تستخدم المعالجة اللاحقة لـ NMS بأسلوب YOLOv8 الخاص بـ Hailo. YOLO26 خالٍ من NMS ولا يستخدم تكوين NMS الخاص بـ YOLO11 هذا.

Link to this sectionYOLO11 و YOLOv8#

تتشارك YOLO11 و YOLOv8 نفس رأس الكشف المفصول. يختلف فهرس الطبقة بواحد بين العائلتين:

عائلة النموذجطبقة رأس الكشفنمط العقدة النهائية
YOLO11 (الكل)model.23/model.23/cv2.0/cv2.0.2/Conv (6 عقد)
YOLOv8 (الكل)model.22/model.22/cv2.0/cv2.0.2/Conv (6 عقد)

عقد نهاية YOLO11 (جميع الأحجام: n, s, m, l, x):

END_NODES = [
    "/model.23/cv2.0/cv2.0.2/Conv",
    "/model.23/cv3.0/cv3.0.2/Conv",
    "/model.23/cv2.1/cv2.1.2/Conv",
    "/model.23/cv3.1/cv3.1.2/Conv",
    "/model.23/cv2.2/cv2.2.2/Conv",
    "/model.23/cv3.2/cv3.2.2/Conv",
]

عقد نهاية YOLOv8 (جميع الأحجام: n, s, m, l, x):

END_NODES = [
    "/model.22/cv2.0/cv2.0.2/Conv",
    "/model.22/cv3.0/cv3.0.2/Conv",
    "/model.22/cv2.1/cv2.1.2/Conv",
    "/model.22/cv3.1/cv3.1.2/Conv",
    "/model.22/cv2.2/cv2.2.2/Conv",
    "/model.22/cv3.2/cv3.2.2/Conv",
]

Link to this sectionهياكل أخرى#

بالنسبة لبنى الكشف الأخرى، قم بتشغيل خطوة التحليل بدون end_node_names أولاً، واقرأ العقد المقترحة من مخرجات سجل DFC، ثم أعد التشغيل مع تلك العقد:

# First pass: let the DFC suggest end nodes
runner = ClientRunner(hw_arch=HW_ARCH)
runner.translate_onnx_model(f"{MODEL}.onnx")
# Check the printed log for: "[info] In order to use HailoRT post-processing..."

لدعم Ultralytics المباشر، يجب إنشاء توجيهات .alls وإعدادات المعالجة اللاحقة هذه أو اختيارها بواسطة المصدّر بدلاً من مطالبة المستخدمين بتجميعها يدوياً.

Link to this sectionبنى الأجهزة المدعومة#

البنية الهندسيةالجهازذروة الحوسبة (مواصفات البائع)حالة الاستخدام الشائعة
hailo8Hailo-826 TOPSبطاقة مسرع Hailo
hailo8lHailo-8L13 TOPSRaspberry Pi AI Kit
hailo15hHailo-15H20 TOPSأجهزة Hailo-15 المستهدفة

اضبط HW_ARCH في البرنامج النصي ليتوافق مع جهازك المستهدف قبل التجميع.

Link to this sectionتشغيل الاستنتاج على أجهزة Hailo#

بمجرد اكتمال الترجمة، انسخ مجلد yolo11n_hailo_model/ بالكامل (ملف .hef بالإضافة إلى metadata.yaml الخاص به) إلى جهازك الذي يعمل بنظام Hailo وقم بتشغيل الاستدلال باستخدام إما HailoRT Python API (حزمة hailo_platform) أو، على Raspberry Pi، أداة المساعدة picamera2 Hailo (غلاف لـ HailoRT). كلاهما معروض في علامات التبويب أدناه. إن الاحتفاظ بالملفين معًا يسمح للنصوص البرمجية أدناه بقراءة أسماء الفئات من metadata.yaml الموجود بجوار HEF. على عكس خطوات تصدير DFC، يتم تشغيل الاستدلال مباشرة على جهاز الحافة.

ملاحظة

كود الاستنتاج أدناه يعمل على الجهاز الذي يعمل بنظام Hailo (على سبيل المثال Raspberry Pi + AI Kit)، وليس على جهاز x86 المستخدم للتجميع.

Link to this sectionالخطوة 1: تثبيت HailoRT على الجهاز#

على الجهاز المستهدف، قم بتثبيت HailoRT وروابط Python. بالنسبة لمستخدمي Raspberry Pi AI Kit و AI HAT+، يقوم دليل برنامج Raspberry Pi AI الرسمي بتثبيت HailoRT، وبرنامج تشغيل الجهاز، وروابط Python باستخدام:

sudo apt install dkms
sudo apt install hailo-all
sudo reboot

بالنسبة لأجهزة Hailo غير التابعة لـ Raspberry Pi، قم بتثبيت حزمة HailoRT التي تتوافق مع جهازك وبرنامج التشغيل وإصدار SDK من منطقة مطوري Hailo.

تستخدم أجهزة AI HAT+ 2 حزمة Raspberry Pi مختلفة (hailo-h10-all) وسير عمل Hailo-10H. اتبع دليل برنامج Raspberry Pi AI لهذا الجيل من الأجهزة.

Link to this sectionالخطوة 2: فحص سريع#

قبل تشغيل استنتاج Python، تأكد من التعرف على جهاز Hailo:

hailortcli fw-control identify

يجب أن ترى نوع الجهاز وإصدار البرنامج الثابت والرقم التسلسلي مطبوعين.

Executing on device: 0001:01:00.0
Identifying board
Control Protocol Version: 2
Firmware Version: 4.23.0 (release,app,extended context switch buffer)
Logger Version: 0
Board Name: Hailo-8
Device Architecture: HAILO8

Link to this sectionالخطوة 3: تشغيل الاستنتاج#

The scripts below run object detection with the compiled HEF file. Both tabs accept the same --source inputs (an image, a video, a USB webcam index, or csi for the Raspberry Pi Camera Module) and differ only in the inference API: the Hailo SDK tab uses the low-level hailo_platform API (portable, minimal dependencies), while the picamera2 tab uses the Raspberry Pi picamera2 Hailo helper. Images and videos are written to an annotated file; webcam and CSI streams display in a live window.

يعمل مسار HailoRT الأصلي للمورد على أي منصة تحتوي على جهاز Hailo ولا يحتاج إلى تبعيات إضافية. قم بتمرير --source لمسار صورة، أو مسار فيديو، أو مؤشر كاميرا ويب (على سبيل المثال 0) لالتقاط USB/V4L2 المباشر، أو csi لوحدة كاميرا Raspberry Pi. يتطلب خيار CSI تثبيت picamera2، نظرًا لأن نظام تشغيل Raspberry Pi الحديث يوجه الكاميرا عبر libcamera بدلاً من جهاز V4L2 عادي.

import argparse
from pathlib import Path

import cv2
import numpy as np
import yaml
from hailo_platform import (
    HEF,
    ConfigureParams,
    FormatType,
    HailoStreamInterface,
    InferVStreams,
    InputVStreamParams,
    OutputVStreamParams,
    VDevice,
)
from tqdm import tqdm

IMAGE_EXTS = {".jpg", ".jpeg", ".png", ".bmp", ".webp", ".tif", ".tiff"}

def parse_and_draw(per_class, frame, conf, names):
    """Draw HailoRT NMS detections (grouped by class, normalized [0, 1] coords) onto a BGR frame."""
    h, w = frame.shape[:2]
    for cls_idx, cls_dets in enumerate(per_class):
        for det in cls_dets:
            score = float(det[4])
            if score < conf:
                continue
            # HailoRT NMS returns normalized [0, 1] coords as (y1, x1, y2, x2)
            y1, x1, y2, x2 = det[:4]
            x1, y1, x2, y2 = int(x1 * w), int(y1 * h), int(x2 * w), int(y2 * h)
            label = f"{names[cls_idx]} {score:.2f}"
            cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
            cv2.putText(frame, label, (x1 + 2, y1 + 15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1, cv2.LINE_AA)

def preprocess(frame, imgsz):
    """BGR frame -> (1, imgsz, imgsz, 3) float32 in 0-255 (HEF normalizes internally)."""
    rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    resized = cv2.resize(rgb, (imgsz, imgsz))
    return np.expand_dims(resized.astype(np.float32), axis=0)

def csi_frames(width=1280, height=720):
    """Yield BGR frames from the Pi CSI Camera Module via picamera2."""
    from picamera2 import Picamera2

    picam2 = Picamera2()
    # picamera2 "RGB888" is BGR-ordered in memory, so it drops straight into OpenCV
    picam2.configure(picam2.create_preview_configuration(main={"size": (width, height), "format": "RGB888"}))
    picam2.start()
    try:
        while True:
            yield picam2.capture_array("main")  # BGR
    finally:
        picam2.stop()
        picam2.close()

def cv2_frames(src):
    """Yield BGR frames from a video file or USB/V4L2 webcam via OpenCV."""
    cap = cv2.VideoCapture(src)
    if not cap.isOpened():
        raise RuntimeError(f"Could not open source {src}")
    total = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))  # 0 for live webcams
    pbar = tqdm(total=total, desc="Processing video", unit="frame") if total > 0 else None
    try:
        while True:
            ok, frame = cap.read()  # BGR
            if not ok:
                break
            yield frame
            if pbar is not None:
                pbar.update(1)
    finally:
        if pbar is not None:
            pbar.close()
        cap.release()

def open_source(source):
    """Yield (frame, kind) pairs where kind is 'image', 'video', or 'stream'."""
    if source == "csi":
        yield from ((f, "stream") for f in csi_frames())
    elif source.isdigit():
        yield from ((f, "stream") for f in cv2_frames(int(source)))
    elif Path(source).suffix.lower() in IMAGE_EXTS:
        frame = cv2.imread(source)
        if frame is None:
            raise FileNotFoundError(f"Could not read image {source}")
        yield frame, "image"
    else:
        yield from ((f, "video") for f in cv2_frames(source))

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Hailo YOLO inference (image, video, webcam, or CSI camera)")
    parser.add_argument("-m", "--model", default="yolo11n_hailo_model/yolo11n.hef", help="Path to the HEF model.")
    parser.add_argument("--source", default="0", help="Image/video path, webcam index (e.g. 0), or 'csi'.")
    parser.add_argument("--imgsz", type=int, default=640)
    parser.add_argument("--conf", type=float, default=0.25)
    args = parser.parse_args()

    # Load class names from metadata.yaml saved next to the HEF during compilation (keyed by class index)
    with open(Path(args.model).parent / "metadata.yaml") as f:
        names = yaml.safe_load(f)["names"]

    # Configure the device and network group ONCE
    hef = HEF(args.model)
    target = VDevice(VDevice.create_params())
    configure_params = ConfigureParams.create_from_hef(hef, interface=HailoStreamInterface.PCIe)
    network_group = target.configure(hef, configure_params)[0]
    network_group_params = network_group.create_params()
    input_vstreams_params = InputVStreamParams.make(network_group, quantized=False, format_type=FormatType.FLOAT32)
    output_vstreams_params = OutputVStreamParams.make(network_group, quantized=False, format_type=FormatType.FLOAT32)
    input_name = hef.get_input_vstream_infos()[0].name

    writer = None  # lazily created for video output

    # Keep the pipeline and activation OPEN across frames (re-opening per frame is slow)
    with InferVStreams(network_group, input_vstreams_params, output_vstreams_params) as pipeline:
        with network_group.activate(network_group_params):
            try:
                for frame, kind in open_source(args.source):
                    raw = pipeline.infer({input_name: preprocess(frame, args.imgsz)})
                    parse_and_draw(raw[next(iter(raw.keys()))][0], frame, args.conf, names)

                    if kind == "image":
                        cv2.imwrite("output.jpg", frame)
                        print("Saved output.jpg")
                    elif kind == "video":
                        if writer is None:
                            h, w = frame.shape[:2]
                            writer = cv2.VideoWriter("output.mp4", cv2.VideoWriter_fourcc(*"mp4v"), 30, (w, h))
                        writer.write(frame)
                    else:  # live stream
                        cv2.imshow("Hailo YOLO", frame)
                        if cv2.waitKey(1) & 0xFF == ord("q"):
                            break
            finally:
                if writer is not None:
                    writer.release()
                    print("Saved output.mp4")
                cv2.destroyAllWindows()

قم بتشغيله مقابل أي مصدر (يتم حفظ الصور باسم output.jpg، ويتم حفظ مقاطع الفيديو باسم output.mp4، وتظهر البثوث المباشرة في نافذة، اضغط على q للخروج):

python hailo_infer.py --source bus.jpg  # single image
python hailo_infer.py --source clip.mp4 # video file
python hailo_infer.py --source 0        # USB webcam, live
python hailo_infer.py --source csi      # Raspberry Pi Camera Module
نصيحة

يفترض تنسيق مخرجات الاكتشاف أنه تم تجميع HEF باستخدام nms_postprocess في برنامج .alls النصي. إذا قمت بالتجميع بدون NMS، فإن المخرجات الأولية هي عبارة عن 6 موترات لرأس الاكتشاف ويجب عليك تشغيل NMS في تطبيقك بشكل منفصل.

Link to this sectionاستنتاج الفيديو باستخدام TAPPAS#

بالنسبة لخطوط أنابيب الفيديو ذات الإنتاجية العالية، توفر TAPPAS عناصر GStreamer التي تقوم ببث الفيديو عبر شريحة Hailo في الوقت الفعلي:

MODEL=yolo11n
gst-launch-1.0 filesrc location=video.mp4 ! decodebin ! \
  hailonet hef-path=${MODEL}.hef ! \
  hailofilter function-name=yolov8 ! \
  hailooverlay ! autovideosink

اطلع على وثائق TAPPAS للحصول على خيارات تكوين خط الأنابيب الكاملة.

Link to this sectionملخص#

غطى هذا الدليل سير العمل الكامل لتصدير نماذج اكتشاف Ultralytics YOLO إلى تنسيق Hailo HEF:

  1. التصدير إلى ONNX باستخدام Ultralytics (model.export(format="onnx")).
  2. تحليل نموذج ONNX باستخدام Hailo DFC وتحديد العقد النهائية لرأس الاكتشاف.
  3. تكوين التطبيع و NMS عبر برنامج نصي للنموذج.
  4. التقدير الكمي باستخدام مجموعة بيانات معايرة (COCO128 عبر Ultralytics).
  5. التجميع إلى ملف .hef جاهز لـ Hailo-8 أو Hailo-8L أو Hailo-15.

لمزيد من التفاصيل، راجع Hailo Developer Zone و وثائق Hailo. بالنسبة لوجهات تصدير Ultralytics الأخرى، راجع أدلة ONNX و OpenVINO و TensorRT و NCNN و TFLite Edge TPU و RKNN و Sony IMX500 و Qualcomm QNN ذات الصلة. لمقارنة سرعة ودقة النموذج المُصدّر عبر التنسيقات، استخدم وضع المعيار القياسي (Benchmark mode). للحصول على القائمة الكاملة للتنسيقات والخيارات، قم بزيارة وثائق وضع التصدير (Export mode) و صفحة دليل التكامل.

Link to this sectionالأسئلة الشائعة#

Link to this sectionما هي أجهزة Hailo المدعومة؟#

يدعم Hailo DFC كلاً من Hailo-8 (hailo8) و Hailo-8L (hailo8l) و Hailo-15H (hailo15h). راجع جدول بنى الأجهزة المدعومة للحصول على قيمة HW_ARCH المطابقة.

Link to this sectionما هي نماذج Ultralytics التي يمكن تصديرها؟#

يركز هذا الدليل على نماذج الاكتشاف. راجع المهام المدعومة لنطاق المهام، و ملاحظات التوافق لحدود توافق النموذج، و النماذج المدعومة والعقد النهائية للحصول على أمثلة للعقد النهائية في YOLO11 و YOLOv8.

Link to this sectionلماذا يستخدم برنامج النموذج meta_arch=yolov8 لـ YOLO11؟#

يستخدم YOLO11 نفس بنية رأس الاكتشاف المنفصلة مثل YOLOv8. يستخدم Hailo DFC meta_arch=yolov8 لتكوين NMS لكلتا عائلتي النماذج.

Link to this sectionهل أحتاج إلى GPU لخطوة التحسين؟#

يوصى بشدة باستخدام GPU للضبط الدقيق الواعي بالتقدير الكمي في runner.optimize(). بدون GPU، تستمر العملية في العمل ولكنها تكون أبطأ بشكل ملحوظ (عدة ساعات مقابل 10-20 دقيقة تقريباً باستخدام GPU).

Link to this sectionكيف يمكنني العثور على العقد النهائية الصحيحة لنموذجي؟#

قم بتشغيل runner.translate_onnx_model(...) دون تحديد end_node_names، ثم استخدم عقد رأس الاكتشاف المقترحة التي يطبعها DFC. راجع بنى أخرى للحصول على أمر المثال.

Link to this sectionأين يمكنني الحصول على Hailo DFC SDK؟#

تتوفر حزمة Python الخاصة بـ Hailo DFC SDK من Hailo Developer Zone. بالنسبة لمصدّر Ultralytics Hailo المباشر، يجب إنشاء برنامج النموذج وتكوين المعالجة اللاحقة أو اختيارهما داخل سير عمل التصدير.

التعليقات