之前我不是搞眼动追踪吗?最近有篇论文还挺有意思的,周末了稍微写一下:

整体设计非常的简单,就是两个事件摄像头,加一个 CNN 的芯片+Nordic 传输数据出去:

两个Speck2f单元

作者做了一副真正能戴在头上的、用电极少得离谱(每只眼 <5 mW)的眼动追踪眼镜

传感器用的是 event-based vision sensor(事件相机),只在亮度变化时产生“事件”,天然高时间分辨率、低数据量;处理用的是 Speck2f 神经形态芯片(板上集成事件相机 + 卷积 SNN 核);输出坐标用一个低功耗 nRF52840 MCU 做轻量级解码。

目标任务:实时跟踪瞳孔中心坐标 + 给出置信度,做到戴在头上,电池供电;双眼 100 Hz 输出;每只眼平均 <5 mW 功耗(芯片本身约 4.2 mW)

为什么要搞事件相机 + 神经形态硬件?

传统方案的问题

传统眼动仪一般用帧相机 + CNN/传统图像处理:必须几十到上百 FPS 地采帧 → 数据量大、功耗高;图像是“静态快照”,高速眼动时容易运动模糊;需要 CPU/GPU 做 dense 图像处理 → 对穿戴设备来说太重、太费电。

事件相机(EVS)的好处

EVS 的工作方式:每个像素监测“对数亮度变化”,一旦超过阈值,就立刻发一个事件 (x,y,t, polarity);没变化就没事件 → 数据天然稀疏;时间分辨率微秒级,没有运动模糊,动态范围也大。

非常适合:眼珠快速转动(saccade),光照变化大的场景,低功耗、always-on 设备

为什么一定要“神经形态 SoC”而不是普通 MCU/GPU?

问题在于:事件流是异步、稀疏的,如果你把它累积成帧再喂 CNN,本来省下来的功耗又被吃回去了;Speck2f 的 SNN 核是按照“来一个 spike 就处理一次”,全异步事件驱动,而且和传感器在一个 die 上;传感器是事件驱动的,计算也是事件驱动的,两边风格统一,就能把功耗压到毫瓦级。

硬件系统结构:一副“神经形态眼镜”

放大看也很是粗糙

看论文第一页的照片(Fig.1 上图):

每只眼:1 颗 Speck2f SoC + 一圈 IR LED 环(照亮眼睛、制造对比度)

两只眼共用:一个 nRF52840 MCU

电源:两片 3.7 V 纽扣电池(每个镜腿一片)

数据流大致是:

IR LED 打光,Speck2f 上的 128×128 事件相机拍眼睛;眼睛边缘、瞳孔边缘产生的亮度变化 → 形成事件流;事件直接进入片上的 9 个卷积 SNN 核中的 7 个,形成一个 7 层 SNN;SNN 最后一层输出 15 个“输出神经元”的脉冲序列。

MCU 通过 SPI 周期性读出这 15 个神经元活动,做一个门控解码器 (gated decoding),输出:

(x, y) 归一化瞳孔中心坐标

unc:这一帧的预测不确定度

下图画的就是:左边 Speck2f 异步 SNN,右边 MCU 100 Hz 同步解码

Speck2f 芯片 & SNN 的限制

Speck2f 概况

128×128 事件相机 + 9 个卷积 SNN core 集成在一颗数字 SoC 里;

每个 core:

8 bit 权重

16 bit 神经元电压

有 SOP(synaptic operations)带宽限制:

第一层最多 100 M SOP/s

后面每层 30 M SOP/s

读出方式:片上有一个 专用 readout core,只能通过 SPI 访问;最多监控 16 个输出神经元,而且 0 号永远静默 → 实际最多 15 个可用;输出的是按 1/16/32 个 SCLK 周期的移动平均脉冲数,不是总计数。

以前所有工作几乎都用 FPGA 开发板接 Speck2f:

FPGA 本身静态功耗就在 0.6 W 量级,而 Speck2f 自己静态功耗只有 0.5 mW,系统功耗完全被“壳子”吃光了;这篇文章的一个重要点就是:不用 FPGA,只用 MCU + SPI 和 SoC

SNN 结构

他们用 7 个 core 堆了一个非常小的 CNN:2511.20175v1

输入:两通道 128×128 (正极性事件 / 负极性事件的计数图像)

每层:3×3 卷积 + 步幅(strided) + IF 神经元;

通道数:{4, 12, 18, 27, 40, 60, 15}

总参数量:46.2k

不用 bias(因为实现 bias 要额外同步 update,违背异步 flavor)

神经元模型用的是“无泄露的 IF 神经元 + 软重置”:

当  时:

On-chip:最多发 1 个 spike,并做 soft reset 

Off-chip 训练:发  个 spike(这样统计量更接近真正异步行为)

为防止一次权重就把电压打过多阈值,他们约束 w < v_th,避免 reality gap;训练时用 surrogate gradient(反向传播时对发放函数用光滑近似)。

训练数据:真实多用户事件数据集

他们自己采了一个数据集:

8 个被试,每人多段序列,共 432 段:369 用于训练,63 用于验证

每段 3 s,只看一只眼;被试用下巴托固定头部,看屏幕上的移动小点;换不同背景颜色改变瞳孔大小;用 4 颗不同 Speck2f 拍,加入硬件差异;真实眨眼、自然眼动都保留;真值瞳孔中心:人工标注,100 Hz。

训练时的输入格式:事件流切成 ∆t = 10 ms 的窗口,把该窗口内每个像素的正负事件累计成两通道计数图 → 类似 100 Hz 的事件帧。

来自真实数据集的代表性样本(左图和下图)展示了不同用户和采集条件下的事件流。颜色用于区分事件极性:红色代表阴性,绿色代表阳性。中心热图显示了真实瞳孔中心的分布,边缘直方图则指示了每个轴上的覆盖范围。

MCU 上的“门控解码 + 不确定度估计”

Speck2f 只输出 15 维的 spike 活动 。在 MCU 上,他们用一个非常轻量的“门控单元”来做时间整合和回归:

先把当前输出  与上一时刻隐藏状态  拼在一起,经过一层全连接 + sigmoid 得到门控向量 

索尼基于时识科技Speck2f芯片实现功耗<5mW全集成的可穿戴眼动追踪

隐状态更新:

如果事件很多(眼睛在动), 会偏向用现在的 

如果几乎没事件(注视 / 眨眼), 会偏向保留历史 

把  做 min-max 归一化后,过线性层,得到:

(x_hat, y_hat):瞳孔中心归一化坐标(用 sigmoid 限制到 [0,1])

u_hat:对数方差(log variance),代表预测的 观测噪声(aleatoric uncertainty)2511.20175v1

整个解码器算力很小,大约 1.1k FLOPs,一块低功耗 MCU 轻松 100 Hz 跑满。

不确定度建模的 loss

损失用了 Kendall & Gal 的不确定度加权 MSE:2511.20175v1

当前误差大 → 会倾向学到更大的 (不确定度)

但第二项  又会惩罚过大的不确定度

好处:遮挡、眨眼、事件少的时候,模型会说“我不太确定”,而不是瞎给一个点;下游系统可以利用不确定度做鲁棒决策。

活动正则:直接用 SOP 带宽做“硬件感知正则”

因为每个 core 有 SOPs 上限,所以训练时要控制网络整体脉冲活动;否则:仿真时没问题 → 上板跑会超带宽、变慢甚至丢事件。

作者定义每层的 SOP 估计:

(上一层脉冲计数 × 连接矩阵,除以时间窗)2511.20175v1

然后定义惩罚:

如果当前 SOP 超过阈值 ,才罚;否则不管。 总正则项:对中间层 SOP 和最后一层的输出 spike 数做这种“超标惩罚”。

SOP 阈值:每层 20 M;输出层 spike 阈值:83.3k(对应 readout 能力);这样训练出来的网络,在 Speck2f 实机上可以稳稳跑满而不超载。

Readout 的工程难点:SPI 只能看 15 个神经元,还有硬件 bug…

循环读出(cyclic readout)

问题 1:readout core 只有一个 SPI 接口,每次只能读一个神经元的活动。

解决:在每个 ∆t 窗口(10 ms)内,MCU 尽可能快地轮询 15 个输出神经元:

用 SCLK 做基准,读 neuron 0,1,2,…,14

75 µs 左右读完一个 → 15 个差不多 2.6 ms 内搞定;每 10 ms 完成一个完整的“轮询周期”,就得到 15 维的  向量给解码器;时间偏差(2.6 ms)相对 10 ms 还是很小,可以接受。

移动平均 & Spike multiplier

问题 2:readout 给的是16 个 SCLK 周期内的平均脉冲数,不是总数;如果事件很少,平均结果就更模糊。

他们的解决办法是:“在网络末尾插一个 spike 乘法层”:把每个输出神经元接到 N 个新神经元(权重=1, 阈值=1);这样原本 1 个 spike 现在变 N 个 spike;再把这些 new neurons 映射到 readout core 上,从读出的平均值里“放大”信号。

因为芯片的一个映射 bug(S3 节),他们实际上用 N=4,再加一个 4:1 的连接,总体放大 16 倍。

戴在头上的可穿戴原型

然后是重头戏:把两个 Speck2f 焊在自制 PCB 上,挂在眼镜框上,MCU 通过 SPI + 蓝牙工作。

image-20251206155447985

实验设置:3 个被试戴着眼镜看屏幕上的移动点(固定距离、下巴托);先录一段校准序列,用线性变换对齐预测坐标和屏幕坐标;测试两种眼动模式:smooth pursuit(平滑跟踪)和 saccade(扫视,快速跳动)。2511.20175v1

结果大致是:

不同用户、背景色、左右眼、轴向之间表现差异不大,说明泛化不错;

saccade 比 pursuit 难很多:saccade 时事件是“突发 + 长时间寂静”,网络的时间建模能力有限,fixation 阶段误差更大;

功耗:

pursuit:每只眼 Speck2f 大约 2.5 mW;

saccade:快速跳动时瞬时功耗到 6–8 mW,停住时又回到 ~1.5 mW;

MCU 自身平均约 13.6 mW。2511.20175v1

这套系统整体就是:每只眼芯片 <5 mW + 一个十几毫瓦 MCU → 真·电池眼镜级别

局限

论文最后也很诚实地说了不足:

网络结构受限很厉害:只能用非常简化的 CNN + IF 神经元,没法用更复杂的时序模型(比如更强的 recurrent 单元);有两个 core 被 spike multiplier 占掉了,如果未来硬件能直接给总 spike 数 / 更灵活 readout,网络可以做大很多。

输出频率目前只到 100 Hz:不是硬件极限,而是因为数据真值只有 100 Hz;理论上如果有更快真值,MCU 可以 500 Hz / 1 kHz 更新坐标,而芯片功耗几乎不变(事件总量不变)。

精度依然有限:对于需要“精确 gaze point” 的 AR/VR 眼控系统可能还不够;但对“粗略注视、vergence 估计、简单交互”等应用已经够用。

把 事件传感器 + SNN + 置信度输出 + 功耗监测 这一整条链打通,用实测功耗曲线证明“事件多 → 功耗高,事件少 → 功耗低”,非常符合“只在有信息时才花能量”的神经形态理念。

https:///pdf/2511.20175