- 计算机视觉
- AI 应用
【免费下载链接】EyeGestures
gaze tracking software
EyeGestures 是一款开源视线追踪(眼动追踪)库,只需普通摄像头就能把"目光"变成屏幕上的光标与交互事件,无需昂贵硬件。它的 V4 版本完成了一次关键重构:核心算法统一用 Rust 写成一份引擎,再通过 WebAssembly 与 pyo3 两个"薄适配层",让同一套视线追踪算法同时跑在浏览器和 Python 桌面程序中。本文带你快速看懂这份"一份引擎、两个平台"的架构是如何搭起来的。
🎯 为什么要收敛到"一份核心"?
EyeGestures 早期有两条并行的算法路线:桌面端是纯 Python 实现,Web 端是 JavaScript 实现(EyeGesturesLite)。README 中明确写道,随着 Rust 引擎发布,"fully pythonic engines become deprecated",动机就是"single algorithm powering eyegestures applications"——用同一个算法驱动所有版本,因为维护多套引擎已经超出能力范围。
这带来的直接好处:
- 修一次 Bug,两个平台同时受益:校准逻辑、平滑策略只需在 Rust 里改一次
- 行为一致:网页版和桌面版的视线输出完全同构,均为
[x, y, calibrating, calib_x, calib_y]五个数 - 性能更好:核心计算全部编译为机器码,Python/JS 侧不再承担算法开销
🧠 核心只有一个:EyeGesturesCore
真正的"大脑"在 engine/src/eyegestures.rs 中,源码注释直接写明它的身份:"Shared core gaze tracking logic (wasm + python)"。
它的process_landmarks方法每帧做四件事:
- 提取眼部关键点:从 MediaPipe 的 478 个面部 landmark 中挑出左右眼轮廓与瞳孔(468/473 号点),并对坐标做归一化,消除头部缩放/位移的影响
- 校准预测:把关键点送入 engine/src/calibrator.rs 中的
Calibrator——一套线性回归 + 高斯消元求解,配合 25 个固定校准点(engine/src/calibrator.rs);代码里 "Match JS MLR behavior" 的注释说明它是 Web 端算法的忠实移植 - 20 帧滑动平均:对原始预测做平滑,抑制抖动
- 状态输出:返回 GazeResult(注视坐标、是否处于校准中、当前校准目标点)
此外还有 engine/src/fixation.rs 负责注视(fixation)强度计算。整个核心不依赖任何平台 API,只处理纯浮点数数组——这正是它能"一份代码、两端运行"的前提。
🔌 两个适配层:同一批 API,两套绑定
engine/src/lib.rs 用 Rust 的条件编译把平台模块隔开:
#[cfg(target_arch = "wasm32")] pub mod wasm; #[cfg(feature = "python")] pub mod python;也就是说,同一份 Cargo 工程,编译目标不同、feature 不同,产出的东西完全不同:
| 🌐 Web(WASM) | 🐍 Python | |
|---|---|---|
| 绑定框架 | wasm-bindgen+web-sys | pyo3 |
| 入口类 | EyeGesturesEngineWasm | EyeGesturesEnginePython |
| 编译命令 | wasm-pack build --target web | maturin build --features python |
| 分发形式 | npm 包 / CDN 脚本 | PyPI 包eyeGestures |
两个适配层暴露的 API 几乎完全对称:new(screen_width, screen_height)、process(landmarks) -> [f64; 5]、add_calibration_point(x, y)、recalibrate();Python 侧仅额外多了calib_counter、calib_max两个 getter。依赖的开关则集中在 engine/Cargo.toml:default = ["wasm"],python = ["pyo3"],且 crate 类型为cdylib + rlib,天然支持编译成 WASM 模块和 Python 扩展两种产物。
🌐 Web 端:wasm-pack 编译 + JS 封装
构建链路写在根目录 Makefile 的wasm目标里:先执行wasm-pack build --target web把 Rust 编译成浏览器可用的EyegesturesEngine.js,再用 terser 压缩产出eyegestures.min.js。
运行时的胶水代码在 web/src/eyegestures.js:
this.engine = new engineModule.EyeGesturesEngineWasm(width, height);之后 MediaPipe FaceMesh 每检测一帧人脸,就把 478 个 landmark 拍平成一维数组,交给this.engine.process(flattened)(见 web/src/eyegestures.js),拿到五个数后驱动蓝色光标。JS 层只负责摄像头、人脸检测、DOM 渲染这些平台杂活,算法全部在 WASM 里完成。
🐍 Python 端:maturin 编译 + Python 封装
Python 侧的构建链路在根 Makefile 的python目标:
maturin build --release --no-default-features --features python --interpreter python3.12 python3.13pyproject.toml 中的[tool.maturin]段把构建指向同一个 Rust 工程:manifest-path = "engine/Cargo.toml"、features = ["python"]、module-name = "eyeGestures.EyegesturesEngine"。仓库里甚至直接带着编译产物 EyegesturesEngine.cpython-313-x86_64-linux-gnu.so(另有 cpython-314 版本)可以印证这一点。
上层封装在 eyeGestures/__init__.py:EyeGestures_v4.step()里先实例化RustEyeGesturesEngine(width, height),再把 mediapipe 检测出的 landmark 拍平后调用self.engine.process(...)(见 eyeGestures/__init__.py)。用户完全感知不到底层是 Rust——依赖的mediapipe、opencv只负责人脸与眼部检测,视线回归计算本身一行 Python 都不用写。
📦 这套架构的可借鉴之处
- 核心与运行时解耦:把纯算法(浮点进、浮点出)与 I/O(摄像头、屏幕、GUI)严格分层,核心零平台依赖
- feature flags 一个工程出两种产物:
wasm与python作为 feature,配合#[cfg],避免维护两份源码 - FFI 边界刻意保持简单:跨语言只传一个扁平
f64数组,不做复杂对象映射,序列化与版本兼容成本几乎为零
🚀 快速上手
- 桌面端:
pip install eyeGestures,然后运行官方示例 examples/simple_example_v4.py——校准 25 个红点后即可用目光移动红色光标 - Web 端:参考 web/example/simple.html 的页面结构,或通过 npm 安装
eyegestures包(web/package.json)
一句代码看懂全貌:无论是浏览器里的new EyeGesturesEngineWasm(...),还是 Python 里的RustEyeGesturesEngine(...),它们背后都是同一个 EyeGesturesCore——这正是"一份引擎、两个平台"的全部秘密。
- 计算机视觉
- AI 应用
【免费下载链接】EyeGestures
gaze tracking software
相关推荐
从Nova3D到FormaNova:同一套引擎如何支撑专业珠宝CAD设计
从Nova3D到FormaNova:同一套引擎如何支撑专业珠宝CAD设计 Nova3D 是一个面向 可编程 3D 设计 的工作区:它把资产与场景构建为 可编辑、
JJYB_AI智剪开发者指南:23个API路由与24个核心引擎如何撑起AI视频剪辑
JJYB_AI智剪开发者指南:23个API路由与24个核心引擎如何撑起AI视频剪辑 JJYB_AI智剪是一款面向视频创作者的 本地 AI 视频自动剪辑与智能解说
nfsu2-web 网络架构详解:Rust 服务器如何支撑 14000 人同时自由漫游?
nfsu2 web 网络架构详解:Rust 服务器如何支撑 14000 人同时自由漫游? nfsu2 web 是一个让经典赛车游戏《极品飞车:地下狂飙2》(NF
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考