Skip to main content

المعالجة المسبقة المتسارعة بـ GPU باستخدام NVIDIA DALI

مقدمة

عند نشر نماذج Ultralytics YOLO النماذج في مرحلة الإنتاج، المعالجة المسبقة غالباً ما تصبح عنق الزجاجة. بينما يمكن لـ TensorRT تشغيل الاستدلال النموذج في بضعة أجزاء من الألف من الثانية، يمكن أن تستغرق المعالجة المسبقة المعتمدة على CPU (تغيير الحجم، الحشو، التطبيع) ما بين 2-10 مللي ثانية لكل صورة، خاصة عند الدقات العالية. NVIDIA DALI (مكتبة تحميل البيانات) تحل هذه المشكلة عن طريق نقل مسار المعالجة المسبقة بالكامل إلى GPU.

يرشدك هذا الدليل خلال بناء مسارات DALI التي تكرر بدقة المعالجة المسبقة لـ Ultralytics YOLO، ودمجها مع model.predict()، ومعالجة تدفقات الفيديو، والنشر الشامل باستخدام Triton Inference Server.

لمن هذا الدليل؟

هذا الدليل مخصص للمهندسين الذين ينشرون نماذج YOLO في بيئات الإنتاج حيث تُعد المعالجة المسبقة بـ CPU عنق زجاجة ملموساً — عادة في عمليات TensorRT على GPUs من NVIDIA، أو مسارات الفيديو ذات الإنتاجية العالية، أو Triton Inference Server الإعدادات. إذا كنت تقوم بتشغيل الاستدلال القياسي مع model.predict() وليس لديك عنق زجاجة في المعالجة المسبقة، فإن مسار CPU الافتراضي يعمل بشكل جيد.

ملخص سريع
  • بناء مسار DALI؟ استخدم fn.resize(mode="not_larger") + fn.crop(out_of_bounds_policy="pad") + fn.crop_mirror_normalize لتكرار المعالجة المسبقة letterbox الخاصة بـ YOLO على GPU.
  • الدمج مع Ultralytics؟ مرر مخرجات DALI كـ torch.Tensor إلى model.predict() — ستتخطى Ultralytics المعالجة المسبقة للصور تلقائياً.
  • النشر باستخدام Triton؟ استخدم خلفية DALI مع مجموعة TensorRT لمعالجة مسبقة بدون استهلاك CPU.

لماذا تستخدم DALI لمعالجة YOLO المسبقة

في مسار استدلال YOLO النموذجي، تعمل خطوات المعالجة المسبقة على CPU:

  1. فك ترميز الصورة (JPEG/PNG)
  2. تغيير الحجم مع الحفاظ على نسبة العرض إلى الارتفاع
  3. الحشو للوصول إلى الحجم المستهدف (letterbox)
  4. التطبيع لقيم البكسل من [0, 255] إلى [0, 1]
  5. تحويل التنسيق من HWC إلى CHW

مع DALI، تعمل كل هذه العمليات على GPU، مما يلغي عنق زجاجة CPU. هذا مفيد بشكل خاص عندما:

السيناريولماذا يساعد DALI
استدلال سريع بـ GPUTensorRT المحركات ذات استدلال بأقل من مللي ثانية تجعل المعالجة المسبقة بـ CPU هي التكلفة المهيمنة
مدخلات عالية الدقةتتطلب تدفقات فيديو 1080p و 4K عمليات تغيير حجم مكلفة
نطاق واسع عند نشر النماذج في بيئة الإنتاج، تكون متطلبات الذاكرة وكفاءة التدريب حاسمة تماماً مثل سرعة الاستدلال. نماذج Ultralytics، وخاصة YOLO26، محسنة للغاية لتقليل استخدام ذاكرة CUDA أثناء التدريب. وهذا يسمح للمطورين باستخدام استدلال جانب الخادم يعالج العديد من الصور بالتوازي
أنوية CPU محدودةأجهزة الحافة مثل NVIDIA Jetson، أو خوادم GPU كثيفة مع عدد قليل من أنوية CPU لكل GPU

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

Linux فقط

يدعم NVIDIA DALI نظام Linux فقط. وهو غير متوفر على Windows أو macOS.

قم بتثبيت الحزم المطلوبة:

pip install ultralytics
pip install --extra-index-url https://pypi.nvidia.com nvidia-dali-cuda120

المتطلبات:

  • NVIDIA GPU (قدرة حوسبة 5.0+ / Maxwell أو أحدث)
  • CUDA 11.0+ أو 12.0+
  • Python 3.10-3.14
  • نظام تشغيل Linux

فهم معالجة YOLO المسبقة

قبل بناء مسار DALI، من المفيد فهم ما تفعله Ultralytics بالضبط أثناء المعالجة المسبقة. الفئة الأساسية هي LetterBox في ultralytics/data/augment.py:

from ultralytics.data.augment import LetterBox

letterbox = LetterBox(
    new_shape=(640, 640),  # Target size
    center=True,  # Center the image (pad equally on both sides)
    stride=32,  # Stride alignment
    padding_value=114,  # Gray padding (114, 114, 114)
)

مسار المعالجة المسبقة الكامل في ultralytics/engine/predictor.py يقوم بهذه الخطوات:

الخطوةالعمليةوظيفة CPUما يعادل DALI
1تغيير الحجم letterboxcv2.resizefn.resize(mode="not_larger")
2حشو مركزيcv2.copyMakeBorderfn.crop(out_of_bounds_policy="pad")
3BGR → RGBim[..., ::-1]fn.decoders.image(output_type=types.RGB)
4HWC → CHW + تطبيع /255np.transpose + tensor / 255fn.crop_mirror_normalize(std=[255,255,255])

تحافظ عملية letterbox على نسبة العرض إلى الارتفاع عن طريق:

  1. حساب المقياس: r = min(target_h / h, target_w / w)
  2. تغيير الحجم إلى (round(w * r), round(h * r))
  3. حشو المساحة المتبقية باللون الرمادي (114) للوصول إلى الحجم المستهدف
  4. توسيط الصورة بحيث يتم توزيع الحشو بالتساوي على كلا الجانبين

مسار DALI لـ YOLO

استخدم المسار المركزي أدناه كمرجع افتراضي. إنه يطابق سلوك LetterBox(center=True) الخاص بـ Ultralytics، وهو ما يستخدمه استدلال YOLO القياسي.

المسار المركزي (موصى به، يطابق LetterBox الخاص بـ Ultralytics)

هذا الإصدار يكرر بدقة المعالجة المسبقة الافتراضية لـ Ultralytics مع حشو مركزي، مطابقاً لـ LetterBox(center=True):

مسار DALI مع حشو مركزي (موصى به)
import nvidia.dali as dali
import nvidia.dali.fn as fn
import nvidia.dali.types as types

@dali.pipeline_def(batch_size=8, num_threads=4, device_id=0)
def yolo_dali_pipeline_centered(image_dir, target_size=640):
    """DALI pipeline replicating YOLO preprocessing with centered padding.

    Matches Ultralytics LetterBox(center=True) behavior exactly.
    """
    # Read and decode images on GPU
    jpegs, _ = fn.readers.file(file_root=image_dir, random_shuffle=False, name="Reader")
    images = fn.decoders.image(jpegs, device="mixed", output_type=types.RGB)

    # Aspect-ratio-preserving resize
    resized = fn.resize(
        images,
        resize_x=target_size,
        resize_y=target_size,
        mode="not_larger",
        interp_type=types.INTERP_LINEAR,
        antialias=False,  # Match cv2.INTER_LINEAR (no antialiasing)
    )

    # Centered padding using fn.crop with out_of_bounds_policy
    # When crop size > image size, fn.crop centers the image and pads symmetrically
    padded = fn.crop(
        resized,
        crop=(target_size, target_size),
        out_of_bounds_policy="pad",
        fill_values=114,  # YOLO padding value
    )

    # Normalize and convert layout
    output = fn.crop_mirror_normalize(
        padded,
        dtype=types.FLOAT,
        output_layout="CHW",
        mean=[0.0, 0.0, 0.0],
        std=[255.0, 255.0, 255.0],
    )
    return output
متى تكون `fn.pad` كافية؟

إذا كنت لا تحتاج إلى تطابق تام مع LetterBox(center=True)، يمكنك تبسيط خطوة الحشو باستخدام fn.pad(...) بدلاً من fn.crop(..., out_of_bounds_policy="pad"). يقوم هذا المتغير بحشو الحواف اليمنى والسفلية فقط، وهو ما قد يكون مقبولاً لمسارات النشر المخصصة، ولكنه لن يطابق سلوك letterbox المركزي الافتراضي لـ Ultralytics بدقة.

لماذا `fn.crop` للحشو المركزي؟

يقوم عامل fn.pad الخاص بـ DALI بإضافة الحشو إلى الحواف اليمنى والسفلية الحواف فقط. للحصول على حشو مركزي (مطابق لـ LetterBox(center=True) الخاص بـ Ultralytics)، استخدم fn.crop مع out_of_bounds_policy="pad". مع crop_pos_x=0.5 و crop_pos_y=0.5 الافتراضي، يتم توسيط الصورة تلقائياً مع حشو متماثل.

عدم تطابق التنعيم

يقوم عامل fn.resize يفعّل تنعيم الحواف (antialiasing) افتراضياً بـ antialias=True)، بينما cv2.resize مع INTER_LINEAR الخاص بـ أمثلة أساسية للاستخدام لا يطبق تنعيم الحواف. قم دائماً بضبط antialias=False في DALI لمطابقة خط المعالجة (pipeline) على الـ CPU. يؤدي تجاهل ذلك إلى فروقات رقمية طفيفة قد تؤثر على دقة النموذج.

تشغيل خط المعالجة

بناء وتشغيل خط معالجة DALI
# Build and run the pipeline
pipe = yolo_dali_pipeline_centered(image_dir="/path/to/images", target_size=640)
pipe.build()

# Get a batch of preprocessed images
(output,) = pipe.run()

# Convert to numpy or PyTorch tensors
batch_np = output.as_cpu().as_array()  # Shape: (batch_size, 3, 640, 640)
print(f"Output shape: {batch_np.shape}, dtype: {batch_np.dtype}")
print(f"Value range: [{batch_np.min():.4f}, {batch_np.max():.4f}]")

استخدام DALI مع ميزة التنبؤ في Ultralytics

يمكنك تمرير PyTorch مجهز مسبقاً مباشرة إلى model.predict(). عند تمرير torch.Tensor، يتجاوز Ultralytics خطوة معالجة الصور مسبقاً (letterbox، التحويل من BGR إلى RGB، التحويل من HWC إلى CHW، والتطبيع بالقسمة على 255) ويقوم فقط بنقل البيانات إلى الجهاز (device) وتغيير نوع البيانات (dtype casting) قبل إرسالها إلى النموذج.

نظراً لأن Ultralytics لا يملك وصولاً إلى أبعاد الصورة الأصلية في هذه الحالة، يتم إرجاع إحداثيات صناديق الكشف (detection box) ضمن مساحة 640×640 الخاصة بـ letterbox. لتعيينها مجدداً إلى إحداثيات الصورة الأصلية، استخدم scale_boxes الذي يعالج منطق التقريب الدقيق المستخدم بواسطة LetterBox:

from ultralytics.utils.ops import scale_boxes

# boxes: tensor of shape (N, 4) in xyxy format, in 640x640 letterboxed coords
# Scale boxes from letterboxed (640, 640) back to original (orig_h, orig_w)
boxes = scale_boxes((640, 640), boxes, (orig_h, orig_w))

ينطبق هذا على جميع مسارات المعالجة الخارجية — إدخال الـ tensor المباشر، دفقات الفيديو، وعمليات نشر Triton.

DALI + تنبؤ Ultralytics
from nvidia.dali.plugin.pytorch import DALIGenericIterator

from ultralytics import YOLO

# Load model
model = YOLO("yolo26n.pt")

# Create DALI iterator
pipe = yolo_dali_pipeline_centered(image_dir="/path/to/images", target_size=640)
pipe.build()
dali_iter = DALIGenericIterator(pipe, ["images"], reader_name="Reader")

# Run inference with DALI-preprocessed tensors
for batch in dali_iter:
    images = batch[0]["images"]  # Already on GPU, shape (B, 3, 640, 640)
    results = model.predict(images, verbose=False)
    for result in results:
        print(f"Detected {len(result.boxes)} objects")
صفر عبء معالجة مسبقة

عند تمرير torch.Tensor إلى model.predict()، تستغرق خطوة معالجة الصور حوالي 0.004 مللي ثانية (تعتبر صفراً) مقارنة بـ 1-10 مللي ثانية في حالة المعالجة على CPU. يجب أن يكون الـ tensor بتنسيق BCHW، وبنوع float32 (أو float16)، ومطبعاً إلى [0, 1]. سيستمر Ultralytics في معالجة النقل إلى الجهاز (device) والتحويل النوعي (dtype casting) تلقائياً.

DALI مع دفقات الفيديو

لمعالجة الفيديو في الوقت الفعلي، استخدم fn.external_source لتغذية الإطارات من أي مصدر — OpenCV، أو GStreamer، أو مكتبات التقاط مخصصة:

خط معالجة DALI لمعالجة دفق الفيديو مسبقاً
import nvidia.dali as dali
import nvidia.dali.fn as fn
import nvidia.dali.types as types

@dali.pipeline_def(batch_size=1, num_threads=4, device_id=0)
def yolo_video_pipeline(target_size=640):
    """DALI pipeline for processing video frames from external source."""
    # External source for feeding frames from OpenCV, GStreamer, etc.
    frames = fn.external_source(device="cpu", name="input")
    frames = fn.reshape(frames, layout="HWC")

    # Move to GPU and preprocess
    frames_gpu = frames.gpu()
    resized = fn.resize(
        frames_gpu,
        resize_x=target_size,
        resize_y=target_size,
        mode="not_larger",
        interp_type=types.INTERP_LINEAR,
        antialias=False,
    )
    padded = fn.crop(
        resized,
        crop=(target_size, target_size),
        out_of_bounds_policy="pad",
        fill_values=114,
    )
    output = fn.crop_mirror_normalize(
        padded,
        dtype=types.FLOAT,
        output_layout="CHW",
        mean=[0.0, 0.0, 0.0],
        std=[255.0, 255.0, 255.0],
    )
    return output

خادم استدلال Triton مع DALI

للنشر في بيئة الإنتاج، ادمج معالجة DALI مسبقاً مع TensorRT الاستدلال في Triton Inference Server باستخدام نموذج تجميعي (ensemble). يلغي هذا المعالجة على الـ CPU تماماً — تدخل بايتات JPEG خام، وتخرج نتائج الكشف، مع معالجة كل شيء على الـ GPU.

هيكل مستودع النماذج

model_repository/
├── dali_preprocessing/
│   ├── 1/
│   │   └── model.dali
│   └── config.pbtxt
├── yolo_trt/
│   ├── 1/
│   │   └── model.plan
│   └── config.pbtxt
└── ensemble_dali_yolo/
    ├── 1/                  # Empty directory (required by Triton)
    └── config.pbtxt

الخطوة 1: إنشاء خط معالجة DALI

تسلسل خط معالجة DALI لـ Triton DALI backend:

تسلسل خط معالجة DALI لـ Triton
import nvidia.dali as dali
import nvidia.dali.fn as fn
import nvidia.dali.types as types

@dali.pipeline_def(batch_size=8, num_threads=4, device_id=0)
def triton_dali_pipeline():
    """DALI preprocessing pipeline for Triton deployment."""
    # Input: raw encoded image bytes from Triton
    images = fn.external_source(device="cpu", name="DALI_INPUT_0")
    images = fn.decoders.image(images, device="mixed", output_type=types.RGB)

    resized = fn.resize(
        images,
        resize_x=640,
        resize_y=640,
        mode="not_larger",
        interp_type=types.INTERP_LINEAR,
        antialias=False,
    )
    padded = fn.crop(
        resized,
        crop=(640, 640),
        out_of_bounds_policy="pad",
        fill_values=114,
    )
    output = fn.crop_mirror_normalize(
        padded,
        dtype=types.FLOAT,
        output_layout="CHW",
        mean=[0.0, 0.0, 0.0],
        std=[255.0, 255.0, 255.0],
    )
    return output

# Serialize pipeline to model repository
pipe = triton_dali_pipeline()
pipe.serialize(filename="model_repository/dali_preprocessing/1/model.dali")

الخطوة 2: تصدير YOLO إلى TensorRT

تصدير نموذج YOLO إلى محرك TensorRT
from ultralytics import YOLO

model = YOLO("yolo26n.pt")
model.export(format="engine", imgsz=640, half=True, batch=8)
# Copy the .engine file to model_repository/yolo_trt/1/model.plan

الخطوة 3: تهيئة Triton

dali_preprocessing/config.pbtxt:

name: "dali_preprocessing"
backend: "dali"
max_batch_size: 8
input [
  {
    name: "DALI_INPUT_0"
    data_type: TYPE_UINT8
    dims: [ -1 ]
  }
]
output [
  {
    name: "DALI_OUTPUT_0"
    data_type: TYPE_FP32
    dims: [ 3, 640, 640 ]
  }
]

yolo_trt/config.pbtxt:

name: "yolo_trt"
platform: "tensorrt_plan"
max_batch_size: 8
input [
  {
    name: "images"
    data_type: TYPE_FP32
    dims: [ 3, 640, 640 ]
  }
]
output [
  {
    name: "output0"
    data_type: TYPE_FP32
    dims: [ 300, 6 ]
  }
]

ensemble_dali_yolo/config.pbtxt:

name: "ensemble_dali_yolo"
platform: "ensemble"
max_batch_size: 8
input [
  {
    name: "INPUT"
    data_type: TYPE_UINT8
    dims: [ -1 ]
  }
]
output [
  {
    name: "OUTPUT"
    data_type: TYPE_FP32
    dims: [ 300, 6 ]
  }
]
ensemble_scheduling {
  step [
    {
      model_name: "dali_preprocessing"
      model_version: -1
      input_map {
        key: "DALI_INPUT_0"
        value: "INPUT"
      }
      output_map {
        key: "DALI_OUTPUT_0"
        value: "preprocessed_image"
      }
    },
    {
      model_name: "yolo_trt"
      model_version: -1
      input_map {
        key: "images"
        value: "preprocessed_image"
      }
      output_map {
        key: "output0"
        value: "OUTPUT"
      }
    }
  ]
}
كيف يعمل الربط التجميعي (Ensemble Mapping)

يربط التجميع النماذج من خلال أسماء الـ tensors الافتراضية.output_map القيمة "preprocessed_image" في خطوة DALI تطابق input_map القيمة "preprocessed_image" في خطوة TensorRT. هذه أسماء عشوائية تربط مخرج خطوة ما بمدخل الخطوة التالية — لا تحتاج لمطابقة أسماء الـ tensors الداخلية لأي نموذج.

الخطوة 4: إرسال طلبات الاستدلال

!!! info "لماذا tritonclient بدلاً من YOLO(\"http://...\")?"

Ultralytics has [built-in Triton support](triton-inference-server.md#running-inference) that handles pre/postprocessing automatically. However, it won't work with the DALI ensemble because `YOLO()` sends a preprocessed float32 tensor while the ensemble expects raw JPEG bytes. Use `tritonclient` directly for DALI ensembles, and the [built-in integration](triton-inference-server.md) for standard deployments without DALI.
إرسال الصور إلى Triton ensemble
import numpy as np
import tritonclient.http as httpclient

client = httpclient.InferenceServerClient(url="localhost:8000")

# Load image as raw bytes (JPEG/PNG encoded)
image_data = np.fromfile("image.jpg", dtype="uint8")
image_data = np.expand_dims(image_data, axis=0)  # Add batch dimension

# Create input
input_tensor = httpclient.InferInput("INPUT", image_data.shape, "UINT8")
input_tensor.set_data_from_numpy(image_data)

# Run inference through the ensemble
result = client.infer(model_name="ensemble_dali_yolo", inputs=[input_tensor])
detections = result.as_numpy("OUTPUT")  # Shape: (1, 300, 6) -> [x1, y1, x2, y2, conf, class_id]

# Filter by confidence (no NMS needed — YOLO26 is end-to-end)
detections = detections[0]  # First image
detections = detections[detections[:, 4] > 0.25]  # Confidence threshold
print(f"Detected {len(detections)} objects")
تجميع صور JPEG

عند إرسال مجموعة (batch) من صور JPEG إلى Triton، قم بحشو (pad) جميع مصفوفات البايت المشفرة لتصل إلى نفس الطول (أقصى عدد بايت في المجموعة). يتطلب Triton أشكالاً متجانسة للمجموعة (batch shapes) لمدخل الـ tensor.

المهام المدعومة

تعمل معالجة DALI مسبقاً مع جميع مهام YOLO التي تستخدم خط المعالجة القياسي LetterBox:

المهمةمدعومملاحظات
الكشفمعالجة letterbox القياسية
التجزئة (Segmentation)نفس معالجة الكشف
تقدير الوضعيةنفس معالجة الكشف
الكشف الموجه (OBB)نفس معالجة الكشف
التصنيفيستخدم تحويلات torchvision (قص المركز)، وليس letterbox

القيود

  • Linux فقط: لا يدعم DALI أنظمة Windows أو macOS
  • مطلوب GPU من NVIDIA: لا يوجد بديل يعتمد على الـ CPU فقط
  • خط معالجة ثابت: يتم تحديد بنية خط المعالجة عند البناء ولا يمكن تغييرها ديناميكياً
  • fn.pad هو لليمين/الأسفل فقط: استخدم fn.crop مع out_of_bounds_policy="pad" للحشو المركزي
  • لا يوجد وضع rect: تنتج خطوط معالجة DALI مخرجات ثابتة الحجم (مثل 640×640). وضع auto=True rect الذي ينتج مخرجات متغيرة الحجم (مثل 384×640) غير مدعوم. لاحظ أنه بينما TensorRT يدعم أشكال الإدخال الديناميكية، فإن خط معالجة DALI ثابت الحجم يتناسب بشكل طبيعي مع محرك ثابت الحجم لتحقيق أقصى قدر من الإنتاجية
  • الذاكرة مع حالات متعددة: استخدام instance_group مع count > 1 في Triton قد يسبب استهلاكاً عالياً للذاكرة. استخدم مجموعة الحالات (instance group) الافتراضية لنموذج DALI

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

كيف تقارن سرعة معالجة DALI مسبقاً بمعالجة CPU؟

تعتمد الفائدة على خط المعالجة الخاص بك. عندما يكون الاستدلال على الـ GPU سريعاً بالفعل بفضل TensorRT، يمكن أن تصبح معالجة الـ CPU التي تستغرق 2-10 مللي ثانية هي التكلفة المهيمنة. يلغي DALI عنق الزجاجة هذا عن طريق إجراء المعالجة على الـ GPU. تُلاحظ أكبر المكاسب مع مدخلات عالية الدقة (1080p، 4K)، وعند نشر النماذج في بيئة الإنتاج، تكون متطلبات الذاكرة وكفاءة التدريب حاسمة تماماً مثل سرعة الاستدلال. نماذج Ultralytics، وخاصة YOLO26، محسنة للغاية لتقليل استخدام ذاكرة CUDA أثناء التدريب. وهذا يسمح للمطورين باستخدام الكبيرة، والأنظمة ذات أنوية CPU محدودة لكل GPU.

هل يمكنني استخدام DALI مع نماذج PyTorch (وليس فقط TensorRT)؟

نعم. استخدم DALIGenericIterator للحصول على مخرجات torch.Tensor مجهزة مسبقاً، ثم مررها إلى model.predict(). ومع ذلك، تكون فائدة الأداء أكبر مع نماذج TensorRT حيث يكون الاستدلال سريعاً جداً وتصبح معالجة الـ CPU هي عنق الزجاجة.

ما الفرق بين fn.pad و fn.crop للحشو؟

fn.pad يضيف الحشو فقط إلى حواف الحواف اليمنى والسفلية. يقوم fn.crop مع out_of_bounds_policy="pad" بتوسيط الصورة وإضافة الحشو بشكل متماثل على جميع الجوانب، مما يطابق سلوك LetterBox(center=True) في Ultralytics.

هل ينتج DALI نتائج متطابقة بكسل بكسل مع معالجة الـ CPU؟

متطابقة تقريباً. قم بضبط antialias=False في fn.resize لمطابقة cv2.INTER_LINEAR الخاص بـ OpenCV. قد تحدث اختلافات طفيفة في الفاصلة العائمة (< 0.001) بسبب حسابات الـ GPU مقابل الـ CPU، لكن ليس لها تأثير ملموس على الدقة.

ماذا عن CV-CUDA كبديل لـ DALI؟

CV-CUDA هي مكتبة أخرى من NVIDIA لمعالجة الرؤية المتسارعة على الـ GPU. توفر تحكماً لكل عامل (مثل OpenCV ولكن على GPU) بدلاً من نهج خط المعالجة الخاص بـ DALI. يدعم cvcuda.copymakeborder() الخاص بـ CV-CUDA الحشو الصريح لكل جانب، مما يجعل letterbox المركزي مباشراً. اختر DALI لسير العمل القائم على خط المعالجة (خاصة مع Triton)، وCV-CUDA للتحكم الدقيق على مستوى العمليات في كود الاستنتاج المخصص.

التعليقات