5.6. رسم الأشكال والنصوص

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

5.6.1. العناصر البدائية

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

  • draw_line() -- مقطع خط مستقيم بين نقطتي نهاية.

  • draw_rectangle() -- مستطيل محاذٍ للمحاور، مجوّف أو مملوء.

  • draw_circle() -- دائرة حول مركز، مجوّفة أو مملوءة.

  • draw_ellipse() -- قطع ناقص بدوران اختياري.

  • draw_cross() -- علامة زائد عند نقطة، وهي العلامة المعتادة لمركز ثقل أو هدف نقر.

  • draw_arrow() -- سهم من نقطة بداية إلى نقطة نهاية.

  • draw_edges() -- الأضلاع الأربعة لشكل رباعي اعتباطي، بإعطاء نقاط الزوايا الأربع؛ وهي الطريقة الطبيعية لتحديد مخطط وسم مكتشف أو منطقة مشوّهة بالمنظور.

  • draw_string() -- نص من خط نقطي مدمج.

تعدّل كل واحدة من هذه الدوال الصورة المصدرية في مكانها وتُعيد الصورة نفسها للتسلسل، اتباعًا لاصطلاح دوال التشغيل المقرر سابقًا.

A grid of small panels showing each of the eight drawing primitives applied once. Each panel contains a line, a rectangle, a circle, an ellipse, a cross, an arrow, a quadrilateral, or a short text string, with the name of the method that produced it labelled underneath.

العناصر البدائية الثمانية للرسم، واحد لكل لوحة. تصنع كل دالة نوعًا واحدًا من العلامات.

5.6.2. اللون

تأخذ كل دالة رسم معامل color الذي يقرر القيمة التي تُكتب في كل بكسل مرسوم. والصيغة التي يتخذها ذلك المعامل تعتمد على تنسيق الصورة. فبالنسبة إلى صورة RGB565، تكون الصيغة الطبيعية صفًا (r, g, b) مع كل قناة في المدى 0 -- 255؛ وتحزم الوحدة ذلك في كلمة RGB565 بحجم 16 بت قبل كتابته. أما بالنسبة إلى صورة بتدرج الرمادي فالصيغة الطبيعية عدد صحيح وحيد للسطوع من 0 (أسود) حتى 255 (أبيض). وتقبل الدوال أيضًا القيمة المخزّنة الخام للتنسيق -- كلمة محزومة بحجم 16 بت لـ RGB565، وعدد صحيح بحجم 8 بت لتدرج الرمادي -- وهي الصيغة الفعّالة عندما يكون اللون قد حُسب في مكان آخر وأصبح بالفعل في الصيغة المخزّنة.

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

5.6.3. السماكة والملء

تأخذ معظم الدوال الهندسية علامتين تقرران كيفية رسم العلامة:

  • يضبط thickness=N عرض الخط بالبكسل. والقيمة الافتراضية هي 1، وهي مناسبة لمعظم الطبقات الفوقية؛ وتكون القيمة الأكبر مفيدة عندما يتعين أن يبقى تعليق توضيحي مرئيًا أمام مشهد مزدحم أو بعد أن تعدّل مرحلة لاحقة من خط الأنابيب الصورة أكثر.

  • يبدّل fill=True العلامة من مخطط إلى علامة صلبة، فيرسم كل بكسل داخلي باللون المختار. والقيمة الافتراضية هي False.

لا تنطبق هاتان العلامتان على العناصر البدائية التي ليس لها داخل لملئه -- الخط وعلامة الزائد والسهم والشكل الرباعي -- حيث يكون thickness وحده ذا معنى.

5.6.4. رسم النصوص

draw_string() يكتب الأحرف من خط نقطي مدمج بحجم 8 في 10 بكسلات. و x و y هما الزاوية العلوية اليسرى لخلية الحرف الأول، و text هي السلسلة المراد رسمها، و color يتبع الاصطلاح ذاته للدوال الهندسية. ويحمل الخط مدى ASCII القابل للطباعة كاملًا وليس فيه ضبط بيني للأحرف -- إذ يشغل كل حرف الخلية ذاتها بعرض 8 بكسلات -- مما يجعل تحديد موضع المخرجات سهلًا.

img.draw_string(10, 10, "blobs: 3", color=(0, 255, 0))

يمكن أن تتضمن السلسلة أسطرًا جديدة (\n)؛ ينقل كل سطر جديد الحرف التالي إلى بداية سطر جديد عشرة بكسلات أسفل السطر السابق. ويرسم معامل scale كل حرف بحجم أكبر بعامل عشري، ويضيف x_spacing و y_spacing حشوًا حول كل حرف. وتنطبق مجموعة صغيرة من علامات التدوير / الانعكاس / القلب إما على السلسلة بأكملها أو على كل حرف بمفرده -- بما يكفي من التحكم لترتيب النص على طول زاوية أو أمام حافة غير أفقية عندما يستدعي التخطيط ذلك.

5.6.5. مسح اللوحة

إحدى الدوال في العائلة لا ترسم أي علامة محددة. فهي تعيد ببساطة ضبط كل بكسل في الصورة إلى صفر:

  • clear() -- يصفّر كل بكسل، مع إمكانية تقييده اختياريًا بمنطقة اهتمام أو حصره عبر قناع.

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

تكون الصورة المخصصة حديثًا صفرًا بالفعل من المُنشئ، لذا فإن clear() يهم تحديدًا للمخازن المؤقتة المعاد استخدامها بين الإطارات.