6.4. Dtypes¶
סוג האיברים של ndarray הוא ה-dtype שלו. ה-dtype מכריע שלושה דברים בבת אחת: כמה בתים תופס כל איבר, כיצד מפרשים את הבתים, ואיזה טווח ערכים יכול המערך לאחסן. בחירת ה-dtype הנכון היא ההחלטה היחידה הגדולה ביותר המשפיעה על השימוש ב-RAM של המצלמה.
6.4.1. ה-dtypes הנתמכים¶
numpy על המצלמה תומך בקבוצה קטנה של dtypes:
dtype |
בתים |
טווח |
|---|---|---|
|
1 |
0 עד 255 |
|
1 |
-128 עד 127 |
|
2 |
0 עד 65,535 |
|
2 |
-32,768 עד 32,767 |
|
4 |
IEEE 754 דיוק יחיד |
|
1 |
|
אין int32 או int64, ובניית ulab של OpenMV אינה מפעילה את ה-dtype האופציונלי complex.
בחר את הסוג התואם לחומרה שהפיקה את הנתונים. דגימת ADC של 8 סיביות זקוקה ל-uint8; דגימת ADC של 12 סיביות נכנסת ב-uint16; פיקסל בהירות ממצלמת גווני אפור נכנס ב-uint8 – וחוסך פי ארבעה מה-RAM שברירת המחדל float הייתה עולה.
6.4.2. ברירת המחדל של dtype¶
ברירת המחדל של dtype בכל בנאי שב-יצירת מערכים היא float. לעיתים רחוקות זה מה שהיישום רוצה כאשר מטפלים בנתוני חיישן. העבר dtype= במפורש בכל פעם שהרוחב הטבעי קטן יותר:
sensor = np.array(samples, dtype=np.uint16)
עטיפה מחדש של מערך שלמים ללא ארגומנט dtype= מעתיקה וגם ממירה ל-float, מה שעולה גם בזמן וגם ב-RAM. כשהביצועים חשובים, ציין את ה-dtype בשמו.
6.4.3. ה-dtype של מערך קיים¶
dtype מחזיר את ה-dtype של המערך בתור קוד הסוג השלם שהמערך נושא בתוכו:
a = np.array([1, 2, 3], dtype=np.uint8)
print(a.dtype) # 66 (the integer value of ``'B'``)
השלמים של קוד הסוג תואמים לקבועים הנחשפים במודול numpy – numpy.uint8, numpy.int8, numpy.uint16, numpy.int16, numpy.float, numpy.bool – כך שהשוואת ה-dtype אל קבוע המודול היא הדרך שבה סקריפט מתפצל לפי מה שמערך מכיל:
if a.dtype == np.uint8:
... # uint8 branch
6.4.4. כללי העלאת סוג¶
שני מערכים בעלי dtypes שונים יכולים להיות אופרנדים של אותו אופרטור. numpy בוחר את סוג התוצאה לפי טבלה קצרה:
שמאל |
ימין |
תוצאה |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
כל |
|
|
השורה של uint16 / int16 מקודמת ישירות ל-float משום של-numpy על המצלמה אין dtype שלם בן 32 סיביות.
כאשר לאופרטור בינארי יש סקלר של Python בצד אחד, הסקלר מומר למערך בן איבר יחיד מה-dtype המתאים ה-קטן ביותר: 123 הופך למערך uint8, -1000 הופך ל-int16, ו-float של Python הופך ל-float.
6.4.5. גלישת שלמים מתגלגלת¶
פעולות על שני מערכים מאותו dtype שלם שומרות על אותו dtype, גם כאשר התוצאה גולשת. הנשא מושמט בשקט:
a = np.array([200, 200], dtype=np.uint8)
b = np.array([100, 100], dtype=np.uint8)
print(a + b)
פלט:
array([44, 44], dtype=uint8)
התוצאה היא 300 mod 256 == 44. כאשר ביניים זקוק לטווח גדול יותר מזה ש-dtype הקלט מאפשר, בצע המרה תחילה:
c = np.array(a, dtype=np.uint16) + b
# array([300, 300], dtype=uint16)
כלל זה חל על כל אופרטור שלמים – +, -, *, //, %, &, |, ^. מערכי float לעולם אינם גולשים (הם מתקדמים לאינסוף במקום), ולכן טריק ההמרה נחוץ רק במקרה השלם.