6.4. Dtype

ndarray의 요소 타입이 그 배열의 dtype입니다. dtype은 한 번에 세 가지를 결정합니다. 각 요소가 차지하는 바이트 수, 바이트를 해석하는 방식, 그리고 배열이 저장할 수 있는 값의 범위입니다. 올바른 dtype을 선택하는 것은 카메라의 RAM 사용량에 영향을 미치는 가장 중요한 단일 결정입니다.

6.4.1. 지원되는 dtype

카메라의 numpy는 소수의 dtype 집합을 지원합니다:

dtype

바이트

범위

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

int32int64는 없으며, OpenMV의 ulab 빌드는 선택적 complex dtype을 활성화하지 않습니다.

데이터를 생성한 하드웨어에 맞는 타입을 선택하세요. 8비트 ADC 샘플에는 uint8이 적합하고, 12비트 ADC 샘플은 uint16에 들어맞으며, 그레이스케일 카메라의 휘도 픽셀은 uint8에 들어맞아 기본 float가 소비할 RAM의 4분의 1만 사용합니다.

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. 업캐스팅 규칙

서로 다른 dtype을 가진 두 배열이 같은 연산자의 피연산자가 될 수 있습니다. numpy는 짧은 표에 따라 결과 타입을 선택합니다:

왼쪽

오른쪽

결과

uint8

int8

int16

uint8

int16

int16

uint8

uint16

uint16

int8

int16

int16

int8

uint16

uint16

uint16

int16

float

임의

float

float

uint16 / int16 행은 카메라의 numpy에 32비트 정수 dtype이 없기 때문에 곧바로 float로 승격됩니다.

이항 연산자의 한쪽에 Python 스칼라가 있으면, 그 스칼라는 가장 작은 적합한 dtype의 단일 요소 배열로 변환됩니다. 123uint8 배열이 되고, -1000int16이 되며, Python floatfloat가 됩니다.

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 배열은 결코 오버플로되지 않으므로(대신 무한대로 승격됨) 캐스팅 기법은 정수의 경우에만 필요합니다.