حدّد المشكلة
حوّل فكرة منتج مبهمة إلى مواصفات مهمة من ثلاثة أسطر، وأبقِ قاعدة العمل في الشيفرة حيث يمكنك تغييرها دون إعادة التدريب.

معظم مشاريع الرؤية الحاسوبية التي تتعثر لم تبدأ بسؤال واضح. تبدو عبارة «اكتشاف السلوك غير الآمن» كأنها متطلب، لكن لا يستطيع المعلِّق وضع تسمية له، ولا يستطيع النموذج تعلّمه، ولا يمكن لأحد تحديد ما إذا كان يعمل. تحل مواصفات من ثلاثة أسطر هذه المشكلة في ظهيرة واحدة — وتحدد المهمة التي ستدرّبها، وما ستضع له تسميات، والمقياس الذي ستبلّغ عنه.
عملي
لماذا تأتي المواصفات أولًا#

ترث كل خطوة في مشروع الرؤية الحاسوبية هدفها من الخطوة 0. فالسؤال المبهم ينتج مجموعة بيانات مبهمة، ومعلّقين مختلفين، ومقياسًا يقيس الشيء الخطأ — ولن يصلح أي قدر من التدريب في الخطوة 2 ذلك.
الأسطر الثلاثة#
تتكون مواصفات المهمة من ثلاث جمل، جملة واحدة في كل سطر. وتجيب كل جملة عن سؤال سيطرحه شخص مختلف في المشروع:
| السطر | السؤال الذي يجيب عنه | ضعيف | قوي |
|---|---|---|---|
| المدخلات | ماذا يرى النموذج؟ | «لقطات من كاميرا» | «إطارات بدقة 1920×1080 وبمعدل 5 fps من 12 كاميرا سقفية» |
| المخرجات | ما البيانات التي تعود؟ | «اكتشاف مشكلات السلامة» | «مربعات حول forklift وperson، لكل منها درجة ثقة» |
| القرار | من يتخذ الإجراء، ومتى؟ | «تحسين السلامة» | «إخطار مشرف الوردية عندما تكون رافعة شوكية وشخص على بُعد 2 m أو أقل لمدة 2 s» |
يستحق سطر المخرجات أكبر قدر من الاهتمام، لأن نوع بياناته يحدد المهمة:

تعني تسمية للصورة بأكملها التصنيف؛ وتعني المربعات الكشف؛ وتعني الحدود الخارجية التجزئة؛ وتعني المفاصل تقدير الوضعية؛ وتعني المربعات المدورة OBB؛ وتعني فئة أو مسافة لكل بكسل التجزئة الدلالية أو تقدير العمق. يتناول الدرس التالي المهام السبع كلها.
مثال تطبيقي: افصل النموذج عن القاعدة#
«نريد معرفة متى تفعل الرافعات الشوكية شيئًا خطيرًا في أرضية المستودع.»
هذه الجملة تصف مشروعًا لا مهمة. فهي تخلط بين مهمتين: العثور على الرافعات الشوكية والأشخاص، وهذا يتعلق بالبكسلات، وتحديد ما يُعدّ خطيرًا، وهذا يتعلق بالسياسة. افصلهما:
الكاشف وحده هو النموذج. أما المعين فهو شيفرة عادية. يمكنك تجربة هذا الفصل الآن: لا تحتوي bus.jpg على رافعة شوكية، لكن الحافلة وأربعة أشخاص فيها يتيحون إجراء الاختبار نفسه. تنص القاعدة الأولية على «إطلاق تنبيه عندما يتداخل أكثر من 30% من مربع الشخص مع مربع مركبة»:
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
result = model("https://ultralytics.com/images/bus.jpg", verbose=False)[0]
# The model's job ends here: a class, a box, and a confidence per object.
people = [b.xyxy[0].tolist() for b in result.boxes if result.names[int(b.cls)] == "person"]
vehicles = [b.xyxy[0].tolist() for b in result.boxes if result.names[int(b.cls)] == "bus"]
def share_inside(a, b):
"""Fraction of box a's area that lies inside box b."""
w = max(0, min(a[2], b[2]) - max(a[0], b[0]))
h = max(0, min(a[3], b[3]) - max(a[1], b[1]))
return w * h / ((a[2] - a[0]) * (a[3] - a[1]))
# The decision rule is plain code: change the policy without retraining.
ALERT_SHARE = 0.30
for person in people:
share = max(share_inside(person, v) for v in vehicles)
print(f"person at x={person[0]:3.0f}: {share:4.0%} inside the bus box -> {'ALERT' if share > ALERT_SHARE else 'ok'}")person at x= 49: 70% inside the bus box -> ALERT
person at x=223: 76% inside the bus box -> ALERT
person at x=670: 70% inside the bus box -> ALERT
person at x= 0: 62% inside the bus box -> ALERTأُطلقت أربعة تنبيهات، وكلها خاطئة: فالأشخاص على الرصيف أمام حافلة متوقفة. الكاشف محق في جميع المربعات؛ أما القاعدة فخاطئة، لأن التداخل في صورة ثنائية الأبعاد لا يعني أن الشيئين متقاربان في الواقع. وبما أن القاعدة شيفرة، فإصلاحها يكون بالشيفرة. قارن موضع ملامسة قدمي كل شخص للأرض مع خط عجلات الحافلة:
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
result = model("https://ultralytics.com/images/bus.jpg", verbose=False)[0]
people = [b.xyxy[0].tolist() for b in result.boxes if result.names[int(b.cls)] == "person"]
vehicles = [b.xyxy[0].tolist() for b in result.boxes if result.names[int(b.cls)] == "bus"]
def same_ground_line(person, vehicle, tolerance=40):
"""True when the person's feet are level with the vehicle's wheels and inside its width."""
feet_x, feet_y = (person[0] + person[2]) / 2, person[3]
return vehicle[0] < feet_x < vehicle[2] and abs(feet_y - vehicle[3]) < tolerance
for person in people:
alert = any(same_ground_line(person, v) for v in vehicles)
print(f"person at x={person[0]:3.0f}: feet y={person[3]:.0f}, bus wheels y={vehicles[0][3]:.0f} -> {'ALERT' if alert else 'ok'}")person at x= 49: feet y=902, bus wheels y=751 -> ok
person at x=223: feet y=861, bus wheels y=751 -> ok
person at x=670: feet y=880, bus wheels y=751 -> ok
person at x= 0: feet y=871, bus wheels y=751 -> okتقع أقدام كل شخص على بُعد 110–150 بكسل أسفل خط العجلات، ما يعني أنهم أقرب إلى الكاميرا من الحافلة. لا حاجة لإعادة التدريب أو وضع تسميات من جديد: يستطيع فريق السلامة تحسين القاعدة فيما يبقى الكاشف ثابتًا. أما نسخة الإنتاج، فستحوّل مواضع الأقدام إلى إحداثيات على الأرض باستخدام كاميرا معايرة، وستضيف شرط الاستمرار لمدة ثانيتين عبر تتبّع الكائنات — وكل ذلك يظل شيفرة تُطبّق على المربعات نفسها.
مكان الكلمات الذاتية — «غير آمن» و«معيب» و«مريب» و«شخصية مهمة» — هو في الشيفرة التي تقرأ مخرجات النموذج. يجيب النموذج عن أسئلة تتعلق بالبكسلات. إذا كان خبيران سيختلفان حول تسمية ما، فمكان الخلاف في قاعدة يمكنك تحديد إصدارها واختبارها وتغييرها.
مواطن الخلل#
العَرَض: تنص المواصفات على «اكتشاف مشكلات السلامة» أو «فهم المشهد»، ويسأل العاملون على التعليقات التوضيحية عمّا ينبغي رسمه. الحل: أعد صياغة المخرجات على هيئة نوع بيانات ذي فئات مسماة: «مربعات لـ forklift وperson».
العَرَض: فئة مثل suspicious_behavior أو dangerous يضع لها شخصان يعملان على التعليقات التوضيحية تسميتين مختلفتين في الإطار نفسه. الحل: استبدلها بدليل مرئي — شخص داخل منطقة محظورة، أو باب مُبقى مفتوحًا — وانقل الحكم إلى سطر القرار.
العَرَض: «صِف ما يحدث» (وصف الصور) أو «توقّع ما إذا كانت الرافعة الشوكية ستصدم شخصًا» (التنبؤ). الحل: حدّد مواقع الكائنات أولًا، ثم أضف قواعد التتبع والحركة. أنشئ الكاشف قبل التنبؤ.
من المواصفات إلى معايير النجاح#
توضح المواصفات ما يفعله النموذج، لا مقدار الجودة الكافي أو تكلفة الحالة الفائتة مقارنةً بإنذار كاذب. يحوّل قسم ابدأ بهدف العمل في بناء مجموعات بيانات YOLO عالية الأداء المواصفات إلى أهداف قابلة للقياس. وتعود كل الدروس اللاحقة في هذه الدورة إلى أسطرك الثلاثة.
عرض الحل
مواصفات كاميرا الرفوف:
- المدخلات: صورة ثابتة بدقة 1920×1080 كل 60 ثانية من كاميرا ثابتة تواجه ممرًا واحدًا.
- المخرجات: مربعات إحاطة حول
productوempty_facing(حيّز رف خالٍ من المنتجات)، لكل منها درجة ثقة. - القرار: إنشاء مهمة لإعادة التزويد عندما تستمر ثلاثة مربعات أو أكثر من
empty_facingعلى الرف نفسه عبر خمس صور ثابتة متتالية خلال ساعات عمل المتجر.
الكلمات التي لا يستطيع النموذج رؤيتها هي مهمة إعادة التزويد والرف نفسه والاستمرار عبر خمس صور ثابتة وساعات عمل المتجر. وتُكتب القاعدة كما يلي:
if count(empty_facing on shelf S) >= 3 in each of the last 5 stills and store_is_open(now):
create_restock_task(shelf=S)يمكن للمتجر تغيير «3» أو «5» أو ساعات العمل دون إعادة وضع تسمية لصورة واحدة.