10.2. Zwracanie zrzutu obrazu¶
Punkt końcowy ze statusem jest w porządku, ale powodem istnienia kamery jest obiektyw. Dodaj punkt końcowy, który zwraca obraz JPEG tego, na co sensor patrzy w danej chwili.
import csi
from microdot import Response
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)
@app.get('/snapshot.jpg')
async def snapshot(request):
img = csi0.snapshot().compress(quality=85)
return Response(
body=img.bytearray(),
headers={'Content-Type': 'image/jpeg'},
)
Wejdź pod http://<cam-ip>/snapshot.jpg z przeglądarki, a obraz JPEG bieżącego widoku wypełni kartę. Odśwież, a otrzymasz nowy.
10.2.1. Obiekt Response¶
Procedura obsługi zwracająca słownik pozwala microdot zrobić resztę. Bajty JPEG wymagają pełnej formy: jawnie skonstruowanego obiektu microdot.Response. Argument body przyjmuje dowolną wartość przypominającą bajty – bufor image.Image kamery jest udostępniany przez bytearray(), więc ten sam bufor, do którego zapisał sensor, trafia prosto do gniazda.
Content-Type: image/jpeg to to, co mówi przeglądarce, aby wyrenderowała treść jako obraz. Bez tego przeglądarka próbowałaby wyświetlić bajty JPEG jako tekst i zobaczyłbyś pełen ekran śmieci.
image.Image.compress() uruchamia kodowanie JPEG na istniejącym buforze obrazu w miejscu i zwraca ten sam obraz (teraz w formacie JPEG), aby jego bajty mogły zostać wysłane takie, jakie są. quality=85 to zwykła wartość domyślna – na tyle wysoka, że obraz jest ostry, i na tyle niska, że plik mieści się w wolnym łączu.
10.2.2. Przechwytywanie blokuje pętlę¶
csi.CSI.snapshot() czeka, aż sensor zakończy ekspozycję i transfer DMA ramki, zanim zwróci wynik. Wewnątrz asynchronicznej procedury obsługi oznacza to, że pętla zdarzeń zatrzymuje się na czas ekspozycji – dziesięć, dwadzieścia, pięćdziesiąt milisekund, w zależności od oświetlenia. Przy jednym kliencie pytającym o jedną trasę naraz jest to niezauważalne; przy wielu klientach lub przy korutynie przechwytującej działającej równolegle blokowałoby to wszystko inne.
Dla przypadku z wieloma korutynami istnieje nieblokujący wariant snapshot() (blocking=False zwraca następną gotową ramkę lub None). Dla jednego zrzutu na żądanie domyślne blokujące wywołanie jest w porządku.
Właściciel może teraz odpytać URL i otrzymać świeżą ramkę.