6.18. Görüntüler ve ndarray’ler

Image sınıfı, kamera için yerel piksel işlemlerinin hızlı yüzeyidir: üzerindeki her metot doğrudan çerçeve arabelleği (frame buffer) üzerinde, kameranın yerel piksel formatında çalışır. numpy ise diğer her şey için kullanılan genel sayısal yüzeydir. İki metot bunları birbirine bağlar:

Birlikte kullanıldıklarında, bir uygulamanın bir çerçeve yakalamasına, bunu özel bir dönüşüm için numpy‘a vermesine ve ardından sonucu görüntülemek, kaydetmek veya görüntü kütüphanesinin geri kalanına geri beslemek üzere tekrar bir görüntüye yerleştirmesine olanak tanırlar.

6.18.1. Görüntüden ndarray’e

to_ndarray() yeni bir ndarray ayırır ve görüntünün piksel verilerini (aşağıdaki dtype eşlemesiyle) bunun içine kopyalar. Bu hiçbir zaman görüntünün çerçeve arabelleğine (frame buffer) bir görünüm (view) değildir – numpy dizisi her zaman kendi baytlarına sahiptir. İmza to_ndarray(dtype, *, buffer=None) şeklindedir ve çıktının şekli görüntü formatına bağlıdır:

  • GRAYSCALE – 2 boyutlu dizi, (height, width) şekli.

  • RGB565 – 3 boyutlu dizi, (height, width, 3) şekli, düzlemler R/G/B sırasında.

dtype argümanı, her 8 bitlik piksel değeri v‘nin nasıl eşleneceğini kontrol eder:

dtype

eleman

8 bitlik bir piksel değeri v için eşleme

'B'

uint8

v (ham)

'b'

int8

v - 128 (sıfır etrafında yeniden ortalanmış)

'f'

float32

float(v) (0.0 … 255.0)

Örnek – bir gri tonlamalı çerçeveyi bir uint8 matrisi olarak görüntüleme:

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= anahtar sözcüğü, uygulamanın önceden ayırdığı bir bytearray‘i yeniden kullanmasına olanak tanır; böylece kameranın her çerçevede yeni bir tane ayırması gerekmez:

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

6.18.2. ndarray’den görüntüye

Ters yönde gitmek için, ndarray‘i image.Image‘a ilk argüman olarak geçirin. Yapıcı yeni bir görüntü arabelleği ayırır ve dizinin değerlerini 0..255 aralığına sınırlayıp yuvarlayarak bunun içine kopyalar:

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

Yapıcı, geometriyi ve piksel formatını dizinin şeklinden çıkarır:

  • şekil (h, w)GRAYSCALE görüntü.

  • şekil (h, w, 3)RGB565 görüntü.

ndarray‘in dtype’ı float olmalıdır; yapıcı bugün yalnızca bu durumu destekler. Değerler yuvarlanır ve 0..255 aralığına sınırlanır.

buffer=, uygulamanın sonuçtaki görüntü için önceden ayırdığı bir bytearray‘i sağlamasına olanak tanır. copy_to_fb=True sonucu kameranın çerçeve arabelleğine (frame buffer) yazar; bu da sonucun IDE önizlemesinde görünmesi gerektiğinde doğru seçimdir.

6.18.3. Gidiş-dö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. Köprü ne zaman kullanılır

Bu köprü, uygulamanın yerleşik image metotlarının sağlamadığı genel bir sayısal işleme ihtiyaç duyduğunda – özel filtreler, özel harmanlamalar, alışılmadık doğrusal olmayan işlemler – ya da piksel verilerinin görüntü olmayan verilerle (IMU eksenleri, ses örnekleri) tek bir hesaplamada birleştirilmesi gerektiğinde doğru yanıttır.

Bu köprü, Image sınıfının zaten kapsadığı yüksek iş hacimli piksel işleme için doğru yanıt değildir. Yerleşik metotlar doğrudan çerçeve arabelleği (frame buffer) üzerinde, kameranın yerel piksel formatında çalışır ve eşdeğer numpy ifadesinden çok daha hızlıdır. Görüntü kütüphanesinin halihazırda sağlamadığı işlemler için köprüye başvurun.