6.4. أنواع البيانات (Dtypes)

نوع العنصر في ndarray هو نوع البيانات (dtype) الخاص به. ويحدد نوع البيانات ثلاثة أشياء في آن واحد: عدد البايتات التي يشغلها كل عنصر، وكيفية تفسير تلك البايتات، ونطاق القيم التي يمكن للمصفوفة تخزينها. واختيار نوع البيانات الصحيح هو أكبر قرار منفرد يؤثر على استخدام RAM في الكاميرا.

6.4.1. أنواع البيانات المدعومة

يدعم numpy على الكاميرا مجموعة صغيرة من أنواع البيانات:

نوع البيانات

البايتات

النطاق

uint8

1

0 إلى 255

int8

1

-128 إلى 127

uint16

2

0 إلى 65,535

int16

2

-32,768 إلى 32,767

float

4

أحادي الدقة وفق معيار IEEE 754

bool

1

True / False

لا يوجد int32 أو int64، كما أن بنية ulab الخاصة بـ OpenMV لا تُفعّل نوع البيانات الاختياري complex.

اختر النوع الذي يطابق العتاد الذي أنتج البيانات. فعينة ADC بطول 8 بتات تتطلب uint8؛ وعينة ADC بطول 12 بت تتسع في uint16؛ وبكسل سطوع من كاميرا بتدرج الرمادي يتسع في uint8 -- مما يوفر أربعة أضعاف الذاكرة RAM التي كان سيكلفها نوع float الافتراضي.

6.4.2. نوع البيانات الافتراضي

نوع البيانات الافتراضي لكل مُنشئ في إنشاء المصفوفات هو float. ونادرًا ما يكون ذلك ما يريده التطبيق عند التعامل مع بيانات المستشعر. مرّر dtype= صراحةً كلما كان العرض الطبيعي أصغر:

sensor = np.array(samples, dtype=np.uint16)

إعادة تغليف مصفوفة أعداد صحيحة دون وسيط dtype= تنسخ البيانات و تحوّلها إلى float، وهو ما يكلف وقتًا ويكلف RAM. وعندما يكون الأداء مهمًا، حدّد نوع البيانات بالاسم.

6.4.3. نوع البيانات لمصفوفة موجودة

تقرأ 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 -- لذا فإن مقارنة نوع البيانات مع ثابت الوحدة هي الطريقة التي يتفرع بها البرنامج النصي بناءً على ما تحتويه المصفوفة:

if a.dtype == np.uint8:
    ...  # uint8 branch

6.4.4. قواعد الترقية النوعية (Upcasting)

يمكن أن تكون مصفوفتان من أنواع بيانات مختلفة معاملين لنفس العامل. ويختار numpy نوع النتيجة وفقًا لجدول قصير:

اليسار

اليمين

النتيجة

uint8

int8

int16

uint8

int16

int16

uint8

uint16

uint16

int8

int16

int16

int8

uint16

uint16

uint16

int16

float

أي نوع

float

float

يرتقي صف uint16 / int16 مباشرة إلى float لأن numpy على الكاميرا لا يملك نوع بيانات عدد صحيح بطول 32 بت.

عندما يكون لدى عامل ثنائي قيمة عددية من Python على أحد جانبيه، تُحوّل القيمة العددية إلى مصفوفة أحادية العنصر من أصغر نوع بيانات مناسب: تصبح 123 مصفوفة uint8، وتصبح -1000 من نوع int16، وتصبح قيمة float في Python من نوع float.

6.4.5. تجاوز الأعداد الصحيحة يلتف

تحافظ العمليات على مصفوفتين من نفس نوع بيانات العدد الصحيح على ذلك النوع، حتى عندما تتجاوز النتيجة الحد. فيُسقَط الفائض بصمت:

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. وعندما يحتاج ناتج وسيط إلى نطاق أكبر مما يسمح به نوع بيانات الإدخال، اعمل التحويل النوعي أولًا:

c = np.array(a, dtype=np.uint16) + b
# array([300, 300], dtype=uint16)

تنطبق هذه القاعدة على كل عامل أعداد صحيحة -- + و- و* و// و% و& و| و^. ومصفوفات float لا تتجاوز الحد أبدًا (بل تترقى إلى ما لا نهاية بدلًا من ذلك)، لذا فإن حيلة التحويل النوعي لازمة فقط في حالة الأعداد الصحيحة.