13.1.10. Samostatná terminálová okna¶
Tools → Open Terminal otevírá nezávislá terminálová okna – každé z nich je miniaturní relace OpenMV IDE ve vlastním okně, s prohlížečem snímkového bufferu (frame buffer), histogramem a interaktivním terminálem, připojeným přes přenos podle vašeho výběru. Připojení hlavního okna zůstává nedotčeno, takže samostatný terminál umožňuje sledovat druhou kameru, zatímco první zůstává připojena, nebo ladit kameru na vzdálené straně sítě.
Samostatné terminálové okno přes sériový port: vlevo interaktivní terminál s lištou run / stop / reset, vpravo snímkový buffer (frame buffer) a histogram – ty se rozsvítí, když kamera streamuje snímky uvnitř datového toku.¶
New Terminal nabízí jeden ze tří přenosů:
Serial port – libovolný sériový port při libovolné přenosové rychlosti (baud rate) (výchozí 115 200). To zahrnuje USB port druhé kamery, kameru zapojenou přes USB-to-UART můstek, sériové spojení přes Bluetooth (které se zobrazuje jako běžný sériový port) nebo jakékoli ne-OpenMV sériové zařízení, které potřebuje terminál. Na USB portu přenosová rychlost neomezuje rychlost – data se vždy přesouvají rychlostí USB linky – ale na USB portu kamery se vyhněte hodnotám 921 600 a 12 000 000, které přepínají kameru z REPL do ladicího protokolu IDE.
TCP – připojení k serveru na zvoleném hostiteli a portu, nebo naslouchání jako server na zvoleném portu.
UDP – stejná dvojice rolí, ale přes UDP.
IDE si pamatuje posledních deset konfigurací a uvádí je v podnabídce Open Terminal pro opětovné otevření jedním kliknutím; Clear Menu je zapomene.
Na rozdíl od panelu hlavního okna určeného pouze pro výstup je samostatný terminál plně interaktivní: je to REPL. Pište na příkazovém řádku a Python se na připojené kameře spouští řádek po řádku, s historií a doplňováním tabulátorem, které poskytuje samotný MicroPython. Lišta nástrojů přidává ekvivalenty běžných řídicích sekvencí na jedno kliknutí – spuštění aktuálního skriptu v editoru, zastavení běžícího skriptu a soft reset – a stejné ovládací prvky pro vymazání, uložení a zalamování jako hlavní panel terminálu.
Snímkový buffer (frame buffer) nad terminálem je rovněž živý. Když připojená kamera streamuje komprimované snímky uvnitř datového toku – vložené do téhož toku jako její tiskový výstup – terminál je dekóduje a zobrazuje a tlačítka Record a Zoom fungují přesně jako v hlavním okně. Tato kombinace tvoří přístup IDE k síťovému ladění: kamera, která zpřístupňuje svůj REPL přes Wi-Fi, získá kompletní smyčku edit-run-preview bez jediného USB kabelu.
13.1.10.1. Streamování snímků uvnitř datového toku¶
Kódování, kterému terminál rozumí, je jednoduché: bajt 0xFE zahajuje snímek, druhý bajt 0xFE jej ukončuje a každý bajt užitečného zatížení mezi nimi má nastavený nejvyšší bit a nese šest bitů komprimovaného obrazu – tři obrazové bajty se stávají čtyřmi bajty užitečného zatížení. Prostý text nikdy nepoužívá tyto hodnoty bajtů, takže snímky a výstup z print() sdílejí datový tok bez kolize: terminál zobrazuje text i snímky.
Skript níže pořizuje snímky, převádí každý snímek na JPEG a tiskne jej v této podobě. Balení bitů probíhá pomocí ulab (které nemá operátory posunu, takže posuny jsou zapsány jako násobení a dělení) a je dostatečně rychlé, aby udrželo krok s kamerou:
import csi
import sys
import time
from ulab import numpy as np
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)
clock = time.clock()
def encode_for_ide(data):
n = len(data)
n3 = n - (n % 3)
m = (n3 // 3) * 4
out = bytearray(((n * 8) + 5) // 6 + 2)
out[0] = 0xFE
out[-1] = 0xFE
if n3:
src = np.frombuffer(data, dtype=np.uint8)
dst = np.frombuffer(out, dtype=np.uint8)
b0 = src[0:n3:3]
b1 = src[1:n3:3]
b2 = src[2:n3:3]
dst[1:m + 1:4] = (b0 & 0x3F) | 0x80
dst[2:m + 2:4] = (b0 // 64) | ((b1 & 0x0F) * 4) | 0x80
dst[3:m + 3:4] = (b1 // 16) | ((b2 & 0x03) * 16) | 0x80
dst[4:m + 4:4] = (b2 // 4) | 0x80
if n % 3 == 2:
x = data[n - 2] | (data[n - 1] << 8)
out[m + 1] = 0x80 | (x & 0x3F)
out[m + 2] = 0x80 | ((x >> 6) & 0x3F)
out[m + 3] = 0x80 | ((x >> 12) & 0x3F)
elif n % 3 == 1:
out[m + 1] = 0x80 | (data[n - 1] & 0x3F)
out[m + 2] = 0x80 | (data[n - 1] >> 6)
return out
while True:
clock.tick()
img = csi0.snapshot().to_jpeg(quality=80)
sys.stdout.write(encode_for_ide(img.bytearray()))
print(clock.fps())
V samostatném terminálu to funguje, protože tisk z REPL čeká: kamera se zablokuje, dokud terminál data nepřevezme, takže každý bajt snímku dorazí a JPEG se přes USB linku full-speed nebo high-speed přesouvá rychle. Stejný skript funguje beze změny i přes TCP terminál, což je výše uvedená cesta síťového ladění. Jediné místo, kde nefunguje, je hlavní ladicí připojení IDE, jehož výstupní kanál se při přetečení sám resetuje místo čekání – tam již prohlížeč snímkového bufferu (frame buffer) zobrazuje snímky kamery nativně, takže o nic nepřijdete.