6.18. Ảnh và ndarray

Lớp Image là bề mặt nhanh cho công việc điểm ảnh gốc của camera: mọi phương thức trên nó đều hoạt động trực tiếp trên bộ đệm khung hình theo định dạng điểm ảnh gốc của camera. numpy là bề mặt số chung cho mọi thứ khác. Hai phương thức kết nối chúng:

Kết hợp lại, chúng cho phép ứng dụng chụp một khung hình, chuyển nó sang numpy để thực hiện phép biến đổi tùy chỉnh, rồi đưa kết quả trở lại một ảnh để hiển thị, lưu, hoặc đưa vào phần còn lại của thư viện ảnh.

6.18.1. Ảnh sang ndarray

to_ndarray() cấp phát một ndarray mới và sao chép dữ liệu điểm ảnh của ảnh vào đó (theo ánh xạ dtype bên dưới). Nó không bao giờ là một view vào bộ đệm khung hình của ảnh -- mảng numpy luôn sở hữu các byte của chính nó. Chữ ký là to_ndarray(dtype, *, buffer=None), và hình dạng đầu ra phụ thuộc vào định dạng ảnh:

  • GRAYSCALE -- mảng 2 chiều, hình dạng (height, width).

  • RGB565 -- mảng 3 chiều, hình dạng (height, width, 3), các mặt phẳng theo thứ tự R/G/B.

Đối số dtype kiểm soát cách mỗi giá trị điểm ảnh 8-bit v được ánh xạ:

dtype

phần tử

ánh xạ cho giá trị điểm ảnh 8-bit v

'B'

uint8

v (thô)

'b'

int8

v - 128 (căn chỉnh lại quanh giá trị 0)

'f'

float32

float(v) (0.0 ... 255.0)

Ví dụ -- xem một khung hình thang xám dưới dạng ma trận 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))

Từ khóa buffer= cho phép ứng dụng tái sử dụng một bytearray đã được cấp phát sẵn, để camera không phải cấp phát một cái mới mỗi khung hình:

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

6.18.2. ndarray sang ảnh

Đi theo chiều ngược lại, truyền ndarray làm đối số đầu tiên cho image.Image. Hàm tạo cấp phát một bộ đệm ảnh mới và sao chép các giá trị của mảng vào đó, cắt giới hạn và làm tròn về 0..255

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

Hàm tạo suy ra hình học và định dạng điểm ảnh từ hình dạng của mảng:

  • hình dạng (h, w) -- ảnh GRAYSCALE.

  • hình dạng (h, w, 3) -- ảnh RGB565.

ndarray phải có dtype float; hàm tạo hiện chỉ hỗ trợ trường hợp đó. Các giá trị được làm tròn và cắt giới hạn về phạm vi 0..255.

buffer= cho phép ứng dụng cung cấp một bytearray đã được cấp phát sẵn cho ảnh kết quả. copy_to_fb=True ghi kết quả vào bộ đệm khung hình của camera, đây là lựa chọn đúng khi kết quả cần xuất hiện trong bản xem trước của IDE.

6.18.3. Chu trình khép kín

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. Khi nào nên dùng cầu nối

Cầu nối này là câu trả lời đúng khi ứng dụng cần một phép toán số chung mà các phương thức image tích hợp không cung cấp -- bộ lọc tùy chỉnh, pha trộn tùy chỉnh, các phi tuyến bất thường -- hoặc khi dữ liệu điểm ảnh cần kết hợp với dữ liệu không phải ảnh (các trục IMU, mẫu âm thanh) trong một phép tính duy nhất.

Đây không phải là câu trả lời đúng cho việc xử lý điểm ảnh thông lượng cao mà lớp Image đã đảm nhiệm. Các phương thức tích hợp hoạt động trực tiếp trên bộ đệm khung hình theo định dạng điểm ảnh gốc của camera và nhanh hơn nhiều so với biểu thức numpy tương đương. Hãy dùng cầu nối cho những phép toán mà thư viện ảnh chưa cung cấp sẵn.