5.20. الانحدار والتشابه¶
قياسان إضافيان على الفئة Image يلخّصان الصورة كشيء آخر غير توزيع لقيم البكسل. يعطي الانحدار الخطي للبكسلات المُعتبَنة التطبيقَ خطاً يمكنه التصرّف بناءً عليه -- وهو المدخل الكلاسيكي لروبوت متتبّع للخطوط. ويعطي قياس التشابه التطبيقَ رقماً مفرداً يصف مدى تشابه صورتين -- وهو المدخل الطبيعي لاختبار انحدار الصورة الذهبية أو لكاشف التغيّر الجسيم.
5.20.1. الانحدار الخطي¶
عندما تشكّل بكسلات مقدمة الصورة خطاً عبر الإطار -- الشريط على مسار يتبعه روبوت، أو خط الأفق، أو حافة طريق أو ممر -- فإن التطبيق عادة لا يريد كل بكسل مقدمة على حدة. بل يريد الخط الأفضل ملاءمة الذي يمرّ بها جميعاً، مُمعلَماً بحيث يمكنه أن يقرّر كيف يتوجّه الخط وأين يعبر الإطار.
يقوم التابع get_regression() بهذه الملاءمة. يأخذ صيغة صف العتبة نفسها التي يستخدمها binary() و find_blobs()، ويحدّد كل بكسل يطابق العتبة، ويُرجع نتيجة line مفردة تصف الخط الأفضل ملاءمة المارّ بتلك البكسلات:
line = img.get_regression([(0, 60)])
if line:
img.draw_line((line.x1(), line.y1(),
line.x2(), line.y2()),
color=(255, 0, 0))
الملاءمة هي انحدار خطي Theil-Sen -- وهي طريقة متينة تتحمّل القيم الشاذة على نحو أفضل من ملاءمة المربعات الصغرى الأكثر شيوعاً. فحفنة صغيرة من البكسلات البعيدة عن الخط الحقيقي لا تحرف النتيجة كما تفعل مع المربعات الصغرى، ما يطابق واقع المقدمة المشوّشة لخرج عتبة حقيقي.
تحمل نتيجة line النقطتين الطرفيتين مقصوصتين إلى مستطيل الصورة (x1 و y1 و x2 و y2)، وطول الخط ومقداره (length و magnitude)، والوصف الهندسي للخط في الصيغة القطبية (theta و rho) -- زاوية الخط عن الأفقي ومسافته العمودية عن نقطة الأصل. الصيغة القطبية هي ما تريده حلقة التحكم عادة: يخبر theta الروبوتَ في أي اتجاه يميل الخط، ويخبره rho أين يعبر الخط الصورة، وتُبقي حلقة تغذية راجعة على الاثنين الروبوتَ في وسط الخط.
تضبط حفنة من الوسائط المفتاحية المتانة والتكلفة. يتخطّى x_stride و y_stride البكسلات أثناء الملاءمة -- الخطوات الأكبر تجعل الانحدار أرخص على حساب ملاءمة عدد أقل من البكسلات. يرفض area_threshold و pixels_threshold الخطوط التي لا يكفي عدد البكسلات المطابقة خلفها. يعيد target_size تحجيم المدخل إلى حجم أصغر قبل الملاءمة -- يعمل الانحدار أسرع على بديل بأبعاد 80 في 60 للصورة دون خسارة كبيرة في دقة اتجاه الخط.
إذا تعذّرت ملاءمة أي خط مقبول -- إذا لم تطابق العتبة أي بكسلات، أو طابقت نمطاً لا يبدو كخط -- يُرجع التابع None. تحرس شيفرة تتبّع الخطوط الحقيقية كل استدعاء get_regression() بفحص None قبل الوصول إلى سمات الخط.
5.20.2. تشابه الصور¶
نوع مختلف من القياس: بدلاً من السؤال "ماذا تحتوي الصورة؟"، اسأل "كم تتشابه هاتان الصورتان؟". العملية التي نلجأ إليها هي get_similarity()، التي تحسب مؤشر التشابه البنيوي (SSIM) بين الصورة المصدر وصورة مرجعية.
s = img.get_similarity(reference)
print(s.mean, s.stdev)
SSIM هو مقياس تشابه الصور القياسي المستخدم على نطاق واسع في معالجة الصور لأنه يتصرّف بالطريقة التي يتصرّف بها حدس الإنسان حول التشابه -- إزاحة صغيرة أو تغيّر سطوع صغير يخفّض الدرجة قليلاً، في حين يخفّضها تغيّر بنيوي كبير (كائن مفقود، مشهد مختلف) بشكل جذري. تتراوح الدرجة من -1 إلى +1: +1 تعني أن الصورتين متطابقتان، و 0 تعني أنهما غير مترابطتين، و -1 تعني أنهما متعاكستان بنيوياً. يكشف الكائن similarity المُرجَع عن متوسط SSIM عبر الصورة، إضافة إلى الانحراف المعياري والحد الأدنى والحد الأقصى للدرجات لكل بلاطة.
بالنسبة لنوع المقارنة التي يكون فيها الرقم الصغير أفضل من الكبير -- اختبار انحدار ينبغي أن يُبلّغ صفراً عند "لم يتغيّر شيء" ويرتفع مع تراكم التغيّرات -- تُرجع الراية dssim=True عدمَ التشابه البنيوي: متوسط SSIM مطروحاً من 1، بحيث تكون القيمة المُرجَعة 0.0 للصور المتطابقة وترتفع مع اختلافها.
5.20.3. حالات استخدام SSIM¶
التطبيقان الشائعان:
اختبار انحدار الصورة الذهبية. يلتقط إطار عمل اختبار إطاراً مرجعياً في ظروف معروفة الجودة ويخزّنه كصورة ذهبية. تلتقط عمليات التشغيل اللاحقة للاختبار في الظروف نفسها وتقارن مقابل الصورة الذهبية باستخدام SSIM. الدرجة فوق عتبة ما (0.95 أو 0.98 حسب التسامح) تعني النجاح؛ ودونها تعني الفشل. لا يحتاج إطار عمل الاختبار إلى معرفة ما الذي تغيّر -- درجة SSIM هي الإشارة.
كشف التغيّر الجسيم. التطبيق الذي يريد نسخة أخشن من فرق الإطارات -- نسخة تتجاهل تغيّرات السطوع الصغيرة لكنها تتفاعل مع التغيّرات البنيوية الكبيرة -- يمكنه استخدام SSIM مقابل إطار مرجعي بدلاً من difference() لكل بكسل متبوعاً بعتبة. SSIM أقل حساسية لانحراف الإضاءة من فرق كل بكسل، ما يجعله الخيار الأفضل عندما يكون الهدف كشف "المشهد يبدو مختلفاً جوهرياً" بدلاً من "تغيّر أي بكسل بعينه".
يستخدم كلا التطبيقين الاستدعاء نفسه -- img.get_similarity(reference) -- ويُطلَقان عند عتبة للدرجة المُرجَعة. الفرق هو فقط ما إذا كانت العتبة مرتفعة (اختبار الانحدار، بحثاً عن تطابق شبه متطابق) أم منخفضة (كشف التغيّر، بحثاً عن أي تغيّر بنيوي كبير).
5.20.4. صيغة التحويل والمقارنة¶
دقّة مفيدة: يقبل get_similarity() المعاملات نفسها x و y و x_scale و y_scale و roi و rgb_channel و alpha و color_palette و alpha_palette و hint و transform التي يقبلها draw_image(). تُوضَع الصورة المرجعية وتُحجَّم وتُحوَّل بهذه المعاملات قبل تشغيل مقارنة SSIM.
هذا يعني أن التطبيق يمكنه السؤال "كم تتشابه هذه الصورة مع إطار مرجعي بعد إزاحة / دوران / تحجيم معروف" دون تحضير صورة مرجعية محوّلة مسبقاً. إنها الطريقة الرخيصة لبناء متتبّع يبحث في فضاء معاملات ويُبلّغ أي تحويل للمرجع يطابق الإطار الحالي على أفضل وجه.