13.3.1.3. Streamování snímků¶
Skript, který zachytává snímky na kameře, může každý snímek streamovat zpět do hostitele přes USB. Vzorec spočívá ve dvou voláních na instanci openmv.Camera: streaming() pro zapnutí nebo vypnutí streamu a read_frame() pro vyzvednutí dalšího snímku z kanálu.
13.3.1.3.1. Minimální smyčka pro stream a zobrazení¶
Skript na straně kamery je obvyklá smyčka se snímky; novinkou je, že hostitel otevře streamování a čte výsledek zpět:
from openmv import Camera
script = """
import csi
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)
while True:
csi0.snapshot()
"""
with Camera('/dev/ttyACM0') as cam:
cam.stop()
cam.exec(script)
cam.streaming(True)
while True:
if frame := cam.read_frame():
print(f"{frame['width']}x{frame['height']}, "
f"{frame['raw_size']} bytes")
Kamera zachytává snímky nepřetržitě; hostitel vyzvedává každý z nich ze stream bufferu, jakmile dorazí. Kamera přepisuje stream buffer při každém novém snímku, takže hostitel, který odečítá pomaleji, než kamera zachytává, bude tiše zahazovat snímky – a to je správné chování pro případy užití typu prohlížeče.
13.3.1.3.2. Slovník snímku (frame dict)¶
read_frame() vrací buď None (žádný snímek nečeká), nebo dict s pěti položkami:
Klíč |
Význam |
|---|---|
|
Šířka snímku v pixelech. |
|
Výška snímku v pixelech. |
|
Identifikátor formátu pixelů, který kamera deklarovala (celé číslo z konstant |
|
U komprimovaných formátů (JPEG, PNG) velikost komprimovaného obrazu v bajtech. U nekomprimovaných formátů se nepoužívá. |
|
Snímek jako buffer |
|
Bajty, které kamera odeslala přes USB před dekódováním. Užitečné pro skutečný výpočet propustnosti. |
Balíček před vrácením převede nativní formát kamery (GRAYSCALE, RGB565, JPEG) na RGB888, takže hostitel se nikdy nemusí sám zabývat bitově zabaleným RGB565 ani dekompresí JPEG. Snímky ve stupních šedi se vrací s hodnotou jasu replikovanou do všech tří kanálů.
Buffer data je uspořádán řádek po řádku, shora dolů; jeho přímé předání do knihovny pro zobrazení nebo uložení jako surového RGB souboru funguje bez jakéhokoli dalšího přerovnávání.
13.3.1.3.3. Režim surového streamování (raw)¶
Ve výchozím nastavení kamera každý zachycený snímek komprimuje do JPEG, než jej umístí do stream kanálu, a read_frame() jej na hostiteli dekomprimuje. Na kamerách bez hardwarové podpory JPEG je softwarová komprese nejpomalejším krokem ve smyčce. Předání raw=True ji vynechá:
cam.streaming(True, raw=True, resolution=(320, 240))
Kamera pak odešle buffer pixelů nekomprimovaný. Nekomprimované snímky jsou mnohem větší než jejich JPEG ekvivalenty, takže kamera každý zachycený snímek zmenší tak, aby se vešel do stream kanálu, než jej odešle; argument resolution=(width, height) nastavuje tento cíl. Hostitel stále přijímá RGB888 v poli data – balíček převádí z libovolného formátu pixelů, který kamera nahlásila v format.
13.3.1.3.4. Nechte řízení smyčky na událostech¶
Smyčka odečítání, která volá read_frame() rychleji, než kamera produkuje snímky, stráví většinu času tím, že dostává zpět None. Když má hostitel i jinou práci (aktualizovat UI, odečítat jiné kanály), je read_status() levnější kontrolou: vrací slovník mapující každý registrovaný název kanálu na booleovskou hodnotu „data jsou připravena“:
while True:
status = cam.read_status()
if status.get('stream'):
frame = cam.read_frame()
# ... process the frame ...
if status.get('stdout'):
text = cam.read_stdout()
print(text, end='')
if status.get('my_channel'):
data = cam.channel_read('my_channel')
# ... process custom-channel data ...
Toto je tvar smyčky, který používá samotný CLI prohlížeč.
13.3.1.3.5. Zastavení streamu¶
Zavolejte streaming() s enable=False pro zastavení. Kamera dál běží svůj skript, ale již neplní stream buffer; read_frame() od tohoto okamžiku jednoduše vrací None. Volání stop() udělá totéž implicitně tím, že zastaví skript.