تقدير الوضعية ومربعات الإحاطة الموجّهة (OBB)
اقرأ النقاط المفتاحية والمربعات المدوّرة من YOLO26، واكتب قاعدةً تستند إلى كلٍّ منها، وتعرّف على الحالات التي تكون فيها الوضعية أو الزاوية هي الإشارة الفعلية.
يحتاج دار رعاية إلى معرفة ما إذا كان أحدهم قد سقط؛ ويحتاج ميناء إلى عدّ السفن المتراصّة جنبًا إلى جنب في صورة ملتقطة بطائرة مسيّرة. تخفق المربعات العادية في الحالتين: فالمربع لا يوضح ما إذا كان الشخص منتصبًا، والمربع المنتصب حول سفينة مائلة يشغل معظمه ماء. صُمّم كلٌّ من تقدير الوضعية ومربعات الإحاطة الموجّهة (OBB) خصيصًا لهاتين المشكلتين.
عملي
تقدير الوضعية: عندما تكون الوضعية هي الإشارة#

يعيد نموذج تقدير الوضعية مربعًا لكل شخص، إضافةً إلى قائمة ثابتة من النقاط المفتاحية. تتنبأ النماذج المدرّبة على COCO-Pose بـ17 نقطة لكل شخص — الأنف والعينين والأذنين والكتفين والمرفقين والمعصمين والوركين والركبتين والكاحلين — بالترتيب نفسه دائمًا؛ لذلك تكون النقطة ذات الفهرس 0 هي الأنف، و11 الورك الأيسر، و15 الكاحل الأيسر. ولكل نقطة مفتاحية أيضًا درجة ثقة.
أبسط قاعدة مفيدة هي أن الجسم الواقف أطول من عرضه، بينما يكون الجسم المستلقي على الأرض أعرض من طوله. إليك تطبيقها على صورة الحافلة، باستخدام النقاط المفتاحية التي يثق بها النموذج فقط:
from ultralytics import YOLO
model = YOLO("yolo26n-pose.pt")
result = model("https://ultralytics.com/images/bus.jpg", verbose=False)[0]
for xy, conf in zip(result.keypoints.xy, result.keypoints.conf):
visible = xy[conf > 0.5] # drop keypoints the model couldn't see
width = float(visible[:, 0].max() - visible[:, 0].min())
height = float(visible[:, 1].max() - visible[:, 1].min())
posture = "unknown" if len(visible) < 5 else "lying" if width > height else "upright"
print(f"{len(visible):2d}/17 keypoints visible, body {width:3.0f} px wide x {height:3.0f} px tall -> {posture}")16/17 keypoints visible, body 117 px wide x 427 px tall -> upright
6/17 keypoints visible, body 80 px wide x 359 px tall -> upright
16/17 keypoints visible, body 91 px wide x 384 px tall -> upright
1/17 keypoints visible, body 0 px wide x 0 px tall -> unknown
2/17 keypoints visible, body 3 px wide x 6 px tall -> unknownثلاثة أشخاص منتصبون بوضوح. أما الصفان الأخيران فيمثلان الشخص المقطوع عند الحافة اليسرى وتكرارًا منخفض الثقة: لا يوجد ما يكفي للحكم عند ظهور نقطة أو نقطتين مفتاحيتين فقط، لذا تعطي القاعدة «غير معروف» بدلًا من التخمين. ويضيف كاشف السقوط المستخدم في الإنتاج عنصر الزمن عبر التتبّع، مثل الاستلقاء لأكثر من بضع ثوانٍ بعد سقوط سريع.
العَرَض: هياكل عظمية بمعاصم معلقة في الهواء، وقواعد وضعية تُفعّل عند ظهور نصف الشخص فقط. السبب: يُرجع keypoints.xy موضعًا لجميع النقاط المفتاحية الـ17، حتى تلك التي لم يتمكن النموذج من رؤيتها. الحل: رشّح باستخدام keypoints.conf كما سبق، واشترط حدًا أدنى من النقاط المفتاحية المرئية قبل اتخاذ أي قرار.
تكون فائدة تقدير الوضعية واضحة عندما تعتمد الإجابة على ما يفعله الجسم: حالات السقوط أو الرفع مع انحناء الظهر لأغراض السلامة، أو زوايا المفاصل وعدّ التكرارات في الرياضة كما في مراقبة التمارين، أو وضعية المواشي والمعالم الثابتة على القطع باستخدام تخطيط مخصص للنقاط المفتاحية. للإجابة عن سؤال «هل يوجد شخص هنا؟»، استخدم الكشف العادي.
مربعات الإحاطة الموجّهة (OBB): عندما تكون الزاوية مهمة#

تكون حواف المربع العادي موازية لحواف الصورة. ويضيف مربع الإحاطة الموجّه دورانًا، ويُخزّن على هيئة المركز والعرض والارتفاع والزاوية (xywhr). في الصور الملتقطة من الأعلى — مثل صور الأقمار الصناعية والطائرات المسيّرة وكاميرات السيور الناقلة العلوية — تظهر الأجسام بزوايا مختلفة، ويكون المربع المنتصب حول جسم مائل معظمه خلفية، كما هو الحال مع اليخوت أعلاه. قِس مقدار ذلك في صورة لمَرْسى التقطتها طائرة مسيّرة:
from ultralytics import YOLO
model = YOLO("yolo26n-obb.pt")
result = model("https://ultralytics.com/images/boats.jpg", verbose=False)[0]
obb = result.obb
rotated_area = obb.xywhr[:, 2] * obb.xywhr[:, 3] # width x height of each rotated box
x1, y1, x2, y2 = obb.xyxy.T # the axis-aligned box that would enclose the same object
upright_area = (x2 - x1) * (y2 - y1)
print(f"{len(obb)} objects, classes: {sorted({result.names[int(c)] for c in obb.cls})}")
cx, cy, w, h, angle = obb.xywhr[0].tolist()
print(f"first box: center=({cx:.0f}, {cy:.0f}) size={w:.0f}x{h:.0f} angle={angle:.2f} rad")
ratio = float((upright_area / rotated_area).median())
print(f"an axis-aligned box would be {ratio:.1f}x larger (median)")173 objects, classes: ['harbor', 'ship']
first box: center=(619, 850) size=33x108 angle=-0.25 rad
an axis-aligned box would be 2.1x larger (median)يغطي المربع المنتصب مساحة تقارب ضعف مساحة المربع المدوّر حول القارب نفسه، والمساحة الإضافية ماء. وهذا يسبب مشكلتين: ترى NMS تداخلًا بين المربعات المنتصبة للقوارب المتجاورة، وقد تستبعد قوارب موجودة فعلًا؛ كما تتضخم أي تقديرات للأحجام. تتعامل نماذج OBB المدرّبة على مجموعات بيانات جوية مثل DOTA مع هذه المشاهد مباشرةً. لاحظ أن الزاوية بالراديان: -0.25 rad تساوي نحو -14°.
الاختيار بين الكشف وتقدير الوضعية ومربعات الإحاطة الموجّهة (OBB)#
| السيناريو | المهمة الأنسب | السبب |
|---|---|---|
| عدّ الأشخاص على الرصيف | الكشف | الإجابة هي الوجود والموقع |
| اكتشاف سقوط في دار رعاية | تقدير الوضعية | اتجاه الجسم هو الإشارة |
| عدّ تمرينات القرفصاء في صالة رياضية | تقدير الوضعية | زوايا الركبة والورك هي الإشارة |
| عدّ القوارب الراسية باستخدام طائرة مسيّرة | OBB | القوارب مائلة ومتراصّة بإحكام |
| طرود على سير ناقل، تُرى من الأعلى | OBB | يتفاوت الاتجاه وتتلامس الأجسام المتجاورة |
| سيارات على مستوى الشارع | الكشف | تظهر السيارات منتصبة تقريبًا في الإطار |
تضيف Pose نقاطًا مفتاحية إلى كل مربع؛ وتضيف OBB زاوية. إذا لم تقرأ الشيفرة لديك النقاط المفتاحية أو الزاوية مطلقًا، فالكاشف العادي أسرع في وضع التسميات والتشغيل، وأسهل في تصحيح الأخطاء.
عرض الحل
from ultralytics import YOLO
image = "https://ultralytics.com/images/boats.jpg"
upright = YOLO("yolo26n.pt")(image, verbose=False)[0]
rotated = YOLO("yolo26n-obb.pt")(image, verbose=False)[0]
print(f"axis-aligned detector: {len(upright.boxes)} boxes")
print(f"OBB model: {len(rotated.obb)} rotated boxes")axis-aligned detector: 0 boxes
OBB model: 173 rotated boxesينجم معظم الفارق عن بيانات التدريب، لا عن الهندسة. دُرّب yolo26n.pt على COCO، حيث تُصوّر القوارب في الغالب من الجانب؛ لذلك لا يكتشف شيئًا عند رؤيتها من الأعلى باستخدام العتبة الافتراضية (اخفض conf إلى 0.05، وسيصنّف بعضها زجاجات). أما نموذج OBB فدُرّب على صور جوية. وتظل الهندسة مهمة أيضًا: فحتى الكاشف المدرّب على صور جوية للقوارب سيرسم مربعات أكبر بنحو الضعف ويواجه مشكلات NMS في الصفوف المتراصّة بإحكام. يجب أن تتوافق كل من المهمة وبيانات التدريب مع مشهد النشر.