5.18. المدرجات التكرارية والإحصاءات

إلى جانب العمليات التي تغيّر بكسلات الصورة، تحمل الفئة Image مجموعة من التوابع التي تقيسها -- فتلخّص توزيع قيم البكسل، وتُرجع متوسط ووسيط السطوع، وتجد العتبة المثلى بين البكسلات الداكنة والساطعة، وتُبلّغ عن انتشار قنوات اللون. تغذّي هذه القياسات التطبيقات بطريقتين: كمدخلات للشيفرة التي تقرّر أي عتبة تُستخدم، وأي كسب يُضبط، وكيف يبدو الملف اللوني لنبرة المشهد؛ وكإشارات تشخيصية -- "هل المشهد ساطع بما فيه الكفاية؟" -- يمكن للتطبيق أن يتصرّف بناءً عليها دون اتخاذ قرار بشأن أي بكسل بعينه.

نقطة البداية لكل قياس تقريباً هي المدرج التكراري.

5.18.1. المدرج التكراري

المدرج التكراري للصورة هو عدّ لكمية البكسلات التي تحمل كل قيمة سطوع ممكنة. بالنسبة لصورة بتدرج الرمادي، فهو قائمة من الأعداد مفهرسة بالقيم من 0 إلى 255. أما بالنسبة لصورة ملونة، فهو ثلاث قوائم من هذا النوع -- واحدة لكل قناة.

يحسبه التابع get_histogram():

h = img.get_histogram()

الكائن المُرجَع هو نتيجة histogram تكشف عن قوائم الخانات لكل قناة وبعض الاستعلامات عالية المستوى عليها. أعداد الخانات مُطبَّعة بحيث يكون مجموعها 1.0 -- فالمدرج التكراري يصف ملف التوزيع بدلاً من عدد البكسلات المطلق، ما يجعل القياسات قابلة للمقارنة عبر صور بأحجام مختلفة.

بالنسبة لصور تدرج الرمادي يحتوي المدرج التكراري على قناة خانات واحدة، متاحة عبر h.bins() (أو بالمكافئ h[0]). أما بالنسبة لصور RGB565 فيُحسَب المدرج التكراري في فضاء اللون LAB المُقدَّم في صفحة العتبنة الثنائية، مع ثلاث قنوات خانات متاحة عبر h.l_bins() و h.a_bins() و h.b_bins() (أو h[0] و h[1] و h[2]). LAB هو الخيار نفسه الذي تستخدمه توابع العتبنة والتتبّع؛ تتفق المدرجات التكرارية مع العتبات حول الفضاء الذي يُقاس فيه اللون.

5.18.2. الخانات وعدد الخانات

يحتوي المدرج التكراري الافتراضي على خانة واحدة لكل قيمة بكسل ممكنة -- 256 خانة لقناة بعرض 8 بت. أحياناً تكون هذه دقة أعلى مما يحتاجه التطبيق. قد يُخدَم مُصنِّف لا يهتمّ إلا بالملف التقريبي للتوزيع بشكل أفضل بعدد خانات أصغر -- 32 أو حتى 8 خانات -- ما يجعله أسرع تشغيلاً وينتج نتيجة أنظف في مواجهة الضوضاء. تضبط الكلمة المفتاحية binsl_bins و a_bins و b_bins لكل قناة في حالة الألوان) العدد:

h = img.get_histogram(bins=32)

يعمل تحديد نطاق منطقة الاهتمام والعتبة بالطريقة نفسها كما في كل تابع قياس آخر. مرّر roi لحصر المدرج التكراري في مستطيل من البكسلات؛ ومرّر قائمة thresholds لتضمين البكسلات المطابقة لتلك النطاقات فقط. صيغة العتبة هي ما يجعل "احسب المدرج التكراري للبكسلات المطابقة فقط" عملية باستدعاء واحد -- وهو نمط شائع عندما يريد التطبيق توصيف نسيج منطقة مكتشفة بالفعل دون الحاجة إلى المرور على البكسلات بنفسه.

A grayscale histogram drawn as a row of bars across the brightness range 0 to 255. The distribution has two peaks -- a smaller dark peak and a larger bright peak -- separated by a clear valley. Three vertical lines are overlaid: the Otsu threshold in the valley, the mean shifted toward the larger bright peak, and the median further right where cumulative pixel count reaches one-half.

مدرج تكراري بتدرج الرمادي تُراكَب عليه ثلاثة قياسات ملخّصة: عتبة Otsu (الفاصل الذي يقسم العنقودين الداكن والساطع على أفضل وجه)، والمتوسط، والوسيط. كل قياس يقول شيئاً مختلفاً عن التوزيع نفسه.

5.18.3. الإحصاءات

المدرج التكراري هو وصف لشيوع كل قيمة؛ أما الإحصاءات فهي الملخّصات العددية المشتقّة منه. يحمل الكائن statistics المُرجَع من get_statistics() المجموعة القياسية:

  • mean -- المتوسط الحسابي لقيم البكسل.

  • median -- القيمة التي يقع تحتها نصف البكسلات.

  • mode -- القيمة المفردة الأكثر شيوعاً.

  • stdev -- الانحراف المعياري، وهو مقياس للانتشار حول المتوسط.

  • min و max -- أسطع وأدكن قيم البكسل الموجودة.

  • lq و uq -- فاصلا الربيع الأدنى والأعلى.

بالنسبة لصورة RGB565 تقدّم الصيغ الخاصة بكل قناة (l_mean و a_median و b_mode وهكذا) القياسات نفسها قناةً بقناة.

تظهر معظم هذه الأرقام في سياقات محددة. يعطي mean و stdev معاً تقديراً للضوضاء: المشهد الذي يُفترَض أن يكون منتظماً له انحراف معياري صغير، في حين يعطي المستشعر المشوّش للمشهد نفسه انحرافاً معيارياً أكبر. يعطي min و max تباين الصورة: كلما اقتربا كان المشهد أكثر تسطّحاً؛ وكلما تباعدا زاد المدى الديناميكي الذي على الخوارزمية العمل به. median هو المركز المتين عندما يحتوي التوزيع على قيم شاذة (بضعة بكسلات ساطعة جداً لا تجذب الوسيط كما تجذب المتوسط). mode هو القيمة المفردة الأكثر شيوعاً، وهو مفيد لإيجاد مستوى الخلفية لصورة تغطّي خلفيتها معظم البكسلات.

يشغّل التابع get_statistics() تمريرة المدرج التكراري داخلياً ثم يلخّصها؛ وتمرير وسيطَي thresholds و roi نفسيهما المستخدمين في مدرج تكراري محسوب سابقاً ينتج الإحصاءات لمجموعة البكسلات نفسها.

5.18.4. المئينات وعمليات البحث في الدالة التراكمية CDF

يكشف الكائن histogram عن تابع get_percentile() يحوّل كسراً إلى قيمة بكسل -- القيمة التي يقع تحتها الكسر المطلوب من البكسلات. h.get_percentile(0.5) هو الوسيط؛ و h.get_percentile(0.05) و h.get_percentile(0.95) معاً يعطيان حداً أدنى/أعلى متيناً يتجاهل أدنى وأعلى 5% باعتبارها قيماً شاذة.

هذه هي الصيغة التي يستخدمها التطبيق عندما يريد توصيف مدى قيم البكسل دون أن يدع حفنة من البكسلات الساطعة أو الداكنة الشاردة تحرف الإجابة. الحد الأدنى/الأعلى المتين من المئينين الخامس والخامس والتسعين هو أيضاً المدخل الطبيعي لتمريرة تمديد التباين -- إعادة التعيين لكل بكسل التي تغطّيها صفحة التصحيحات النبرية.

5.18.5. طريقة Otsu

تجيب المدرجات التكرارية عن سؤال آخر يستحق الإشارة إليه بمفرده: إذا أُعطيت صورة تنقسم بكسلاتها إلى عنقود "داكن" وآخر "ساطع"، فما هو الفاصل بينهما؟ سمّت صفحة العتبنة الآلية بالفعل باسم نتيجتها -- عتبة عامة مفردة يمكن للتطبيق تسليمها إلى binary() -- لكنها أجّلت الكيفية. الكيفية هي طريقة Otsu، وهي تعيش على المدرج التكراري.

الحدس: الصورة ذات المقدمة والخلفية الواضحتين لها عنقودان اثنان في مدرجها التكراري للسطوع، مع وادٍ بينهما. المكان الصحيح للعتبنة هو قاع الوادي -- القيمة التي يُفصل عندها العنقودان على أفضل وجه. تبحث طريقة Otsu في كل فاصل ممكن وتختار الفاصل الذي تكون عنده التباينات داخل العنقود أصغر ما يمكن (وهو ما يعادل القول إن التباين بين العنقودين هو الأكبر)، والنتيجة هي التقسيم الثنائي الأمثل لتوزيع تلك الصورة بالذات.

يكشف الكائن histogram عن طريقة Otsu عبر get_threshold:

h = img.get_histogram()
t = h.get_threshold()

يحمل الكائن threshold المُرجَع السمة value (لتدرج الرمادي) أو السمات l_value / a_value / b_value (للألوان) التي تحمل الفاصل المختار. إن إعادة تغذية النتيجة مباشرة إلى binary() تعطي عتبة عامة ذاتية الضبط يختار الفاصل فيها بالصورة نفسها:

img.binary([(t.value, 255)])

لا يحلّ هذا النمط مشكلة الإضاءة غير المتساوية التي تحلّها العتبة التكيّفية القائمة على المرشّح؛ ما يحلّه هو سؤال "أي قيمة ينبغي أن أقطع عندها؟" عندما تكون العتبنة العامة هي المقاربة الصحيحة بالفعل. بالنسبة لمشهد يكون التمييز فيه بين المقدمة والخلفية محدداً جيداً، تكون القيمة التي تختارها Otsu عادة ضمن بضع وحدات مما قد يختاره الإنسان بالعين.

5.18.6. الحساب على صورة الفرق

تفصيل مفيد عن get_histogram() و get_statistics(): يقبل كلاهما كلمة مفتاحية difference تأخذ صورة Image أخرى وتحسب المدرج التكراري (أو الإحصاءات) للفرق لكل بكسل بين المصدر وتلك الصورة، دون تخصيص صورة فرق منفصلة. هذه هي الطريقة الرخيصة للسؤال "كم تغيّر المشهد منذ الإطار المرجعي؟" دون دفع ثمن استدعاء difference() صريح لإنتاج صورة غرضها الوحيد أن تُقاس. وبالنسبة لبرنامج نصي لكشف الحركة يعمل باستمرار، يتراكم هذا التوفير.