קווים נייחים

סיכום

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

https://g.co/LandLines

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

פריסת דמיון t-sne
פריסת t-sne דמיון, רזולוציה גבוהה 50 mb

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

זיהוי קו

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

פיתחתי גרסה קודמת של החיפוש על ידי שרטוט אלגוריתם בפרויקט עם Local Projects, ולצורך כך רשמנו הערות לשורות שצריך לחפש. היה כיף לצייר על יצירות אמנות, אבל היה מתיש כשעוברים מעשרות תמונות לאלפי תמונות. רציתי לנסות להפוך את התהליך לחיפוש קווים לאוטומטי.

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

התנסיתי עם מגוון אלגוריתמים לזיהוי קווים, כולל אלגוריתמים חדשים כמו gPb (PDF). האלגוריתמים קיבלו תוצאות מדהימות, אבל נדרשו דקות כדי להפעיל כל תמונה. בסוף הגעתי לזיהוי של קצוות מיוערים מובְנים, אלגוריתם שמשויך ל-openCV.

אחרי שהייתה לי "תמונת קו" טובה, עדיין הייתה לי בעיה להבין את הקווים ולזהות שורות נפרדות אחד מהשני. כלומר, איך אני יכול לקחת את נתוני רשת הנקודות האלה ולהפוך אותם לווקטורים. לעיתים קרובות, כשאני מנסה לפתור בעיות ראייה ממוחשבת, אני חוקר את imageJ, סביבת עיבוד תמונות בקוד פתוח של Java שבה משתמשים מדענים וחוקרים, עם מערכת אקולוגית תקינה של יישומי פלאגין. מצאתי פלאגין בשם זיהוי רידג' שעוזר לצלם תמונת עוצמה ולהפוך אותה לקבוצה של קטעי קו. (הערה: הקוד לזיהוי הקצוות ולהוספת תוויות מ-Matlab מועיל).

תמונה עם קטעי קו שזוהו
תמונה עם קטעי קו שזוהו

Serverless

רציתי גם לבדוק אם אפשר ליצור אפליקציה להצגה חזותית של נתונים ללא שרת במהותו, שבה העבודה הקשה של התאמה וחיבור מתרחשת בצד הלקוח. בדרך כלל אני עובד/ת ב-openFrameworks, שהיא מסגרת c++ לקידוד קריאייטיב. מלבד הפרויקט של הצומת שמזדמן, לא התעסקתי הרבה בתכנות בצד השרת. מעניין אותי אם אפשר לבצע את כל החישובים בצד הלקוח, ולהשתמש בשרת רק כדי להציג נתונים של JSON ותמונות.

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

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

אתגר נוסף בשימוש בלי שרת הוא לטעון את הנתונים למכשיר נייד – לצורך השרטוט, הנתונים בקטעי העצים והקווים היו גדולים מ-12MB והתמונות גדולות למדי, רצינו שחוויית השימוש תהיה מהירה ורספונסיבית. המטרה היא לנסות להוריד את הקובץ בגודל קטן. הפתרון שלנו היה לטעון נתונים בהדרגה. באפליקציית השרטוט, פיצלנו את הנתונים של עץ נקודת התצפית ל-5 חלקים. כשהאפליקציה נטענת היא טוענת רק את המקטע הראשון. לאחר מכן, בכל 10 שניות היא טוענת קטע נוסף של נתונים ברקע, כך שלמעשה האפליקציה משתפרת ומשתפרת כבר בדקה הראשונה של השימוש בה. באפליקציית הגרירה עבדנו קשה גם כדי לשמור תמונות במטמון, כך שתמונות חדשות נטענות ברקע בזמן הגרירה.

לסיום, אחד הדברים שגיליתי קשה מהצפוי הוא ליצור טוען מראש לשתי האפליקציות, כך שהעיכוב הראשוני בטעינת הנתונים היה מובן. השתמשתי בקריאה חוזרת (callback) בבקשות ajax ובצד pixi.js, תמונות שנבדקו ונטענות באופן אסינכרוני כבר נטענו, והשתמשו בהן כדי להפעיל את ההודעה לטעינה מראש.

קו מחובר

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

הקווים הטובים לחיבור מסומנים באדום הקווים הטובים לחיבור מסומנים באדום
הקווים הטובים לחיבור מסומנים באדום

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

אם מחשיבים את הקו כשינוי בזווית ולא כנקודות, קל יותר לשלב קווים לקו גדול יותר עם פחות אי-רציפות – במקום לחבר נקודות, פשוט מוסיפים שינויי זוויות יחסיים. כדי להוסיף קו, לוקחים את הזווית הנוכחית של הקו הראשי0 ומוסיפים לה את השינויים היחסיים של הקו שרוצים להוסיף.

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

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

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