10.2. การส่งคืนสแนปช็อต¶
endpoint สถานะใช้ได้ดี แต่เหตุผลที่ cam มีอยู่คือเลนส์ เพิ่ม endpoint ที่ส่งคืน JPEG ของสิ่งที่ sensor กำลังมองอยู่ในขณะนี้
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'},
)
เข้าถึง http://<cam-ip>/snapshot.jpg จากเบราว์เซอร์และ JPEG ของมุมมองปัจจุบันจะเติมเต็มแท็บ รีเฟรชแล้วคุณจะได้ภาพใหม่
10.2.1. ออบเจกต์ Response¶
ตัวจัดการที่ส่งคืน dict ให้ microdot ทำส่วนที่เหลือ ไบต์ JPEG ต้องการรูปแบบยาว: microdot.Response ที่สร้างอย่างชัดเจน อาร์กิวเมนต์ body รับค่าที่คล้ายไบต์ใดก็ได้ -- บัฟเฟอร์ image.Image ของกล้องเปิดเผยผ่าน bytearray() ดังนั้นบัฟเฟอร์เดียวกันที่ sensor เขียนลงไปจะส่งตรงไปยัง socket
Content-Type: image/jpeg คือสิ่งที่บอกเบราว์เซอร์ให้เรนเดอร์ body เป็นภาพ หากไม่มี เบราว์เซอร์จะพยายามแสดงไบต์ JPEG เป็นข้อความและคุณจะเห็นหน้าจอเต็มไปด้วยอักขระสุ่ม
image.Image.compress() รันการเข้ารหัส JPEG บนบัฟเฟอร์ภาพที่มีอยู่ในพื้นที่และส่งคืนภาพเดิม (ขณะนี้อยู่ในรูปแบบ JPEG) เพื่อให้ไบต์ของมันสามารถส่งได้โดยตรง quality=85 คือค่าเริ่มต้นปกติ -- สูงพอที่ภาพจะคมชัด ต่ำพอที่ไฟล์จะผ่านลิงก์ที่ช้าได้
10.2.2. การจับภาพบล็อกลูป¶
csi.CSI.snapshot() รอให้ sensor เสร็จสิ้นการรับแสงและ DMA เฟรมก่อนส่งคืน ภายใน async handler นั่นหมายความว่า event loop หยุดนิ่งตลอดระยะเวลาของการรับแสง -- สิบ, ยี่สิบ, ห้าสิบมิลลิวินาทีขึ้นอยู่กับแสง เมื่อไคลเอนต์หนึ่งรายถาม route หนึ่งในแต่ละครั้ง สิ่งนี้มองไม่เห็น; เมื่อมีหลายไคลเอนต์ หรือ coroutine จับภาพทำงานควบคู่ มันจะบล็อกทุกอย่างอื่น
มีตัวแปรไม่บล็อกของ snapshot() สำหรับกรณีหลาย coroutine (blocking=False ส่งคืนเฟรมถัดไปที่พร้อมหรือ None) สำหรับสแนปช็อตหนึ่งต่อคำขอ การเรียกแบบบล็อกเริ่มต้นก็เพียงพอ
ขณะนี้เจ้าของสามารถเข้า URL และรับเฟรมใหม่ได้