6.18. Citra dan ndarray

Kelas Image adalah permukaan cepat untuk pekerjaan piksel native kamera: setiap metode di dalamnya beroperasi langsung pada buffer bingkai dalam format piksel native kamera. numpy adalah permukaan numerik generik untuk segala hal lainnya. Dua metode menjembatani keduanya:

Bersama-sama, keduanya memungkinkan aplikasi mengambil bingkai, menyerahkannya ke numpy untuk transformasi kustom, lalu menempatkan hasilnya kembali ke dalam citra untuk ditampilkan, disimpan, atau diumpankan kembali ke library citra lainnya.

6.18.1. Citra ke ndarray

to_ndarray() mengalokasikan ndarray baru dan menyalin data piksel citra ke dalamnya (dengan pemetaan dtype di bawah). Ini tidak pernah merupakan tampilan langsung ke buffer bingkai citra -- array numpy selalu memiliki byte-nya sendiri. Tanda tangan fungsinya adalah to_ndarray(dtype, *, buffer=None), dan bentuk output bergantung pada format citra:

  • GRAYSCALE -- array 2-D, bentuk (height, width).

  • RGB565 -- array 3-D, bentuk (height, width, 3), bidang dalam urutan R/G/B.

Argumen dtype mengontrol bagaimana setiap nilai piksel 8-bit v dipetakan:

dtype

elemen

pemetaan untuk nilai piksel 8-bit v

'B'

uint8

v (mentah)

'b'

int8

v - 128 (dipusatkan ulang di sekitar nol)

'f'

float32

float(v) (0.0 ... 255.0)

Contoh -- lihat bingkai skala abu-abu sebagai matriks 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))

Kata kunci buffer= memungkinkan aplikasi menggunakan kembali bytearray yang sudah dialokasikan, sehingga kamera tidak harus mengalokasikan yang baru setiap bingkai:

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

6.18.2. ndarray ke citra

Untuk arah sebaliknya, teruskan ndarray sebagai argumen pertama ke image.Image. Konstruktor mengalokasikan buffer citra baru dan menyalin nilai array ke dalamnya, dipotong dan dibulatkan ke 0..255

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

Konstruktor menyimpulkan geometri dan format piksel dari bentuk array:

  • bentuk (h, w) -- citra GRAYSCALE.

  • bentuk (h, w, 3) -- citra RGB565.

ndarray harus memiliki dtype float; konstruktor hanya mendukung kasus tersebut saat ini. Nilai dibulatkan dan dipotong ke rentang 0..255.

buffer= memungkinkan aplikasi menyediakan bytearray yang sudah dialokasikan untuk citra yang dihasilkan. copy_to_fb=True menulis hasil ke buffer bingkai kamera, yang merupakan pilihan tepat ketika hasilnya harus muncul di pratinjau IDE.

6.18.3. Perjalanan pulang-pergi

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. Kapan harus menjembatani

Jembatan ini adalah jawaban yang tepat ketika aplikasi membutuhkan operasi numerik generik yang tidak disediakan oleh metode image bawaan -- filter kustom, pencampuran kustom, non-linearitas yang tidak biasa -- atau ketika data piksel harus digabungkan dengan data non-citra (sumbu IMU, sampel audio) dalam satu komputasi.

Ini bukan jawaban yang tepat untuk pemrosesan piksel throughput tinggi yang sudah ditangani oleh kelas Image. Metode bawaan beroperasi langsung pada buffer bingkai dalam format piksel native kamera dan jauh lebih cepat daripada ekspresi numpy yang setara. Gunakan jembatan untuk operasi yang belum disediakan oleh library citra.