用手机后置摄像头 + 闪光灯(或外部灯光)实现接触式指尖光电容积脉搏波(PPG),测量心率、心率变异性(HRV)并评估压力水平。
PulseCalm 是一款纯本地、无账号、无联网的 Android 应用。它把手指轻贴在手机后置摄像头与闪光灯上,利用透射光随心脏搏动产生的微小亮度变化(PPG 信号)反演出心率与 HRV,并据此给出压力指数。
开源地址: https://github.com/lichuang07/PulseCalm
- 双光源模式:默认「闪光灯」常亮补光(信号最稳);也支持「外部灯光」模式(关闭闪光灯,依靠环境光或自行打光),适合闪光灯效果欠佳的设备。
- 心率与 HRV:实时估算心率,离线分析得到 SDNN、RMSSD、pNN50 等时域指标,以及 5 分钟深度模式下的 LF/HF 频域指标。
- 压力评估:以 Baevsky 压力指数(SI)为主、结合 RMSSD 与静息心率给出压力评分与等级。
- 呼吸引导:内置 4-7-8 呼吸训练,辅助放松。
- 本地趋势:测量记录以本地 JSON Lines 形式保存,提供趋势图,不依赖任何云端账号。
- 信号质量反馈:以信号质量(SQI)驱动实时引导("轻一点 / 别抖 / 贴合"),降低误测。
- 采集:Camera2 以最小 YUV 分辨率持续取帧,取 G 通道全画面均值作为每一时刻的光强采样。
- 降噪抑制:刻意关闭相机固件的降噪与边缘增强、锁定自动曝光与白平衡、关闭自动对焦与防抖——这些"优化"会把本就微弱的 PPG 交流分量平滑掉。
- 信号处理:去趋势 → 0.5–4 Hz 零相位带通 → 峰值检测。30 fps 下相邻帧间隔约 33 ms,直接用整数帧做峰位会带来 ±16 ms 量化误差,足以淹没 RMSSD;因此用三点抛物线插值把峰位细化到约 5 ms 量级。
- HRV 与压力:由相邻心搏间隔(IBI)序列计算时域/频域指标,再映射为压力指数。
关于"非接触式":指尖完全贴合镜头采集属于接触式 PPG,其信噪比远高于纯远程(rPPG)方案,是本应用采用的做法。
| 工具 | 版本 |
|---|---|
| Android Gradle Plugin | 9.4.1 |
| Gradle | 9.7.0(仓库自带 wrapper) |
| Kotlin | 2.4.21 |
| JDK | 17 |
| compileSdk | 37 |
| minSdk | 26 |
| Compose BOM | 2026.09.00 |
# 1. 准备 local.properties(复制示例并填入你的 SDK 路径)
cp local.properties.example local.properties
# 然后编辑 local.properties 设置 sdk.dir
# 2. 编译 Debug 包
./gradlew assembleDebug
# 产物位于 app/build/outputs/apk/debug/app-debug.apk用 Android Studio 打开本项目、点击 Run 亦可。首次构建需联网下载依赖。
- 打开应用,进入「测量」页,选择光源模式(闪光灯 / 外部灯光)。
- 按提示用食指指腹轻贴后置摄像头:
- 闪光灯模式:盖住摄像头和闪光灯;
- 外部灯光模式:盖住摄像头即可,可另用台灯从侧面稳定打光。
- 力度要轻,像把手指放在镜头上休息;测量过程中保持静止、正常呼吸。
- 60 秒快速测量给出心率 / HRV / 压力指数;5 分钟深度测量额外提供 LF/HF。
本应用不是医疗器械,不能诊断、治疗、治愈或预防任何疾病。 测量结果仅供参考,请勿用于医疗决策。如有身体不适,请咨询医疗专业人士。
本项目以 MIT License 发布。
Copyright (c) 2026 李闯 (lichuang07)