Skip to content

实时心率估算器

NOTE

僅限网页 SDK 实时估算功能目前僅适用於网页版 SDK(JavaScript、React、Vue)。不适用於行動装置 SDK(iOS、Android、Flutter、React Native)。

概述

实时估算器在影片撷取過程中提供实时心率反馈,最快可在 3-8 秒內显示结果,无需等待完整的 30 秒扫描。這創造了更具吸引力的使用者體驗,並幫助使用者调整位置和光线以获得最佳测量结果。

快速开始

typescript
import { createVitalSignCamera, RealtimeEstimatorType } from 'ts-vital-sign-camera';

const camera = createVitalSignCamera({
  realtimeEstimationConfig: {
    estimatorType: RealtimeEstimatorType.Panoptic // 预设
  },
  onVideoFrameProcessed: (event) => {
    // 实时估算可從事件中取得
    if (event.realtimeEstimation) {
      console.log(`心率:${event.realtimeEstimation.heartRate} BPM`);
      console.log(`置信度:${event.realtimeEstimation.confidence}`);
      console.log(`稳定:${event.realtimeEstimation.isStable}`);
    }
  }
});

简单设置

想要以最简洁的方式使用 Panoptic 估算器默认值,请使用 enableRealtimeEstimation 布尔值:

typescript
import { createVitalSignCamera } from 'ts-vital-sign-camera';

const camera = createVitalSignCamera({
  enableRealtimeEstimation: true,
  onVideoFrameProcessed: (event) => {
    if (event.realtimeEstimation) {
      console.log(`心率:${event.realtimeEstimation.heartRate} BPM`);
    }
  }
});

Vue SDK:

vue
<VitalSignCamera
  :enableRealtimeEstimation="true"
  @onVideoFrameProcessed="onVideoFrameProcessed"
/>

这会以合理的默认值(signalQualityDelay: 0)启动 Panoptic 估算器。若需要自定义配置,请使用 realtimeEstimationConfig

可用的估算器

ME-rPPG 估算器 🤖

AI 驱动的神經網路方法

  • 最適合:消费者应用程序、变化的环境、现代装置
  • 准确度:最先進(±2-3 BPM)
  • 速度:約 3 秒內首次结果
  • 动作容忍度:优秀
  • 光线容忍度:优秀
  • 授权:开源
  • 需求:約 10 MB 模型文档
typescript
const camera = createVitalSignCamera({
  realtimeEstimationConfig: {
    estimatorType: RealtimeEstimatorType.MeRppg
  }
});

Panoptic 估算器(预设)📈

信号处理方法

  • 最適合:医疗应用程序、实时初始化、最小套件大小
  • 准确度:医疗级(±2-3 BPM)
  • 速度:約 5 秒內首次结果
  • 动作容忍度:良好
  • 光线容忍度:良好
  • 授权:专有(PanopticAI)
  • 需求:无(实时初始化)
typescript
const camera = createVitalSignCamera({
  realtimeEstimationConfig: {
    estimatorType: RealtimeEstimatorType.Panoptic
  }
});

配置选项

基本配置

typescript
interface RealtimeEstimationConfig {
  // 要使用的估算器
  estimatorType?: RealtimeEstimatorType;
  
  // 信号质量计算延迟(秒)
  signalQualityDelay?: number;
  
  // 启用调试记录
  debug?: boolean;
}

ME-rPPG 特定选项

typescript
{
  // 模型文档路径(可選,提供预设值)
  modelPath?: string;
  statePath?: string;
  welchPath?: string;
  hrPath?: string;
  
  // 時間正规化参数
  lambda?: number; // 预设:1.0
}

估算结果

RealtimeEstimation 接口

typescript
interface RealtimeEstimation {
  // 心率(BPM)
  heartRate: number;
  
  // 置信度(0-1)
  confidence: number;
  
  // 结果是否足夠稳定可显示
  isStable: boolean;
  
  // 信噪比(可選)
  snr?: number;
  
  // 信号质量分数 0-100(可選)
  signalQuality?: number;
}

使用估算结果

typescript
camera.onVideoFrameProcessed = (event) => {
  const estimation = event.realtimeEstimation;
  
  if (!estimation) return;
  
  if (estimation.isStable && estimation.confidence > 0.6) {
    // 高置信度 - 显著显示
    displayHeartRate(estimation.heartRate);
  } else if (estimation.confidence > 0.3) {
    // 中等置信度 - 显示指示器
    displayHeartRate(estimation.heartRate, '精炼中...');
  } else {
    // 低置信度 - 引导使用者
    showMessage('调整中... 请保持静止');
  }
};

信号可视化

如需实时信号可视化(PPG 和呼吸波形)的完整文档,请参阅信号可视化器指南

信号可视化器会在相机画面旁显示滚动的 PPG/呼吸波形数据。它是一个独立组件,通过相机的 visualizer 属性或 onVideoFrameProcessed 回调进行连接。

如需完整的可视化选项(包括热图、边界框和面部网格叠加层),请参阅可视化选项总览

SDK 行為

时间轴

0秒 ────────► 5秒 ────────► 8秒 ────────► 15秒 ────────► 30秒
│            │            │            │             │
│            │            │            │             └─ 完整扫描完成
│            │            │            └─ 达到最佳准确度(Panoptic 15秒)
│            │            └─ 首次实时估算(Panoptic 预热完成)
│            └─ 信号质量延迟
└─ 扫描开始

估算生命周期

  1. 初始化(0-3秒)

    • 相机开始撷取
    • 人脸侦测启动
    • 信号缓冲区填充
  2. 早期估算(3-5秒)

    • 首次结果可用
    • 较低置信度
    • 持续精炼
  3. 稳定估算(10秒以上)

    • 高置信度结果
    • 最佳准确度
    • 準備显示
  4. 扫描完成(30秒)

    • 服务器端验证
    • 最終结果可用
    • 实时估算器可重置

事件流程

typescript
// 扫描生命周期
camera.onVideoFrameProcessed = (event) => {
  // 实时估算在此可用
  if (event.realtimeEstimation) {
    console.log('实时更新:', event.realtimeEstimation);
  }
};

camera.startScanning(); // 开始扫描

// 最終结果來自健康结果
camera.onVideoFrameProcessed = (event) => {
  if (event.healthResult) {
    console.log('最終结果:', event.healthResult);
  }
};

最佳實踐

1. 选择正確的估算器

typescript
// 适用於具有变化环境的消费者应用程序
const config = {
  estimatorType: RealtimeEstimatorType.MeRppg
};

// 适用於需要实时初始化的医疗应用程序
const config = {
  estimatorType: RealtimeEstimatorType.Panoptic,
  signalQualityDelay: 10
};

2. 提供使用者反馈

typescript
camera.onVideoFrameProcessed = (event) => {
  const estimation = event.realtimeEstimation;
  if (!estimation) return;
  
  // 显示置信度指示器
  updateConfidenceBar(estimation.confidence);
  
  // 根据质量引导使用者
  if (estimation.confidence < 0.4) {
    showTip('改善光线或保持静止');
  }
  
  // 稳定時显示
  if (estimation.isStable) {
    displayHeartRate(estimation.heartRate);
  }
};

3. 处理边缘情况

typescript
let noEstimationTimeout;
let hasReceivedEstimation = false;

camera.startScanning();

// 设定无估算的超时
noEstimationTimeout = setTimeout(() => {
  if (!hasReceivedEstimation) {
    showError('无法侦测心率。请调整光线。');
  }
}, 15000); // 15 秒

camera.onVideoFrameProcessed = (event) => {
  const estimation = event.realtimeEstimation;
  
  if (estimation) {
    hasReceivedEstimation = true;
    clearTimeout(noEstimationTimeout);
    
    if (estimation.confidence > 0.5) {
      hideError();
    }
  }
};

4. 最佳化效能

typescript
// 节流 UI 更新
let lastUpdate = 0;
const UPDATE_INTERVAL = 500; // 500毫秒

camera.onVideoFrameProcessed = (event) => {
  const estimation = event.realtimeEstimation;
  if (!estimation) return;
  
  const now = Date.now();
  if (now - lastUpdate > UPDATE_INTERVAL) {
    updateUI(estimation);
    lastUpdate = now;
  }
};

常见使用案例

健身应用程序

typescript
const camera = createVitalSignCamera({
  realtimeEstimationConfig: {
    estimatorType: RealtimeEstimatorType.MeRppg
  },
  onVideoFrameProcessed: (event) => {
    if (event.realtimeEstimation) {
      updateWorkoutDisplay(event.realtimeEstimation.heartRate);
      updateHeartRateZone(event.realtimeEstimation.heartRate);
    }
  }
});

医疗应用程序

typescript
const camera = createVitalSignCamera({
  realtimeEstimationConfig: {
    estimatorType: RealtimeEstimatorType.Panoptic,
    signalQualityDelay: 10
  },
  onVideoFrameProcessed: (event) => {
    const estimation = event.realtimeEstimation;
    if (estimation?.isStable && estimation.confidence > 0.7) {
      recordMeasurement(estimation);
    }
  }
});

使用信号可视化

如需完整示例,请参阅信号可视化器指南

疑難排解

无实时估算

问题:事件中未收到实时估算

解决方案

  1. 等待预热完成(Panoptic 约 5-8 秒)
  2. 检查人脸是否正確侦测
  3. 验证光线条件是否充足
  4. 检查 event.realtimeEstimation 不为 null

低置信度分数

问题:置信度持续低于阈值

解决方案

  1. 改善光线(自然光最佳)
  2. 确保使用者保持静止
  3. 检查人脸是否居中且稳定
  4. 如果置信度持續較低,考虑使用 ME-rPPG 以获得更好的动作容忍度

ME-rPPG 模型未加载

问题:模型加载失败

解决方案

  1. 验证模型文档在正確的目录中
  2. 检查 CORS 标头允许模型加载
  3. 确保正確的文档路径(使用绝对路径)
  4. 检查浏览器控制台是否有错误

API 参考

RealtimeEstimator 接口

typescript
interface RealtimeEstimator {
  readonly estimation: RealtimeEstimation | null;
  readonly signalData: SignalData | null;
  
  configure(config?: RealtimeEstimationConfig): void;
  reset(): void;
}

SignalVisualizer 類別

typescript
class SignalVisualizer {
  constructor(container: HTMLElement, config?: SignalVisualizerConfig);
  
  updateSignal(
    signalData: SignalData | null,
    realtimeEstimation?: RealtimeEstimation | null
  ): void;
  
  resetScale(): void;
  destroy(): void;
}

VideoFrameProcessedEvent

typescript
interface VideoFrameProcessedEvent {
  videoFrameInfo: VideoFrameInfo;
  videoFrame: VideoFrame;
  facebox?: NormalizedFacebox;
  healthResult?: ScanResult;
  scanConditions?: ScanConditions;
  landmarks?: NormalizedLandmarkList;
  
  // 实时估算数据
  realtimeEstimation?: RealtimeEstimation | null;
  signalData?: SignalData | null;
}

下一步