7.13. كبت غير الحد الأقصى (Non-max suppression)¶
عادةً ما تنتج شبكة الكشف عدة مربعات مرشحة متداخلة حول الكائن الواقعي نفسه: كل مرساة قريبة من الكائن تُطلق بدرجة متشابهة، ويرى المعالج اللاحق جميعها. كبت غير الحد الأقصى (NMS) هو الخطوة التي تحوّل تلك المجموعة إلى مربع واحد.
الخوارزمية قصيرة: رتّب المربعات المرشحة حسب الدرجة، خذ الأعلى درجة، اكبت كل مربع آخر يتداخل معه فوق عتبة مختارة، ثم خذ التالي الأعلى مما تبقّى، وكرّر. مقياس التداخل هو التقاطع على الاتحاد (IoU) -- المساحة المشتركة بين مربعين مقسومة على مساحتهما المجمّعة، وهي قيمة بين 0 (لا تداخل) و 1 (مربعان متطابقان). الوسيطة nms_threshold في بانِي كل معالج لاحق مشحون هي الحد الذي تُعامَل فوقه المربعات كنسخ مكررة لمربع محفوظ بالفعل.
يطوي NMS مجموعة من الكشوف المتداخلة إلى الأعلى درجةً.¶
7.13.1. Soft-NMS¶
تنفّذ الفئة المشحونة ml.utils.NMS Soft-NMS، وهو تحسين يخفّض درجة المربع المتداخل بمقدار يعتمد على مدى تداخله، بدلاً من إسقاط المربع كلياً. إذا هبطت الدرجة المخفّضة دون العتبة أُسقط المربع؛ وإلا فإنه ينجو بالدرجة المخفّضة ويتنافس في الجولة التالية.
تتحكم الوسيطة nms_sigma في مدى عدوانية التخفيض. مع قيمة nms_sigma صغيرة (الافتراضي المشحون 0.1) يكون التخفيض حاداً: المربع شديد التداخل تُدفع درجته إلى ما يقارب الصفر ويتراجع Soft-NMS إلى NMS الكلاسيكي. ومع قيمة nms_sigma أكبر يكون التخفيض لطيفاً وتنجو المربعات المتداخلة لكائنات مختلفة أكثر تكراراً، وهو ما يهم عندما تتداخل كائنات واقعية من الفئة نفسها فعلياً (حشد من الوجوه، أو مجموعة من راحات الأيدي).
ضبط nms_sigma على قيمة <= 0 يعطّل التخفيض كلياً: تمرّ المربعات المتداخلة بدرجاتها الأصلية، ولا تُرشّحها سوى عتبة الدرجة.
7.13.2. بناء واحد مباشرةً¶
يبني كل معالج لاحق مشحون مثيلاً جديداً من NMS لكل استدلال، ويضيف كل مرشح إليه، ويستدعي get_bounding_boxes() في النهاية. يتبع المعالج اللاحق المخصص النمط نفسه:
from ml.utils import NMS
iw = model.input_shape[0][2]
ih = model.input_shape[0][1]
nms = NMS(iw, ih, inputs[0].roi)
for box, score, class_idx in candidates:
nms.add_bounding_box(box.xmin, box.ymin,
box.xmax, box.ymax,
score, class_idx)
result = nms.get_bounding_boxes(threshold=nms_threshold,
sigma=nms_sigma)
يأخذ البانِي عرض وارتفاع مدخلات الشبكة بالبكسل ومنطقة الاهتمام (ROI) من الصورة الأصلية التي عمل عليها النموذج؛ تأخذ add_bounding_box() إحداثيات المربع في فضاء بكسل مدخلات الشبكة ذاك، وتعيد get_bounding_boxes() تخطيط الناجين إلى إحداثيات الصورة باستخدام منطقة الاهتمام (ROI). يأخذ إعادة التخطيط في الحسبان تمدد التطبيع تلقائياً -- إذ تُستخدَم منطقة الاهتمام (ROI) نفسها التي رآها المتنبّئ لإسقاط المربعات إلى الخلف -- فتكون المربعات المُعادة جاهزة للرسم على الإطار الملتقَط.
شكل القيمة المُعادة هو قائمة من القوائم لكل فئة، مفهرسة بحسب label_index المُمرَّر إلى add_bounding_box. تُحفَظ قوائم الفئات الفارغة حتى يطابق الفهرس فهرس فئة النموذج؛ ويمشي enumerate(result) عبر الفئات جنباً إلى جنب مع كشوفها.