6.18. 이미지와 ndarray

Image 클래스는 카메라 네이티브 픽셀 작업을 위한 빠른 표면입니다. 이 클래스의 모든 메서드는 카메라의 네이티브 픽셀 형식으로 된 프레임 버퍼에 직접 작동합니다. numpy 는 그 외 모든 작업을 위한 범용 수치 표면입니다. 두 메서드가 이 둘을 연결합니다:

이 둘을 함께 사용하면 애플리케이션이 프레임을 캡처하여 numpy 에 넘겨 사용자 정의 변환을 수행한 다음, 그 결과를 다시 이미지로 되돌려 표시하거나 저장하거나 이미지 라이브러리의 나머지 부분에 다시 공급할 수 있습니다.

6.18.1. 이미지를 ndarray로

to_ndarray() 는 새 ndarray 를 할당하고 이미지의 픽셀 데이터를 (아래의 dtype 매핑에 따라) 그 안으로 복사합니다. 이것은 결코 이미지의 프레임 버퍼에 대한 뷰가 아닙니다 – numpy 배열은 항상 자신의 바이트를 소유합니다. 시그니처는 to_ndarray(dtype, *, buffer=None) 이며, 출력 형태는 이미지 형식에 따라 달라집니다:

  • GRAYSCALE – 2차원 배열, 형태 (height, width).

  • RGB565 – 3차원 배열, 형태 (height, width, 3), 평면은 R/G/B 순서입니다.

dtype 인수는 각 8비트 픽셀 값 v 가 어떻게 매핑되는지를 제어합니다:

dtype

요소

8비트 픽셀 값 v 에 대한 매핑

'B'

uint8

v (원시 값)

'b'

int8

v - 128 (0을 중심으로 재조정)

'f'

float32

float(v) (0.0 … 255.0)

예제 – 그레이스케일 프레임을 uint8 행렬로 보기:

import csi
from ulab import numpy as np

csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.GRAYSCALE)
csi0.framesize(csi.QVGA)

img = csi0.snapshot()
a   = img.to_ndarray('B')        # shape (240, 320), dtype=uint8

print(a.shape, a.dtype)
print("mean brightness:", np.mean(a))

buffer= 키워드를 사용하면 애플리케이션이 이미 할당한 bytearray 를 재사용할 수 있으므로, 카메라가 매 프레임마다 새 버퍼를 할당할 필요가 없습니다:

buf = bytearray(320 * 240)
while True:
    img = csi0.snapshot()
    a   = img.to_ndarray('B', buffer=buf)
    # ... process a ...

6.18.2. ndarray를 이미지로

반대 방향으로 가려면 ndarrayimage.Image 의 첫 번째 인수로 전달하십시오. 생성자는 새 이미지 버퍼를 할당하고 배열의 값을 0..255 범위로 클램핑 및 반올림하여 그 안으로 복사합니다:

image.Image(arr, *, buffer=None, copy_to_fb=False)

생성자는 배열의 형태로부터 기하 구조와 픽셀 형식을 추론합니다:

  • 형태 (h, w)GRAYSCALE 이미지.

  • 형태 (h, w, 3)RGB565 이미지.

ndarray 는 dtype이 float 이어야 합니다. 생성자는 현재 그 경우만 지원합니다. 값은 0..255 범위로 반올림 및 클램핑됩니다.

buffer= 를 사용하면 애플리케이션이 결과 이미지를 위해 이미 할당한 bytearray 를 제공할 수 있습니다. copy_to_fb=True 는 결과를 카메라의 프레임 버퍼에 기록하며, 결과가 IDE 미리보기에 표시되어야 할 때 적절한 선택입니다.

6.18.3. 왕복

import csi
import image
from ulab import numpy as np

csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.GRAYSCALE)
csi0.framesize(csi.QVGA)

img = csi0.snapshot()
a   = img.to_ndarray('f')                  # work in float space

a = 255.0 * (a / 255.0) ** 0.5             # gamma correction

out = image.Image(a, copy_to_fb=True)      # back to an image

6.18.4. 언제 연결할 것인가

이 연결은 애플리케이션이 내장 image 메서드가 제공하지 않는 범용 수치 연산 – 사용자 정의 필터, 사용자 정의 블렌드, 특이한 비선형성 – 을 필요로 할 때, 또는 픽셀 데이터를 단일 계산 안에서 비이미지 데이터(IMU 축, 오디오 샘플)와 결합해야 할 때 올바른 답입니다.

Image 클래스가 이미 다루는 고처리량 픽셀 처리에는 올바른 답이 아닙니다. 내장 메서드는 카메라의 네이티브 픽셀 형식으로 된 프레임 버퍼에 직접 작동하며 동등한 numpy 표현식보다 훨씬 빠릅니다. 이미지 라이브러리가 아직 제공하지 않는 연산에 대해서만 이 연결을 활용하십시오.