protocol — Kanály protokolu OpenMV¶
Modul protocol zpřístupňuje hostitelský protokol OpenMV jazyku Python. Umožňuje inicializaci a konfiguraci protokolového zásobníku na straně firmwaru a dovoluje uživatelskému kódu registrovat vlastní logické kanály podpořené objektem Python, který implementuje rozhraní kanálu (read, write, size, poll atd.). S tím komunikují doprovodné nástroje na počítači, když streamují obrazová data nebo zpřístupňují interaktivní widgety připojené kameře.
Příklady¶
Stream obrazu RGB565 do hostitelského nástroje pomocí vlastního backendu, který implementuje rozhraní surového kanálu (backend.size(), backend.shape(), backend.poll(), backend.read()):
import csi
import protocol
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.HD)
img = csi0.snapshot()
img_mv = memoryview(img.bytearray())
frame_ready = True
class FrameChannel:
def size(self):
return len(img_mv)
def shape(self):
return (img.height(), img.width(), len(img_mv))
def poll(self):
return frame_ready
def read(self, offset, size):
global frame_ready
end = offset + size
chunk = img_mv[offset:end]
if end >= len(img_mv):
frame_ready = False
return chunk
protocol.register(name="frame", backend=FrameChannel())
while True:
if not frame_ready:
img = csi0.snapshot()
img_mv = memoryview(img.bytearray())
frame_ready = True
Odpovídající skript na straně hostitele, který používá balíček Python openmv (pip install openmv) k připojení, nahrání skriptu do kamery a stažení každého snímku:
import cv2
import numpy as np
from openmv.camera import Camera
# The on-cam script above, stored as a string (or read from a file).
SCRIPT = open("frame_streamer_on_cam.py").read()
with Camera("/dev/ttyACM0", baudrate=921600) as cam:
cam.stop()
cam.exec(SCRIPT)
while True:
status = cam.read_status()
if not cam.has_channel("frame") or not status.get("frame"):
continue
h, w, size = cam._channel_shape(cam.get_channel(name="frame"))
if cam.channel_size("frame") < size:
continue
data = cam.channel_read("frame", size)
rgb565 = np.frombuffer(data, dtype="<u2").reshape(h, w)
# Unpack RGB565 to an HxWx3 uint8 RGB image.
r = ((rgb565 >> 11) & 0x1F) << 3
g = ((rgb565 >> 5) & 0x3F) << 2
b = ( rgb565 & 0x1F) << 3
frame = np.dstack([r, g, b]).astype(np.uint8)
# Display with OpenCV (cv2 expects BGR, not RGB).
cv2.imshow("OpenMV", cv2.cvtColor(frame, cv2.COLOR_RGB2BGR))
if cv2.waitKey(1) == ord("q"):
break
cv2.destroyAllWindows()
Nahraďte /dev/ttyACM0 sériovým portem kamery (např. COM3 ve Windows). Konstruktor openmv.camera.Camera přijímá stejné parametry protokolu jako init (crc / seq / ack / events / max_payload / max_retry / timeout), pokud byl zásobník na straně kamery překonfigurován tak, aby jim odpovídal.
Funkce¶
- protocol.init(crc: bool = True, seq: bool = True, ack: bool = True, events: bool = True, max_payload: int = ..., rtx_retries: int = 3, rtx_timeout_ms: int = 500, lock_interval_ms: int = 10, poll_ms: int = 0) None¶
Inicializuje (nebo překonfiguruje) protokolový zásobník a registruje výchozí logické datové kanály (
stdin,stdout,streama, pokud je zkompilován,profile). VyvoláRuntimeError, pokud inicializace selže. Firmware startuje s již běžícím výchozím protokolovým zásobníkem USB, takže toto volání je potřeba pouze ke změně přenosu nebo přepsání výchozích parametrů rámcování.crcpovoluje ověřování CRC u rámců protokolu.seqpovoluje sledování sekvenčních čísel.ackpovoluje potvrzování jednotlivých rámců.eventspovoluje oznámení událostí kanálu.max_payloadje maximální velikost užitečného zatížení v bajtech. Pokud je vynechána, použije se níže uvedená výchozí hodnota pro danou kameru; ta je odvozena z velikosti protokolového bufferu každé desky jakobuffer - 10 (header) - 4 (CRC).Kamera
Velikost bufferu
Max. užitečné zatížení
OpenMV Cam M4 (
OPENMV2)512
498
OpenMV Cam M7 (
OPENMV3)512
498
OpenMV Cam H7 (
OPENMV4)512
498
OpenMV Cam H7 Plus (
OPENMV4P)4096
4082
OpenMV Pure Thermal (
OPENMVPT)4096
4082
OpenMV Cam RT1062 (
OPENMV_RT1060)4096
4082
OpenMV Cam N6 (
OPENMV_N6)8192
8178
OpenMV AE3 (
OPENMV_AE3)8192
8178
Arduino Portenta H7 (
ARDUINO_PORTENTA_H7)4096
4082
Arduino Giga (
ARDUINO_GIGA)4096
4082
Arduino Nicla Vision (
ARDUINO_NICLA_VISION)4096
4082
rtx_retriesje počet pokusů o opětovné odeslání. Výchozí hodnota3.rtx_timeout_msje časový limit opětovného odeslání v milisekundách (po každém vypršení se zdvojnásobí). Výchozí hodnota500.lock_interval_msje minimální interval zámku v milisekundách. Výchozí hodnota10.poll_msje interval dotazování v milisekundách.0(výchozí) zakazuje dotazování pomocí časovače.
- protocol.is_active() bool¶
Vrací
True, pokud je aktuálně připojen hostitel a protokolový zásobník je aktivní, jinakFalse.
- protocol.register(name: str, *, backend: object, flags: int = 0) ProtocolChannel¶
Registruje objekt Python
backendjako nový logický kanál a vrátí úchytProtocolChannel. Dostupné metody objektubackend(viz Rozhraní backendu níže) určují schopnosti kanálu;protocol.CHANNEL_FLAG_READ,protocol.CHANNEL_FLAG_WRITEaprotocol.CHANNEL_FLAG_LOCKjsou doflagspřidány automaticky, když jsou odpovídající metody implementovány.nameje název kanálu jako řetězec. Zkrácen na velikost bufferu pro názvy kanálů ve firmwaru. Povinné.backendje objekt Python implementující rozhraní backendu. Povinné. Obvykle předáván klíčovým slovem (backend=...).flagsjsou další příznakové bity kanálu (viz konstantyCHANNEL_FLAG_*). Nepovinné; výchozí hodnota0.Vyvolá
RuntimeError, pokud kanál nelze zaregistrovat (např. žádné volné sloty kanálů).
Třídy¶
- class protocol.ProtocolChannel¶
Úchyt vrácený funkcí
protocol.register. Instance se nevytvářejí přímo.
Rozhraní backendu¶
Objekt backendu předaný funkci protocol.register může implementovat libovolnou podmnožinu následujících metod. K protokolové vrstvě C jsou napojeny pouze metody přítomné na objektu; chybějící metody ponechávají odpovídající schopnost vypnutou.
- class protocol.backend¶
Objekt backendu kanálu předaný funkci
protocol.register. Níže uvedené metody popisují volitelné rozhraní, které může backend Python implementovat.- init() object¶
Voláno jednou při inicializaci kanálu. Při úspěchu vrací libovolnou hodnotu různou od
None; výjimka nebo chybějící návratová hodnota je považována za chybu.
- shape() tuple¶
Vrací n-tici až čtyř celých čísel popisujících tvar dat (např. rozměry obrazu). Protokolová vrstva spotřebuje až čtyři prvky.
- flush() object¶
Vyprázdní veškerá čekající data. Při úspěchu vrací libovolnou hodnotu různou od
None.
- read(offset: int, size: int) bytes¶
Vrací až
sizebajtů počínaje odoffsetjako objekt podobnýbytes, který podporuje buffer protocol.
- readp(offset: int, size: int) bytes¶
Varianta
readbez kopírování (zero-copy). Vrací buffer, jehož podkladovou paměť čte protokolová vrstva přímo; buffer musí zůstat platný po celou dobu trvání přenosu.
- write(offset: int, data: bytearray) int¶
Zapíše
datanaoffset.datajebytearrayodkazující přímo na buffer C. Vrací počet zapsaných bajtů, nebo0při výchozím úspěchu.
- class protocol.CBORChannel(on_read: Callable | None = None, on_write: Callable | None = None)¶
Backend Python vyšší úrovně (poskytovaný zamrazeným balíčkem
protocol), který serializuje pojmenovaná pole do CBOR pomocí celočíselných klíčů kompatibilních se SenML. Podporuje zobrazovací widgety (label,depth) a interaktivní ovládací prvky (toggle,slider,select) s callbackyon_read/on_write.on_readje nepovinný volatelný objekton_read(channel)vyvolaný před serializací kanálu pro hostitele. Použijte jej k obnovení hodnot polí.on_writeje nepovinný volatelný objekton_write(channel, name, value)vyvolaný, když hostitel zapíše novou hodnotu pro pojmenované pole.- add(name: str, type: str, value: Any = None, unit: str | None = None, min: int | float | None = None, max: int | float | None = None, step: int | float | None = None, options: list | None = None, width: int | None = None, height: int | None = None) None¶
Přidá do kanálu pojmenované pole.
nameje zobrazovaný název; musí být v rámci tohoto kanálu jedinečný.typeje typ widgetu:"label","toggle","slider","select"nebo"depth".valueje počáteční hodnota. Výchozí hodnota závisí natype.unitje řetězec jednotky prolabel/slider(např."Cel","%RH").minje minimální hodnota (rozsah slideru nebo rozsah hloubky).maxje maximální hodnota (rozsah slideru nebo rozsah hloubky).stepje velikost kroku (slider).optionsje seznam řetězců možností (select).widthje šířka v pixelech (depth).heightje výška v pixelech (depth).
- __getitem__(name: str) object¶
Vrací aktuální hodnotu pojmenovaného pole. U polí
depthje vrácen buffer binárních dat, jinak skalární hodnota.
- __setitem__(name: str, value: Any) None¶
Nastaví hodnotu pojmenovaného pole. U polí
slidern-tice(min, max, value)současně aktualizuje rozsah i aktuální hodnotu. U polídepthjevaluebuffer binárních dat.
- poll() bool¶
Metoda rozhraní backendu. Vrací
True, když jsou pro hostitele k dispozici serializovaná data.
Konstanty¶
Příznakové bity kanálu (kombinované bitově; předávané funkci protocol.register přes flags nebo nastavované automaticky na základě metod backendu).
- protocol.CHANNEL_FLAG_PHYSICAL: int¶
Kanál představuje fyzický přenos (na rozdíl od logického datového kanálu).
Vestavěné identifikátory kanálů.