13.4.1.3. Strumieniowanie ramek#
Skrypt przechwytujący ramki w kamerze może strumieniować każdą ramkę z powrotem do hosta przez USB. Wzorzec opiera się na dwóch wywołaniach na instancji openmv.Camera: streaming() włącza lub wyłącza strumień, a read_frame() pobiera kolejną ramkę z kanału.
13.4.1.3.1. Minimalna pętla strumieniowania i wyświetlania#
Skrypt po stronie kamery to zwykła pętla zrzutu obrazu; nowością jest to, że host otwiera strumień i odczytuje wynik z powrotem:
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 przechwytuje ramki w sposób ciągły; host pobiera każdą z nich z bufora strumienia w miarę jak się pojawiają. Kamera nadpisuje bufor strumienia przy każdym nowym zrzucie obrazu, więc host odpytujący wolniej niż kamera przechwytuje ramki będzie po cichu gubił ramki – co jest prawidłowym zachowaniem w przypadku zastosowań typu podgląd.
13.4.1.3.2. Słownik ramki#
read_frame() zwraca albo None (żadna ramka nie czeka), albo dict z pięcioma wpisami:
Klucz | Znaczenie |
|---|---|
| Szerokość ramki w pikselach. |
| Wysokość ramki w pikselach. |
| Identyfikator formatu piksela zadeklarowany przez kamerę (liczba całkowita ze stałych |
| Dla formatów skompresowanych (JPEG, PNG) rozmiar skompresowanego obrazu w bajtach. Nieużywane w przypadku formatów nieskompresowanych. |
| Ramka jako bufor |
| Liczba bajtów wysłanych przez kamerę przez USB przed dekodowaniem. Przydatne do rzeczywistego obliczenia przepustowości. |
Pakiet konwertuje natywny format kamery (GRAYSCALE, RGB565, JPEG) na RGB888 przed zwróceniem, dzięki czemu host nigdy nie musi sam zajmować się upakowanym bitowo RGB565 ani dekompresją JPEG. Ramki w skali szarości są zwracane z wartością luminancji powieloną na wszystkie trzy kanały.
Bufor data jest ułożony wiersz po wierszu, od góry do dołu; przekazanie go bezpośrednio do biblioteki wyświetlania lub zapisanie jako surowy plik RGB działa bez żadnego dalszego przetasowania.
13.4.1.3.3. Tryb surowego strumieniowania#
Domyślnie kamera kompresuje każdą przechwyconą ramkę do formatu JPEG przed umieszczeniem jej w kanale strumienia, a read_frame() dekompresuje ją na hoście. W kamerach bez sprzętowej obsługi JPEG programowa kompresja jest najwolniejszym krokiem w pętli. Przekazanie raw=True pomija ją:
cam.streaming(True, raw=True, resolution=(320, 240))
Kamera wysyła wówczas bufor pikseli bez kompresji. Nieskompresowane ramki są znacznie większe niż ich odpowiedniki w formacie JPEG, więc kamera skaluje w dół każdą przechwyconą ramkę, aby zmieściła się w kanale strumienia przed wysłaniem; argument resolution=(width, height) ustawia ten cel. Host nadal otrzymuje RGB888 w polu data – pakiet konwertuje z dowolnego formatu piksela zgłoszonego przez kamerę w polu format.
13.4.1.3.4. Pozwól zdarzeniom sterować pętlą#
Pętla odpytująca, która wywołuje read_frame() szybciej, niż kamera produkuje ramki, spędza większość czasu na otrzymywaniu z powrotem None. Gdy host ma także inne zadania do wykonania (interfejs do aktualizacji, inne kanały do odpytania), read_status() jest tańszym sprawdzeniem: zwraca słownik mapujący każdą zarejestrowaną nazwę kanału na wartość logiczną oznaczającą „dane są gotowe”:
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 ...
Taki kształt pętli wykorzystuje sam podgląd CLI.
13.4.1.3.5. Zatrzymywanie strumienia#
Wywołaj streaming() z enable=False, aby zatrzymać strumień. Kamera nadal wykonuje swój skrypt, ale nie wypełnia już bufora strumienia; read_frame() od tego momentu zwraca po prostu None. Wywołanie stop() robi to samo niejawnie, zatrzymując skrypt.