6.18. Bilder och ndarrays¶
Klassen Image är det snabba gränssnittet för kameranativt pixelarbete: varje metod på den arbetar direkt på bildbufferten i kamerans nativa pixelformat. numpy är det generiska numeriska gränssnittet för allt annat. Två metoder överbryggar dem:
image.Image.to_ndarray()– kopierar pixlarna i en bild till enndarray.Konstruktorn
image.Image– bygger en ny bild från enndarray.
Tillsammans låter de en applikation ta en bildruta, lämna den till numpy för en anpassad transformering och sedan lägga tillbaka resultatet i en bild för att visa, spara eller mata tillbaka det till resten av bildbiblioteket.
6.18.1. Bild till ndarray¶
to_ndarray() allokerar en ny ndarray och kopierar bildens pixeldata till den (med dtype-mappningen nedan). Den är aldrig en vy mot bildens bildbuffert – numpy-arrayen äger alltid sina egna byte. Signaturen är to_ndarray(dtype, *, buffer=None), och utdataformen beror på bildformatet:
GRAYSCALE – 2D-array, form
(height, width).RGB565 – 3D-array, form
(height, width, 3), plan i R/G/B-ordning.
Argumentet dtype styr hur varje 8-bitars pixelvärde v mappas:
|
element |
mappning för ett 8-bitars pixelvärde |
|---|---|---|
|
|
|
|
|
|
|
|
|
Exempel – visa en gråskalebildruta som en uint8-matris:
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))
Nyckelordet buffer= låter applikationen återanvända en bytearray som den redan har allokerat, så att kameran inte behöver allokera en ny för varje bildruta:
buf = bytearray(320 * 240)
while True:
img = csi0.snapshot()
a = img.to_ndarray('B', buffer=buf)
# ... process a ...
6.18.2. ndarray till bild¶
För att gå åt andra hållet skickar du ndarray som första argument till image.Image. Konstruktorn allokerar en ny bildbuffert och kopierar arrayens värden till den, begränsade och avrundade till 0..255
image.Image(arr, *, buffer=None, copy_to_fb=False)
Konstruktorn härleder geometrin och pixelformatet från arrayens form:
form
(h, w)–GRAYSCALE-bild.form
(h, w, 3)–RGB565-bild.
ndarray måste ha dtype float; konstruktorn stöder endast det fallet idag. Värden avrundas och begränsas till intervallet 0..255.
buffer= låter applikationen tillhandahålla en bytearray som den redan har allokerat för den resulterande bilden. copy_to_fb=True skriver resultatet till kamerans bildbuffert, vilket är rätt val när resultatet ska visas i IDE-förhandsvisningen.
6.18.3. Rundtur¶
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. När man ska överbrygga¶
Denna brygga är rätt svar när applikationen behöver en generisk numerisk operation som de inbyggda image-metoderna inte tillhandahåller – anpassade filter, anpassade blandningar, ovanliga icke-lineariteter – eller när pixeldata måste kombineras med icke-bilddata (IMU-axlar, ljudsampel) i en enda beräkning.
Det är inte rätt svar för pixelbehandling med hög genomströmning som klassen Image redan täcker. De inbyggda metoderna arbetar direkt på bildbufferten i kamerans nativa pixelformat och är mycket snabbare än motsvarande numpy-uttryck. Ta till bryggan för de operationer som bildbiblioteket inte redan tillhandahåller.