تشغيل الاستدلال على الفيديو
شغّل YOLO26 على ملفات الفيديو والكاميرات المباشرة مع ذاكرة محدودة، وتتبع الأجسام لاحتساب كل جسم مرة واحدة، وتحقق من أن النموذج يواكب معدل الإطارات.
تعتمد معظم أنظمة الرؤية المنشورة على الفيديو: كاميرات فوق السيور الناقلة والأبواب والطرق. يضيف الفيديو مشكلتين لا تظهران في الصور المفردة. الذاكرة: لا يمكن الاحتفاظ بتسجيل طويل في RAM. الهوية: يرصد الكاشف الشخص نفسه في 60 إطارًا ويبلّغ عن 60 شخصًا.
في هذا الدرس، ستبث الفيديو إطارًا بإطار باستخدام وضع التنبؤ، وتضيف تتبع الأجسام لاحتساب كل شخص مرة واحدة، وتكتب حلقة الكاميرا الخاصة بك، وتقيس ما إذا كان النموذج يواكب سرعة المعالجة.
عملي
مثال تطبيقي: التنبؤ على ملف فيديو#
تُعالج مقاطع الفيديو باستخدام وضع التنبؤ نفسه المستخدم للصور. يعرض هذا المقطع، المؤلف من 62 إطارًا، أشخاصًا يعبرون ردهة:
yolo predict model=yolo26n.pt source=https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4video 1/1 (frame 1/62) solutions_ci_demo.mp4: 384x640 22 persons, 27.3ms
...
video 1/1 (frame 62/62) solutions_ci_demo.mp4: 384x640 22 persons, 54.8ms
Results saved to runs/detect/predictframe 1/62: يفك Ultralytics ترميز الفيديو ويعالج كل إطار كما لو كان صورة.22 persons: عمليات الكشف في ذلك الإطار. يُحتسب المشاة أنفسهم مجددًا في كل إطار.27.3ms...54.8ms: يختلف الزمن لكل إطار بحسب المهام الأخرى التي ينفذها الجهاز.
الفيديو المشروح هو runs/detect/predict/solutions_ci_demo.mp4. يعمل نموذجك بالطريقة نفسها: استبدل yolo26n.pt بـruns/detect/pills_v1/weights/best.pt.
بث المصادر الطويلة والمباشرة#
لإنشاء شيفرة تتصرف بناءً على عمليات الكشف، استخدم حلقة لمعالجة التدفق. تنتج كل دورة Results لإطار واحد، ثم تتخلص منه:
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
source = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
frames, people = 0, 0
for result in model(source, stream=True, classes=[0], verbose=False): # one Results object per frame
frames += 1
people += len(result.boxes)
print(f"{frames} frames, {people / frames:.1f} people per frame")62 frames, 22.2 people per frameتقبل الحلقة نفسها فهرس كاميرا الويب (source=0) أو عنوان URL للكاميرا مثل rtsp://camera.local/stream، وتستمر حتى ينتهي التدفق أو توقفها. أضف vid_stride=2 لمعالجة كل إطار ثانٍ. لإنشاء واجهة متصفح حول هذه الحلقة، يغلّف دليل الاستدلال المباشر باستخدام Streamlit الحلقة في تطبيق.
مثال تطبيقي: احتساب كل شخص مرة واحدة#
«22 شخصًا في كل إطار» ليس العدد الذي يريده أحد؛ بل «كم شخصًا مرّ من هنا؟». يربط تتبع الأجسام المتعددة الصناديق عبر الإطارات، ويمنح وضع التتبع كل جسم معرّفًا في boxes.id:
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
source = "https://github.com/ultralytics/assets/releases/download/v0.0.0/solutions_ci_demo.mp4"
seen = set()
for result in model.track(source, stream=True, persist=True, classes=[0], tracker="bytetrack.yaml", verbose=False):
if result.boxes.is_track:
seen.update(result.boxes.id.int().tolist())
print(f"{len(seen)} unique people tracked")32 unique people trackedis_track هي False في الإطارات السابقة لتأكيد أي مسار، عندما تكون boxes.id هي None. استخدم المعرّفات للاحتساب أو تتبع المسارات أو تنفيذ منطق مثل «ظل هذا الجسم هنا لمدة 3 ثوانٍ».

| أداة التتبع | السرعة | المتانة |
|---|---|---|
bytetrack.yaml | أسرع وأبسط | يفقد المعرّفات بوتيرة أعلى عندما تختفي الأجسام لفترة وجيزة |
botsort.yaml | أبطأ | أفضل في الحفاظ على المعرّفات عند تحرك الكاميرا (تعويض الحركة؛ إعادة التعرّف على المظهر اختيارية عبر with_reid) |
اترك tracker دون تحديد، وسيستخدم Ultralytics tracktrack.yaml، وهو الإعداد الافتراضي الحالي؛ كما يأتي وضع التتبع مع ocsort.yaml وdeepocsort.yaml وfasttrack.yaml. يتناول تتبع الأجسام باستخدام ByteTrack وBoT-SORT وTrackTrack اختيار أدوات التتبع وضبطها، وإنشاء احتساب الأجسام والخرائط الحرارية وتقدير السرعة باستخدامها.
مثال تطبيقي: حلقة الكاميرا الخاصة بك#
غالبًا ما تقرأ التطبيقات الفعلية الإطارات بنفسها — لتغيير حجمها أو اقتصاصها أو إضافة طابع زمني أو مشاركة الكاميرا مع شيفرات أخرى — ثم تمرر كل إطار إلى النموذج. عندئذٍ، تضمن persist=True استمرار عمل أداة التتبع بين الاستدعاءات:
import cv2
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
cap = cv2.VideoCapture("solutions_ci_demo.mp4") # saved locally by the commands above; or 0, or an rtsp:// URL
seen = set()
while cap.isOpened():
ok, frame = cap.read()
if not ok:
break
result = model.track(frame, persist=True, classes=[0], tracker="bytetrack.yaml", verbose=False)[0]
if result.boxes.is_track:
seen.update(result.boxes.id.int().tolist())
cap.release()
print(f"{len(seen)} unique people, highest ID {max(seen)}")32 unique people, highest ID 67العدد نفسه، 32 شخصًا، كما في track.py. لاحظ أن أعلى معرّف هو 67 وليس 32: تخصص أداة التتبع أيضًا معرّفات للمسارات المؤقتة التي لا تُؤكَّد أبدًا، لذا توجد فجوات في المعرّفات.
مواكبة المصدر#
تُرسل كاميرا بمعدل 30 FPS إطارًا كل 33 ms، ويعادل معدلك الفعلي أبطأ المراحل: فك الترميز أو الاستدلال أو الكتابة. على وحدة المعالجة المركزية في حاسوبنا المحمول، استغرق yolo26n ما بين 26 و46 ms لكل إطار بدقة 384×640 عبر عمليات التشغيل، بحسب المهام الأخرى التي كان الجهاز ينفذها: أي عند الميزانية أو فوقها، من دون أي هامش إضافي. إذا لم يستطع جهازك مواكبة المصدر، فجرّب وسائل التحسين التالية بالترتيب:
| وسيلة التحسين | التأثير |
|---|---|
نموذج أصغر (n بدلًا من s) | أسرع غالبًا بمقدار 2–3× |
خفض imgsz (480 بدلًا من 640) | بكسلات أقل وحسابات أقل؛ تتأثر الأجسام الصغيرة أولًا |
vid_stride=2 | يقلل العمل إلى النصف؛ مناسب للمشاهد بطيئة الحركة |
| وحدة GPU أو تصدير مُحسَّن | أكبر التحسينات — محرك TensorRT على NVIDIA، أو INT8؛ راجع الدرس التالي |
يتناول الاستدلال متعدد التدفقات تشغيل عدة كاميرات في الوقت نفسه، وما يرتبط بذلك من تعدد مؤشرات الترابط.
تجنّب هذه الأخطاء#
العَرَض: تزداد الذاكرة حتى تتوقف العملية أثناء تسجيل طويل، أو لا يعود استدعاء الكاميرا المباشرة أبدًا. السبب: من دونه، يجمع استدعاء Python كائن Results لكل إطار قبل الإرجاع. الحل: مرّر stream=True وكرّر على المولّد — فهو لا يفعل شيئًا حتى تبدأ التكرار عليه.
العَرَض: في cv2_loop.py دون persist=True، انخفض العدد إلى 27 وكان أعلى معرّف أيضًا 27: بدأت المعرّفات من جديد في كل إطار، لذا لم يكن العدد «الفريد» سوى عدد الإطار الأكثر ازدحامًا. الحل: مرّر persist=True كلما استدعيت track مرةً لكل إطار.
العَرَض: عدد يبلغ 67 مقابل 32 شخصًا. السبب: توجد فجوات في المعرّفات بسبب المسارات غير المؤكدة. الحل: احسب حجم مجموعة المعرّفات، كما في track.py.
قد تتغير أداة التتبّع الافتراضية بين الإصدارات. مرّر tracker="bytetrack.yaml" (أو الأداة التي تختارها) كي تبقى الأعداد قابلة للمقارنة بين الإصدارات.
عرض الحل
import sys
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
seen, times = set(), []
for result in model.track(sys.argv[1], stream=True, persist=True, tracker="bytetrack.yaml", verbose=False):
times.append(result.speed["inference"])
if result.boxes.is_track:
seen.update(result.boxes.id.int().tolist())
print(f"{len(seen)} unique objects, {sum(times) / len(times):.1f} ms inference per frame")شغّله باستخدام python track_any.py your_video.mp4.
32 unique objects, 30.5 ms inference per frame (26-46 ms across runs on a laptop CPU)
Source is 30 FPS -> 33 ms budget: fits only on a quiet machine, with no headroom
First lever: export to OpenVINO or ONNX for this CPU, then vid_stride=2 if still short