5.17. فهرس بالنوى القياسية

راكمت معالجة الصور الكلاسيكية فهرساً لا بأس بحجمه من أنماط أوزان النوى التي تتكرر مراراً وتكراراً -- كواشف الحواف، أدوات الإحداد، أنماط النقش البارز، أدوات التنعيم، وضبابيات الحركة -- وكل واحدة منها تعمل عبر morph(). كل نواة قصيرة، وكل واحدة تؤدي مهمة واحدة، ومعظمها سهل القراءة بمجرد أن يصبح المنطق الأساسي للأوزان مفهوماً.

النوى أدناه جميعها بحجم 3 في 3 ما لم يُذكر خلاف ذلك، لذا فهي تستخدم جميعاً size=1 في الاستدعاء. يُوصف هيكل أوزان كل نواة بجوارها، لأن قراءة الأوزان هي ما يبني الحدس حول سبب قيام نواة بالنقش البارز وأخرى بالإحداد.

5.17.1. نواة الهوية

أبسط نواة ممكنة هي نواة الهوية -- واحد في المركز، وصفر في كل مكان آخر:

identity = [0, 0, 0,
            0, 1, 0,
            0, 0, 0]

img.morph(1, identity)

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

النواة التي يكون وزن مركزها كبيراً مع أوزان سالبة صغيرة حوله تطرح المحيط من المركز. النواة التي يكون وزن مركزها صفراً تتجاهل البكسل نفسها وتستجيب فقط للفروق بين جيرانها. قراءة النواة بهذه الطريقة -- ماذا يفعل وزن المركز بالبكسل، وماذا تضيف الأوزان المحيطة أو تأخذ -- هي أسرع طريقة للتنبؤ بأثرها.

5.17.2. كشف الحواف

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

Sobel-x هو المثال النموذجي. يكشف الحواف العمودية (انتقالات السطوع يساراً/يميناً):

sobel_x = [-1,  0,  1,
           -2,  0,  2,
           -1,  0,  1]

img.morph(1, sobel_x, mul=0.25, add=128)

نواة Sobel-y المقابلة هي النمط نفسه مدوَّراً 90 درجة؛ تكشف الحواف الأفقية (انتقالات السطوع أعلى/أسفل):

sobel_y = [-1, -2, -1,
            0,  0,  0,
            1,  2,  1]

يكون للصف الأوسط من Sobel-x أوزان -2 و 2 بدلاً من -1 و 1. يمنح الوزن الإضافي على الصف المركزي النواة تنعيماً مدمجاً صغيراً في الاتجاه الموازي للحافة، مما يجعلها أكثر متانة في مواجهة الضوضاء من عامل Prewitt الأبسط الذي يُسقط هذه المقادير الإضافية:

prewitt_x = [-1, 0, 1,
             -1, 0, 1,
             -1, 0, 1]

prewitt_y = [-1, -1, -1,
              0,  0,  0,
              1,  1,  1]

يزِن Prewitt كل صف بالتساوي، لذا تكون استجابته أحدّ قليلاً من استجابة Sobel، على حساب كونه أكثر حساسية لضوضاء البكسل المفرد (تكلفة تشغيل النواة متطابقة -- تؤدي عملية الالتفاف العمل نفسه مهما كانت الأوزان). على صورة نظيفة ذات حواف قوية، يُعد بديلاً صالحاً تماماً عن Sobel.

تذهب Scharr في الاتجاه الآخر. أوزانها أكبر ومضبوطة من أجل الكشف الدقيق لاتجاه الحافة عند زوايا أدق:

scharr_x = [-3,   0,  3,
            -10,  0, 10,
            -3,   0,  3]

img.morph(1, scharr_x, mul=0.0625, add=128)

يُعيد المقسوم عليه mul=0.0625 (1/16) الخرج إلى داخل النطاق 0 -- 255 بعد مجموع الجداءات الأكبر. تُعد Scharr الإجابة الصحيحة عندما يحتاج التطبيق إلى أكثر استجابة تدرجية أمينة هندسياً ويكون مستعداً لدفع قدر أكبر قليلاً من العمليات الحسابية مقابلها.

5.17.3. اللابلاسي

تستجيب نواة اللابلاسي للحواف في أي اتجاه دفعة واحدة. حيث تكشف كل نواة من نوى Sobel تغيرات السطوع على طول محور واحد، يستجيب نمط الأوزان المتماثل للابلاسي بالطريقة نفسها بغض النظر عن الاتجاه الذي تسلكه الحافة:

laplacian_4 = [ 0, -1,  0,
               -1,  4, -1,
                0, -1,  0]

img.morph(1, laplacian_4, add=128)

الهيكل: وزن المركز 4، وأربعة جيران أفقيين/عموديين بوزن -1، والأقطار الأربعة بوزن صفر. مجموع أوزان النواة صفر، لذا تنتج الرقع المستوية خرجاً صفرياً. حيث يتغير السطوع، تختلف قيمة المركز عن متوسط جيرانه الأصليين الأربعة، ويكون الخرج بمقدار ذلك الفرق.

تتضمن النسخة ذات الاتصال الثماني الجيران القطريين:

laplacian_8 = [-1, -1, -1,
               -1,  8, -1,
               -1, -1, -1]

تكشف كل نواة أشياء مختلفة قليلاً. تنتج النسخة ذات الاتصال الرباعي خرجاً أنظف على الحواف الأفقية والعمودية؛ أما النسخة ذات الاتصال الثماني فهي أكثر تماثلاً في الاتجاهات -- تستجيب بالكفاءة نفسها في كل اتجاه -- لكنها تنتج خرجاً أكثر ضوضاءً قليلاً. تنتشر النواة ذات الاتصال الثماني أيضاً تحت اسم المخطط الخارجي، نسبةً إلى استخدامها في تصوير الحواف.

5.17.4. الإحداد

نواة الإحداد هي نواة الهوية مضافاً إليها نواة استجابة للحواف. الخرج هو الصورة الأصلية مضافاً إليها نسخة من الحواف، فتتضخم الميزات عالية التردد نسبةً إلى المناطق الداخلية الملساء.

تضيف نواة الإحداد القياسية ذات الاتصال الرباعي اللابلاسي ذا الاتصال الرباعي إلى نواة الهوية:

sharpen = [ 0, -1,  0,
           -1,  5, -1,
            0, -1,  0]

img.morph(1, sharpen)

قراءة النواة: وزن المركز هو identity (1) + Laplacian centre (4) = 5، وتطابق المحيطات محيطات اللابلاسي. تنتج الرقع المستوية 5 * 1 - 4 * 1 = 1 مضروباً في قيمة المركز -- أي نواة الهوية. تنتج الحواف القيمة الأصلية مضافاً إليها استجابة اللابلاسي. مجموع الأوزان هو 1، لذا يبقى mul و add على قيمهما الافتراضية.

للحصول على إحداد أقوى، تذهب النسخة ذات الاتصال الثماني إلى أبعد من ذلك:

sharpen_strong = [-1, -1, -1,
                  -1,  9, -1,
                  -1, -1, -1]

img.morph(1, sharpen_strong)

وزن المركز 9 هو identity (1) + Laplacian-8 centre (8). المنطق نفسه، مع تضخيم أكبر، وخطر أكبر بتضخيم ضوضاء المستشعر أيضاً.

إن نوى الإحداد القوية هي في جوهرها gaussian() مع unsharp=True، فقط معبَّراً عنها مباشرةً كنواة بدلاً من علامة قناع الإحداد. السلوك على مستوى البكسل هو نفسه؛ والاختيار هو بين راحة الطريقة المسماة والتحكم الدقيق لنواة مضبوطة يدوياً.

5.17.5. النقش البارز

تنتج نواة النقش البارز تأثير الإضاءة من الجانب الموجود في محررات الصور الكلاسيكية. يبدو الخرج وكأن الصورة قد بُثقت إلى نقش بارز ثم أُضيئت من إحدى الزوايا:

emboss = [-2, -1,  0,
          -1,  1,  1,
           0,  1,  2]

img.morph(1, emboss, add=128)

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

يؤدي تدوير عدم التماثل عبر القطر الآخر إلى النقش البارز من الاتجاه المعاكس:

emboss_alt = [ 0,  1,  2,
              -1,  1,  1,
              -2, -1,  0]

img.morph(1, emboss_alt, add=128)

يكون اتجاها النقش البارز مفيدين معاً -- بطرح أحدهما من الآخر، أو بتشغيل كل منهما على الصورة نفسها ومقارنة الاستجابات -- عندما يحتاج التطبيق إلى كشف التوجه.

5.17.6. التنعيم

نوى التنعيم هي العائلة التي يكون مجموع أوزانها واحداً (وكلها غير سالبة). تنتج الرقعة المستوية عبر نواة كهذه السطوع المستوي نفسه، لأن النواة تحسب متوسط قيم البكسلات معاً بدلاً من تضخيم فروقها.

أبسطها هو ضبابية الصندوق، وهي بالضبط ما تحسبه mean():

box_blur = [1, 1, 1,
            1, 1, 1,
            1, 1, 1]

img.morph(1, box_blur)

مجموع أوزان النواة هو 9، لذا تحوِّل القسمة التلقائية على مجموع النواة مجموعَ الجداءات إلى متوسط حقيقي على بكسلات الجوار التسعة. في الممارسة العملية، تُعد mean() الطريقة الأفضل لتشغيل هذه النواة -- فهي تنتج الخرج نفسه بشكل أسرع، عبر مسار محسَّن لحساب المتوسط ولا شيء غير ذلك، بينما يشغّل morph آلية الالتفاف العامة. توجد ضبابية الصندوق في الفهرس لأنها خط الأساس الصحيح لفهم كل نواة تنعيم أخرى.

يزِن تقريب 3 في 3 لـ Gaussian المركزَ والجيران الأصليين أكثر من الزوايا:

gaussian = [1, 2, 1,
            2, 4, 2,
            1, 2, 1]

img.morph(1, gaussian)

الأوزان هي صف مثلث باسكال 1, 2, 1 مضروباً ضرباً خارجياً بنفسه. وزن المركز 4 هو الأكبر لأن بكسل المركز يساهم بأكبر قدر في خرجه الخاص؛ والزوايا 1 لأنها الأبعد عن المركز. مجموع أوزان النواة هو 16، وتتولى القسمة التلقائية على مجموع النواة التطبيع -- دون الحاجة إلى وسيط mul. صيغة 3 في 3 هي تقريب خشن لنواة Gaussian حقيقية ولا يمكن تمييزها عن gaussian() عند size=1؛ وتكون صيغة morph مفيدة في الغالب عندما يريد التطبيق أن يدمج التنعيم مع عملية أخرى في المرور نفسه.

5.17.7. ضبابية الحركة

تحسب نواة ضبابية الحركة متوسط البكسلات على طول اتجاه واحد، تاركةً الاتجاه العمودي عليه دون تضبيب. أبسط حالة هي الأفقية:

motion_h = [0, 0, 0,
            1, 1, 1,
            0, 0, 0]

img.morph(1, motion_h)

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

motion_v = [0, 1, 0,
            0, 1, 0,
            0, 1, 0]

تستخدم ضبابية الحركة القطرية القطر الرئيسي:

motion_diag = [1, 0, 0,
               0, 1, 0,
               0, 0, 1]

img.morph(1, motion_diag)

تكون نوى ضبابية الحركة مفيدة سواء بوصفها تأثيراً (تضبيب إطار عمداً لأغراض بصرية) أو بوصفها نمط اختبار للخوارزميات التي يجب أن تكون متينة في مواجهة آثار الحركة (شغّل الخوارزمية على دخل مضبَّب بالحركة وتحقق من أنها لا تزال تنتج الإجابة الصحيحة).

5.17.8. قراءة النوى بنظرة سريعة

تجعل بضع قواعد إرشادية النوى الجديدة أسهل قراءةً للوهلة الأولى:

  • مجموع يساوي واحداً مع أوزان غير سالبة ⇐ تنعيم (يحافظ على متوسط السطوع).

  • مجموع يساوي صفراً مع أوزان موجبة وسالبة معاً ⇐ استجابة للحواف (صفر على الرقع المستوية).

  • مجموع يساوي واحداً مع مركز موجب كبير ومحيطات سالبة صغيرة ⇐ إحداد (نواة الهوية مضافاً إليها استجابة الحواف).

  • عدم تماثل عبر قطر مع مجموع يساوي واحداً ⇐ نقش بارز (يُبرز جانباً واحداً من كل انتقال للسطوع).

  • تركّز على طول محور واحد مع مجموع يساوي واحداً ⇐ تضبيب اتجاهي.

أول قاعدة من هذه القواعد تطابقها النواة هي عادةً التخمين الصحيح لما تفعله. معظم النوى المفيدة يمكن التعرف عليها من تخطيط نمط أوزانها وحده.

عندما لا تؤدي أي من النوى القياسية ما يريده التطبيق، فإن الخطوة التالية هي ضبط نواة يدوياً. يغطي مزيج القواعد أعلاه مع عناصر التحكم mul / add تقريباً كل مرور خطي رغبت فيه يوماً ما خطوط أنابيب الرؤية الآلية الكلاسيكية؛ ومن هناك تصبح المسألة مسألة تجربة أوزان، والنظر إلى الخرج، والتكرار.