☰
一份引擎两个平台:EyeGestures视线追踪如何用Rust核心同时支撑Web与Python
2026/11/6 1:43:51 网站建设 项目流程
  • 计算机视觉
  • AI 应用

【免费下载链接】EyeGestures

gaze tracking software

项目地址:https://gitcode.com/gh_mirrors/ey/EyeGestures
点击查看免费下载

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方法每帧做四件事:

  1. 提取眼部关键点:从 MediaPipe 的 478 个面部 landmark 中挑出左右眼轮廓与瞳孔(468/473 号点),并对坐标做归一化,消除头部缩放/位移的影响
  2. 校准预测:把关键点送入 engine/src/calibrator.rs 中的Calibrator——一套线性回归 + 高斯消元求解,配合 25 个固定校准点(engine/src/calibrator.rs);代码里 "Match JS MLR behavior" 的注释说明它是 Web 端算法的忠实移植
  3. 20 帧滑动平均:对原始预测做平滑,抑制抖动
  4. 状态输出:返回 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-syspyo3
入口类EyeGesturesEngineWasmEyeGesturesEnginePython
编译命令wasm-pack build --target webmaturin 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.13

pyproject.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 都不用写。

📦 这套架构的可借鉴之处

  1. 核心与运行时解耦:把纯算法(浮点进、浮点出)与 I/O(摄像头、屏幕、GUI)严格分层,核心零平台依赖
  2. feature flags 一个工程出两种产物:wasm与python作为 feature,配合#[cfg],避免维护两份源码
  3. 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

项目地址:https://gitcode.com/gh_mirrors/ey/EyeGestures
点击查看免费下载
上一篇:11.8k stars、日榜第 14:Needle 到底踩中了开源社区的哪根神经?
下一篇:日均 3 万次代码合并的秘密武器开源了,开发者社区连夜开卷

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询