5.2. קואורדינטות ואזורים¶
עיבוד תמונה פועל על פיקסלים, וכדי לפעול על פיקסל אלגוריתם חייב לפנות אליו באמצעות קואורדינטה. כדי לפעול על מלבן של פיקסלים, אותו הדבר – יש לתאר את המלבן באופן שעליו האלגוריתם וקוד היישום מסכימים. המוסכמה שמודול image משתמש בה עבור קואורדינטות ומלבנים היא פשוטה, עם פרט אחד שמפתיע קוראים הרגילים למוסכמה מתמטית במקום למוסכמה של גרפיקה ממוחשבת, וכדאי להבהיר אותו מראש.
5.2.1. רשת הפיקסלים¶
הפיקסל (0, 0) הוא הפינה השמאלית-עליונה של תמונה. ציר ה-x פונה ימינה, כך ש-x גדול יותר משמעו רחוק יותר ימינה. ציר ה-y פונה כלפי מטה, כך ש-y גדול יותר משמעו רחוק יותר למטה בתמונה. תמונה בגודל רוחב על גובה מחזיקה פיקסלים בקואורדינטות שלמות מ-(0, 0) ועד (width - 1, height - 1); אין פיקסל ב-(width, 0) או ב-(0, height) – מיקומים אלה הם הקצוות הימני והתחתון, צעד אחד מעבר לפיקסל האמיתי האחרון בכל כיוון.
ציר ה-y הפונה כלפי מטה הוא הפרט שהוזכר לעיל. קורא הרגיל לגאומטריה של נייר משבצות מצפה ש-y גדול יותר יסמן גבוה יותר; כאן האינטואיציה הזו הפוכה לחלוטין. הסיבה להיפוך היא שחיישנים דיגיטליים וצגים דיגיטליים פועלים שניהם מהפינה השמאלית-עליונה וצועדים ימינה דרך כל שורה, מלמעלה למטה, ופריסת הפיקסלים בזיכרון באותו סדר הופכת את הקשר בין ”מיקום i בחוצץ (buffer)“ לבין ”שורה r, עמודה c של התמונה“ לחישוב הפשוט ביותר האפשרי – המיקום i של הפיקסל (x, y) הוא פשוט y * width + x. כל ספריית הדמיה הסכימה על הסידור הזה לפני עשרות שנים מאותה סיבה, והמחיר הוא התאמה מנטלית קטנה אחת בעבודה הראשונה עם תמונות.
מערכת הקואורדינטות של התמונה: ראשית הצירים בפינה השמאלית-עליונה, x פונה ימינה, y פונה כלפי מטה. אזור מלבני בתוך התמונה מוגדר על ידי פינתו השמאלית-עליונה (x, y) וממדיו (w, h).¶
5.2.2. מלבנים¶
רוב הפעולות על תמונה מתעניינות פחות בפיקסל בודד ויותר במלבן של פיקסלים – שטח להסתכל בו, אזור להעתיק החוצה, מסגרת בתוך מסגרת לחשב עליה סטטיסטיקות. הצורה לשם הגדרת מלבן בוחרת בהרחבה הפשוטה ביותר האפשרית של מוסכמת הפיקסל הבודד: יש לתת את קואורדינטת הפינה השמאלית-עליונה, ואחריה את ממדי המלבן, ארוזים ברביעייה (x, y, w, h). הפיקסלים בתוך המלבן נמצאים בעמודות x עד x + w - 1 ובשורות y עד y + h - 1.
הפרט שכדאי להבהיר כאן הוא ש-w ו-h הם גדלים, ולא קואורדינטות של הפינה הימנית-תחתונה. המלבן (10, 20, 4, 3) מכסה את העמודות 10, 11, 12, 13 ואת השורות 20, 21, 22 – שנים-עשר פיקסלים בסך הכול – ולא אזור הנמתח מ-(10, 20) עד (4, 3). המוסכמה אחידה בכל המודול, כך שברגע שמפנימים אותה הטעויות נפסקות, אך היא אכן מפילה אנשים בפעם הראשונה.
הצורה (x, y, w, h) מופיעה בשלושה מקומות שנראים שונים אך חולקים את אותה מוסכמה. הראשון הוא כאשר תמונה מתארת את טביעת הרגל של עצמה: המלבן המכסה את כל התמונה הוא (0, 0, width, height). השני הוא כאשר שיטת זיהוי מחזירה תוצאה עם תיבה תוחמת – blob, rect, apriltag – והתיבה מדווחת בחזרה כ-(x, y, w, h). השלישי הוא כאשר יש להורות לשיטה לעבוד על תת-אזור של התמונה במקום על הפריים כולו; ארגומנט מילת המפתח roi שמתחם את הפעולה מקבל את אותה רביעייה.
לקיחת תיבה תוחמת משיטה אחת והכנסתה אל ה-roi של השיטה הבאה היא אחד הדפוסים הנפוצים ביותר בעיבוד תמונה. התיבה התוחמת של זיהוי גס ראשון מצמצמת את שטח החיפוש עבור זיהוי עדין שני, ואוצר המילים האחיד בין תוצאות הזיהוי לבין ארגומנטי השיטות הוא מה שהופך את הדפוס לכל כך פשוט – צורת רביעייה אחת, המשמשת באותו אופן בשני צדי המעבר.
5.2.3. כתובות שלמות, מרכזי כובד שבריריים¶
כתובות הפיקסלים עצמן הן מספרים שלמים. פיקסל נמצא או אינו נמצא בעמודה ובשורה שלמה נתונה, והשאלה מה נמצא בקואורדינטה (40.5, 30.7) אינה שאלה תקנית – אין פיקסל היושב בדיוק במיקום הזה. עם זאת, מקצת מהכמויות שמודול image גוזר ממיקומי פיקסלים הן שבריריות, וכדאי להבין מדוע כדי שההבחנה לא תפיל את היישום בהמשך.
המקרה הנפוץ ביותר הוא המרכז כובד (centroid) – מרכז המסה של אזור. עבור אזור מחובר של פיקסלים, מרכז הכובד בצורה של נקודה צפה הוא הממוצע של מיקומי הפיקסלים החברים, משוקלל לפי צפיפותם. אזור שהפיקסלים שלו משתרעים על פני שתי עמודות יהיה בעל מרכז כובד x של, למשל, 41.6 – מיקום אמיתי שהעין הייתה מתארת כ“אמצע האזור הזה“ אף שאף פיקסל ממשי אינו יושב בדיוק ב-x הזה. עצמי תוצאת הזיהוי נושאים את שתי הצורות כתכונות לקריאה בלבד: זוג שלמים (cx / cy, שימושי כשמזינים את המיקום בחזרה אל משהו שרוצה קואורדינטות פיקסל שלמות) וזוג נקודה צפה (cxf / cyf, שימושי כשהמיקום נכנס ללולאת בקרה שנהנית מרזולוציית תת-פיקסל).
המקרה האחר הוא תזוזה בין שני פריימים הנמדדת במרחב התדר. טכניקות המנתחות את התוכן הספקטרלי של תמונה ולא את הפיקסלים שלה ישירות יכולות לפענח הזחות עדינות מפיקסל בודד, והן מדווחות על הזחות אלה כערכי נקודה צפה (dx, dy).
כלל אצבע: כתובות פיקסלים הן מספרים שלמים; מיקומים והזחות שיוצאים מאלגוריתם יכולים להיות מספרי נקודה צפה. שיטות ציור מקבלות כל אחת מהצורות ומעגלות מספרי נקודה צפה כלפי מטה אל הפיקסל השלם הקרוב ביותר כאשר התוצאה חייבת לנחות על הרשת.
5.2.4. קרטזי וקוטבי¶
המערכת שתוארה עד כה היא קרטזית: כל פיקסל מוגדר על ידי ההיסט האופקי והאנכי שלו מראשית הצירים. זוהי המערכת שבה הבתים מאוחסנים – הפיקסל i בחוצץ (buffer) מתאים לפיקסל בעמודה i % width ובשורה i // width, תוך צעידה דרך השורות מלמעלה – וזוהי המערכת שבה כל שיטה פועלת כברירת מחדל.
ייצוג שני כדאי להכיר משום שאלגוריתמים מסוימים עובדים בו הרבה יותר טוב. קואורדינטות קוטביות מגדירות כל פיקסל לפי המרחק שלו מנקודת מרכז נבחרת ולפי הזווית בינו לבין כיוון ייחוס. הפיקסלים של התמונה לא זזו – הבתים עדיין נמצאים באותו חוצץ בסדר שורות – אך שיטת המיעון עברה מ“כמה רחוק ימינה וכמה רחוק למטה“ אל ”כמה רחוק מהמרכז ובאיזו זווית סביבו.“
אותה נקודה P, מוגדרת בשתי דרכים: קרטזית (x, y) מראשית הצירים השמאלית-עליונה, קוטבית (r, theta) ממרכז נבחר.¶
מדוע לטרוח להחליף? בגלל שתי זהויות ההופכות חיפושים קשים לקלים.
בקואורדינטות קוטביות, סיבוב התמונה סביב המרכז הנבחר הוא אותה פעולה כמו הסטת הפיקסלים שלה לאורך ציר הזווית – כיוון ה-x בתמונה המוטלת מחדש. עותק מסובב הוא המקור המוזח שמאלה או ימינה בצורה קוטבית.
בגרסת ה-לוג-קוטבית – ציר המרחק משתמש בקנה מידה לוגריתמי, ציר הזווית נשאר לינארי – שינוי קנה המידה של התמונה סביב המרכז הנבחר הוא אותה פעולה כמו הסטת הפיקסלים שלה לאורך ציר המרחק – כיוון ה-y. עותק שעבר שינוי קנה מידה הוא המקור המוזח מעלה או מטה בצורה לוג-קוטבית.
כך אלגוריתם שצריך לזהות תבנית ידועה תחת סיבוב או שינוי קנה מידה יכול לבצע את החיפוש שלו במרחב קוטבי, שבו שתי הטרנספורמציות הופכות להסטות רגילות. הסטות זולות הרבה יותר לחיפוש מאשר סיבובים ושינויי קנה מידה, וההטלה מחדש הקוטבית היא מה שמאפשר את ההחלפה.
קואורדינטות קוטביות אינן מחליפות את הקרטזיות לאחסון פיקסלים; הבתים תמיד חיים על הרשת הקרטזית. המודול מספק זוג שיטות המטילות מחדש תמונה מצורה קרטזית לצורה קוטבית לפי דרישה, האלגוריתם הזקוק לקואורדינטות קוטביות מבצע את עבודתו, ואז התוצאה מוטלת בחזרה החוצה או שהמדידה במרחב הקוטבי משמשת ישירות. מנגנון זה הוא הסיבה היחידה לכך שקואורדינטות קוטביות מופיעות בכלל באיזשהו מקום בממשק המודול.
עם קואורדינטות קרטזיות להגדרת פיקסלים בודדים, הרביעייה (x, y, w, h) להגדרת מלבנים שלהם, וקואורדינטות קוטביות הזמינות כאשר אלגוריתם נהנה מהן, ליישום יש אוצר מילים שלם להגדרה היכן בתמונה משהו נמצא. מה שבאמת מאוחסן בכל אחד מהמיקומים הללו הוא השכבה הבאה של היסוד.