5.6. ציור צורות וטקסט

אלגוריתם שמחליט משהו לגבי תמונה צריך לעיתים קרובות שההחלטה הזו תהיה גלויה. מזהה רכיבים (blob) מוצא אזור שהיישום מתעניין בו; היישום רוצה שהאזור יצויר על הפריים כך שמפעיל – או המפתח שמריץ את הסקריפט – יוכל לראות מה נמצא. טרנספורמציית קואורדינטות ממפה מיקום קלט למיקום פלט; ניפוי הבאגים שלה משמעו בדרך כלל סימון שני המיקומים על אותה תמונה. התצוגה המקדימה ב-IDE קוראת את כל מה שיושב בחוצץ הפריימים (frame buffer) ברגע שהיא דוגמת אותו, ולכן הדרך הפשוטה ביותר להפוך את פלט האלגוריתם לגלוי היא לכתוב הערות לתוך חוצץ הפריימים עצמו. משפחת הציור במחלקה Image היא ערכת הכלים לעבודה הזו בדיוק.

5.6.1. הפרימיטיבים

כל מתודת ציור מציבה סוג אחד ספציפי של סימן על התמונה. הקטלוג קטן ונשאר קרוב לפרימיטיבים הגאומטריים שהערה אכן זקוקה להם:

  • draw_line() – מקטע קו ישר בין שתי נקודות קצה.

  • draw_rectangle() – מלבן מיושר לצירים, חלול או מלא.

  • draw_circle() – מעגל סביב מרכז, חלול או מלא.

  • draw_ellipse() – אליפסה בעלת סיבוב שרירותי.

  • draw_cross() – סימן פלוס בנקודה, הסימן המקובל למרכז מסה (centroid) או למטרת לחיצה.

  • draw_arrow() – חץ מנקודת התחלה אל נקודת סיום.

  • draw_edges() – ארבע הצלעות של מרובע שרירותי, בהינתן ארבע נקודות הפינה; הדרך הטבעית להתוות תג שזוהה או אזור שעוות בפרספקטיבה.

  • draw_string() – טקסט מגופן bitmap מובנה.

כל אחת מהן משנה את תמונת המקור במקומה ומחזירה את אותה תמונה לצורך שרשור, בהתאם למוסכמת המתודה התפעולית שהתבססה קודם לכן.

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, הצורה הטבעית היא רשומה (tuple) של (r, g, b) כאשר כל ערוץ בטווח 0255; המודול אורז זאת אל מילת RGB565 של 16 ביט לפני כתיבתה. עבור תמונה בגווני אפור הצורה הטבעית היא מספר שלם בודד של בהירות מ-0 (שחור) עד 255 (לבן). המתודות מקבלות גם את הערך הגולמי המאוחסן של הפורמט – מילה ארוזה של 16 ביט עבור RGB565, מספר שלם של 8 ביט עבור גווני אפור – שהיא הצורה היעילה כאשר הצבע חושב במקום אחר וכבר נמצא בצורה המאוחסנת.

השמטת הארגומנט color מציירת בלבן. ברירת מחדל זו נוחה לעבודה בגווני אפור, שבה לבן הוא הערך המרבי ונקרא בבירור על רוב הרקעים. עבור שכבות על לניפוי באגים ב-RGB565 היא כמעט תמיד שגויה: ירוק או אדום בדרך כלל נקראים טוב יותר על סוג הסצנה שמצלמה אכן רואה, וצבע מפורש מתקשר את הכוונה.

5.6.3. עובי ומילוי

רוב המתודות הגאומטריות מקבלות שני דגלים שקובעים כיצד הסימן מצויר:

  • thickness=N קובע את רוחב הקו בפיקסלים. ברירת המחדל היא 1, שמתאימה לרוב שכבות העל; ערך גדול יותר שימושי כאשר הערה צריכה להישאר גלויה על רקע סצנה עמוסה או לאחר ששלב מאוחר יותר בצנרת משנה את התמונה עוד.

  • fill=True מחליף את הסימן ממתאר למלא, וצובע כל פיקסל פנימי בצבע הנבחר. ברירת המחדל היא False.

דגלים אלה אינם חלים על הפרימיטיבים שאין להם פנים למלא – הקו, הצלב, החץ, המרובע – שבהם רק thickness הוא בעל משמעות.

5.6.4. ציור טקסט

draw_string() כותב תווים מתוך גופן bitmap מובנה בגודל 8 על 10 פיקסלים. x ו-y הם הפינה השמאלית-עליונה של תא התו הראשון, text היא המחרוזת לציור, ו-color עוקב אחר אותה מוסכמה כמו המתודות הגאומטריות. הגופן נושא את כל טווח ה-ASCII הניתן להדפסה ואין לו kerning – כל תו תופס את אותו תא ברוחב 8 פיקסלים – מה שמקל על מיקום הפלט.

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

המחרוזת יכולה לכלול תווי שורה חדשה (\n); כל תו שורה חדשה מעביר את התו הבא לתחילת שורה חדשה עשרה פיקסלים מתחת לקודמת. הארגומנט scale מצייר כל תו בגודל גדול יותר לפי גורם של מספר ממשי, ו-x_spacing ו-y_spacing מוסיפים ריווח סביב כל תו. קבוצה קטנה של דגלי סיבוב / שיקוף / היפוך חלה על המחרוזת כולה או על כל תו בנפרד – מספיק שליטה כדי לפרוס טקסט לאורך זווית או על גבי קצה לא אופקי כשהפריסה דורשת זאת.

5.6.5. ניקוי בד הציור

מתודה אחת במשפחה אינה מציירת שום סימן ספציפי. היא פשוט מאפסת כל פיקסל של התמונה לאפס:

  • clear() – מאפסת כל פיקסל, אופציונלית מוגבלת ל-ROI או ממוקדת דרך מסכה.

clear() היא התשובה הנכונה כאשר יישום מרכיב הערה מאפס בכל פריים – מתחילים עם בד ציור שחור, מציירים את ההערות החדשות, מוסרים את התוצאה לתצוגה – במקום לצייר שכבת על מעל הפריים שנלכד. זו גם הדרך הזולה ביותר להכין תמונה זמנית לשימוש כחוצץ מסכה.

תמונה שזה עתה הוקצתה היא כבר מאופסת מהבנאי, ולכן clear() חשובה במיוחד עבור חוצצים שנעשה בהם שימוש חוזר בין פריים לפריים.