6.4. Dtypes¶
ชนิดข้อมูลขององค์ประกอบใน ndarray เรียกว่า dtype ซึ่งกำหนดสามสิ่งในคราวเดียวกัน ได้แก่ จำนวนไบต์ที่แต่ละองค์ประกอบใช้ วิธีตีความไบต์เหล่านั้น และช่วงของค่าที่อาร์เรย์เก็บได้ การเลือก dtype ที่เหมาะสมเป็นการตัดสินใจสำคัญที่สุดที่ส่งผลต่อการใช้ RAM บนกล้อง
6.4.1. ชนิด dtype ที่รองรับ¶
numpy บนกล้องรองรับ dtype เพียงชุดเล็กๆ:
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 เริ่มต้นของทุก constructor บน การสร้างอาร์เรย์ คือ float ซึ่งแทบไม่ตรงกับความต้องการของแอปพลิเคชันเมื่อจัดการข้อมูลจาก sensor ควรระบุ 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. กฎการยกระดับชนิดข้อมูล¶
อาร์เรย์สองตัวที่มี dtype ต่างกันสามารถเป็นตัวดำเนินการของโอเปอเรเตอร์เดียวกันได้ numpy เลือกชนิดผลลัพธ์ตามตารางสั้นๆ:
ซ้าย |
ขวา |
ผลลัพธ์ |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ใดๆ |
|
|
แถว uint16 / int16 ยกระดับขึ้นเป็น float โดยตรง เนื่องจาก numpy บนกล้องไม่มี dtype จำนวนเต็ม 32 บิต
เมื่อโอเปอเรเตอร์ไบนารีมี Python scalar อยู่ด้านหนึ่ง scalar นั้นจะถูกแปลงเป็นอาร์เรย์ที่มีองค์ประกอบเดียวในชนิด dtype ที่เล็กที่สุดที่เหมาะสม: 123 กลายเป็นอาร์เรย์ uint8, -1000 กลายเป็น int16, Python float กลายเป็น 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 ไม่เคยล้นค่า (แต่จะยกระดับเป็น infinity แทน) ดังนั้นเทคนิคการแปลงชนิดจึงจำเป็นเฉพาะในกรณีจำนวนเต็มเท่านั้น