12.10. 总结¶
一个通过 USB 线缆接入的摄像头,能够将帧流式传输到主机程序、接受来自主机的配置更新回传,并在拔插后不丢失同步——其中重传被隐藏、多个逻辑流共享一个端口,且应用程序中没有任何组帧代码——这一切只需约四十行摄像头端代码以及主机端相近的代码量。协议库将一个字节管道变成了一个可编程的通道面,并让应用层之下的一切保持不可见。
12.10.1. 本章构建了什么¶
协议栈的四层心智模型:传输层、组帧层、可靠性层、通道层。每一层只解决一个问题,并忽略其上的一切。
传输线路上的数据包格式——带 CRC 的 10 字节报头、可变长度负载、尾部 CRC。小到足以逐字节地走一遍。
传输连接建立时摄像头和主机所执行的握手:PROTO_SYNC、能力交换、通道发现。
在其之上的可靠性机制:序列号、ACK、NAK、带指数退避的重传,以及十个状态码。
通道模型:一条线路上最多 32 个命名逻辑流,内置
stdin/stdout/stream/profile以及通过 Python 类注册的应用程序通道。后端接口——
size、read、write、poll、lock/unlock、shape、ioctl、flush、is_active——以及协议库如何利用后端上存在的方法来决定通道所支持的功能。主机端:openmv-python SDK 的
Camera类、将 USB-CDC 切换到协议模式的921600波特率魔法值,以及channel_size/channel_read/channel_write的往返模式。一种帧流式传输模式——单缓冲区捕获、带锁存器的
readp、用于新帧通知的send_event——以及一种双向配置模式(主机可写通道、JSON 往返),二者共同构成了每一个交互式摄像头工具的基础。
12.10.2. 参考路线图¶
当这些功能之一在实际代码中出现时,库参考页面就是查阅的目的地:
protocol --- OpenMV 协议通道 ——
protocol模块、protocol.init()、protocol.register()、ProtocolChannel、通道标志常量,以及逐摄像头的最大负载对照表。主机 SDK——
pip install openmv、openmv.camera.Camera。本章涉及的方法:update_channels()、has_channel()、channel_size()、channel_read()、channel_write()、poll_events()、read_frame()、exec()以及stop()。openmv-projects 仓库——基于协议库构建的真实工具。tools/ 目录包含
thermal-overlay-calibration(RGB 与热成像对齐 GUI)、ccm-tuning(颜色校正矩阵调谐器)、genx320-event-streaming和genx320-overlay-calibration(事件相机工具)。它们每一个都从头到尾使用了本章中的模式。
12.10.3. 下一步走向何方¶
摄像头项目从这里出发有几个方向:
构建主机 GUI。 一个帧通道馈送视频部件,一两个配置通道馈送滑块和按钮。对于 GUI 层本身,DearPyGui 是自然的选择——纯 Python、可通过 pip 安装、速度足以支持实时预览,也是每一个现有 OpenMV 主机工具首先选用的方案。
多通道遥测仪表盘。 同一台摄像头上的若干应用程序通道(传感器读数、计数器、状态事件)各自在自己的回调中刷新,主机 GUI 在定时器上读取它们并分别渲染每一个。通道层独立的流量控制意味着一个缓慢的读取不会拖住其他读取。
通过 UART 进行远程调谐。 使用相同的通道回调;应用程序调用
protocol.init从 USB 切换到 UART 传输。摄像头持续无头运行,树莓派或笔记本电脑上的 Python 脚本通过一条串行线路与之通信,用于现场调谐。
传输线路格式、可靠性层和通道抽象都不会改变。挑选适合部署场景的传输方式,并为主机需要查看或设置的每件事添加一个通道,这就是从此往后的全部工程工作。