Panoptic 估算器
NOTE
僅限網頁 SDK 即時估算功能目前僅適用於網頁版 SDK(JavaScript、React、Vue)。不適用於行動裝置 SDK(iOS、Android、Flutter、React Native)。
概述
Panoptic 估算器是一個醫療級心率測量系統,使用進階訊號處理分析面部影片的光體積描記(PPG)訊號。它提供 Panoptic 級準確度,無需外部 AI 模型,非常適合醫療應用程式和即時初始化。
IMPORTANT
專有技術 Panoptic 估算器是 PanopticAI 開發的專有軟體。核心演算法在 WebAssembly 中執行以保護智慧財產權。
主要特點
- ✅ 醫療級:Panoptic 級準確度
- ✅ 即時初始化:無需模型載入
- ✅ 零依賴:無需外部檔案
- ✅ 確定性:相同輸入 → 相同輸出
- ✅ 輕量級:< 200 KB 記憶體佔用
- ✅ 自適應:~8 秒內首次估算,~15 秒內最佳
基本用法
typescript
import { createVitalSignCamera, RealtimeEstimatorType } from 'ts-vital-sign-camera';
const camera = createVitalSignCamera({
realtimeEstimationConfig: {
estimatorType: RealtimeEstimatorType.Panoptic
}
});
camera.onVideoFrameProcessed = (event) => {
const estimation = event.realtimeEstimation;
if (!estimation) return;
console.log(`心率:${estimation.heartRate} BPM`);
console.log(`信心度:${estimation.confidence}`);
console.log(`訊噪比:${estimation.snr}`);
};TIP
最簡設定:使用 enableRealtimeEstimation: true 即可啟用 Panoptic 估算器預設值 — 無需額外配置。
配置
適用於消費者應用程式
typescript
{
estimatorType: RealtimeEstimatorType.Panoptic,
debug: false
}適用於醫療應用程式
typescript
{
estimatorType: RealtimeEstimatorType.Panoptic,
signalQualityDelay: 10, // 延長品質計算等待時間
debug: false
}SDK 行為
初始化
typescript
// Panoptic 估算器即時初始化(無非同步載入)
const camera = createVitalSignCamera({
realtimeEstimationConfig: {
estimatorType: RealtimeEstimatorType.Panoptic
}
});
// 立即就緒 - 無需等待
camera.startScan();處理時間軸
0秒 ────► 5秒 ────► 8秒 ────► 15秒 ────► 30秒
│ │ │ │ │
│ │ │ │ └─ 掃描完成
│ │ │ └─ 最佳準確度(15秒視窗)
│ │ └─ 首次估算(暖機完成,3+ 估算)
│ └─ 訊號品質延遲(5秒)
└─ 掃描開始(即時初始化)暖機與平滑化
Panoptic 估算器應用內建暖機和平滑化機制,以確保穩定可靠的讀數。
暖機閘門
在估算器收集到 150 個 RGB 樣本(30fps 下約 5 秒)並累積至少 3 次估算之前,不會發出任何心率估算值。這可防止緩衝區填滿期間出現早期無效值。
- 典型首次估算時間:~8 秒(5 秒緩衝 + 3 次估算週期,以 1Hz 執行)
- 暖機期間,
onVideoFrameProcessed事件的realtimeEstimation為null。
1Hz 節流
訊號處理以 1 Hz(每秒一次)而非每幀執行。這確保每次估算都基於有意義的時間視窗,並使 EWMA 平滑化以自然速率調節。
EWMA 平滑化
指數加權移動平均平滑心率輸出:
typescript
// EWMA formulation used by the estimator
HR_smooth[t] = 0.4 * HR_raw[t] + 0.6 * HR_smooth[t-1]- α = 0.4 — 平衡反應速度與雜訊抑制(~2 秒時間常數)
- 種子值:所有暖機期間估算的中位數(抗離群值)
- 在不隱藏真實心率變化的情況下穩定顯示
變化率限制
連續估算之間的最大心率變化:±5 BPM/秒。這可防止動作偽影造成的突然跳動,同時仍追蹤真實趨勢。
typescript
// Clamp prevents artifactual jumps
if (Math.abs(delta) > 5) {
HR_output = HR_previous + sign(delta) * 5;
}自適應時間視窗
Panoptic 估算器使用自適應時間視窗,隨著更多資料到達而增長:
| 經過時間 | 視窗大小 | 準確度 | 狀態 |
|---|---|---|---|
| < 5 秒 | — | — | 暖機中(尚無估算) |
| 8 秒 | 8秒 | ±5-8 BPM | 首次估算 |
| 15+ 秒 | 15秒 | ±2-3 BPM | 最佳 ✓ |
typescript
camera.onVideoFrameProcessed = (event) => {
const estimation = event.realtimeEstimation;
if (!estimation) {
showMessage('分析中... 請保持靜止');
return;
}
if (getCurrentScanTime() < 15) {
showHeartRate(estimation.heartRate, '精煉中...');
} else {
showHeartRate(estimation.heartRate, '穩定 ✓');
}
};效能特性
| 指標 | 值 |
|---|---|
| 初始化 | 即時(< 10毫秒) |
| 首次結果 | ~8 秒 |
| 最佳準確度 | ~15 秒 |
| 處理速度 | 每幀 5-10 毫秒 |
| 記憶體使用 | < 200 KB |
| 套件大小 | 約 100 KB(WASM) |
| 典型誤差 | ±2-3 BPM |
| 心率範圍 | 50-140 BPM |
品質指標
訊噪比(SNR)
Panoptic 估算器提供 SNR 值以指示訊號品質:
| SNR | 信心度 | 品質 | 解釋 |
|---|---|---|---|
| 10+ | 1.0 | 優秀 | 完全信任 ✓ |
| 8-10 | 0.8-1.0 | 非常好 | 高度可靠 ✓ |
| 6-8 | 0.6-0.8 | 良好 | 可靠 |
| 4-6 | 0.4-0.6 | 尚可 | 可接受 |
| 2-4 | 0.2-0.4 | 差 | 考慮重試 |
| < 2 | 0.0-0.2 | 非常差 | 需要重試 |
typescript
camera.onVideoFrameProcessed = (event) => {
const estimation = event.realtimeEstimation;
if (!estimation) return;
if (estimation.snr && estimation.snr > 6) {
showQualityIndicator('優秀');
} else if (estimation.snr && estimation.snr > 4) {
showQualityIndicator('良好');
} else {
showQualityIndicator('差');
showTip('改善光線或減少移動');
}
};優勢
🏥 醫療級品質
- Panoptic 級準確度
- 符合已驗證的伺服器實作
- 適合醫療應用程式
- 有利於法規合規
📦 零依賴
- 無需下載模型檔案
- 即時初始化
- 立即離線運作
- 較小的套件大小
⚡ 快速初始化
- 無需非同步載入
- 立即可用
- 無需等待模型
- 更簡單的錯誤處理
🔒 智慧財產權保護
- WebAssembly 中的核心演算法
- 保護專有實作
- 二進位格式防止逆向工程
🎯 確定性
- 相同輸入 → 相同輸出
- 無 AI 隨機性
- 可重現結果
- 更易於除錯
何時使用
✅ 最適合
- 醫療和健康照護應用程式
- 法規合規要求
- 需要即時初始化
- 需要最小套件大小
- 離線優先應用程式
- 嵌入式系統和物聯網裝置
❌ 避免使用
- 使用者會大幅移動
- 光線條件不受控制
- 需要最大動作容忍度
- 需要開源授權
- 偏好 AI 驅動功能
疑難排解
低信心度分數
症狀:信心度 < 0.6,讀數不穩定
解決方案:
typescript
// 1. 改善環境條件
const instructions = [
"使用自然日光",
"避免背光",
"確保均勻照明",
"移除臉部陰影"
];
// 2. 減少動作
const motionTips = [
"保持完全靜止",
"測量期間不要說話",
"如果可能使用手機支架",
"保持穩定距離"
];
// 3. 檢查人臉偵測 - 注意:人臉偵測事件因 SDK 而異
// 對於網頁 SDK,檢查 VideoFrameProcessedEvent 中的 scanConditions
camera.onVideoFrameProcessed = (event) => {
if (event.scanConditions && !event.scanConditions.centered) {
showWarning('保持臉部居中且穩定');
}
};不穩定讀數
症狀:心率跳動
解決方案:
typescript
// 引導使用者
camera.onVideoFrameProcessed = (event) => {
const estimation = event.realtimeEstimation;
if (!estimation) return;
if (estimation.confidence < 0.6) {
showTip('請保持靜止並改善光線');
}
};最佳實踐
1. 漸進式回饋
typescript
camera.onVideoFrameProcessed = (event) => {
const estimation = event.realtimeEstimation;
if (!estimation) {
showMessage("分析中... 請保持靜止");
return;
}
if (getCurrentScanTime() < 15) {
if (estimation.confidence > 0.4) {
showHeartRate(estimation.heartRate, "精煉中...");
} else {
showMessage("調整中... 如果可能請改善光線");
}
} else {
if (estimation.isStable) {
showHeartRate(estimation.heartRate, "穩定 ✓");
} else {
showMessage("信心度低。在更好的條件下重試。");
}
}
};2. 品質指示器
typescript
function getQualityIndicator(estimation: RealtimeEstimation): string {
if (estimation.confidence >= 0.8) return "優秀 ⭐⭐⭐⭐⭐";
if (estimation.confidence >= 0.6) return "非常好 ⭐⭐⭐⭐";
if (estimation.confidence >= 0.4) return "良好 ⭐⭐⭐";
if (estimation.confidence >= 0.2) return "尚可 ⭐⭐";
return "差 ⭐";
}
camera.onVideoFrameProcessed = (event) => {
const estimation = event.realtimeEstimation;
if (!estimation) return;
updateQualityDisplay(getQualityIndicator(estimation));
};3. 重試邏輯
typescript
let retryCount = 0;
const MAX_RETRIES = 3;
camera.onVideoFrameProcessed = (event) => {
const result = event.healthResult;
if (!result) return;
if (result.confidence < 0.6 && retryCount < MAX_RETRIES) {
retryCount++;
showMessage(`信心度低。重試中(${retryCount}/${MAX_RETRIES})...`);
camera.reset();
camera.startScan();
} else {
retryCount = 0;
displayFinalResult(result);
}
};4. 使用者指導
typescript
const guidanceMessages = {
lowConfidence: "改善光線或保持靜止",
noFace: "將您的臉部置於中央",
unstable: "保持您的臉部穩定",
success: "測量完成 ✓"
};
camera.onVideoFrameProcessed = (event) => {
const estimation = event.realtimeEstimation;
if (!estimation) return;
if (estimation.confidence < 0.4) {
showGuidance(guidanceMessages.lowConfidence);
} else if (estimation.isStable) {
showGuidance(guidanceMessages.success);
}
};與 ME-rPPG 估算器比較
| 特點 | Panoptic | ME-rPPG |
|---|---|---|
| 準確度 | ⭐⭐⭐⭐⭐ 醫療級 | ⭐⭐⭐⭐⭐ 最先進 |
| 動作容忍度 | ⭐⭐⭐⭐ 良好 | ⭐⭐⭐⭐⭐ 優秀 |
| 光線容忍度 | ⭐⭐⭐⭐ 良好 | ⭐⭐⭐⭐⭐ 優秀 |
| 初始化 | ⭐⭐⭐⭐⭐ 即時 | ⭐⭐⭐ (1-2秒) |
| 套件大小 | ⭐⭐⭐⭐⭐ 約100 KB | ⭐⭐⭐ 約10 MB |
| 記憶體使用 | ⭐⭐⭐⭐⭐ < 200 KB | ⭐⭐⭐ 約4 MB |
| 授權 | 專有 | 開源 |
| 首次結果 | ~8 秒 | ~3 秒 |
| 最適合 | 醫療應用,嵌入式 | 消費者應用,挑戰性條件 |
範例:完整實作
typescript
import { createVitalSignCamera, RealtimeEstimatorType } from 'ts-vital-sign-camera';
// 使用 Panoptic 估算器建立相機
const camera = createVitalSignCamera({
realtimeEstimationConfig: {
estimatorType: RealtimeEstimatorType.Panoptic,
debug: false
}
});
// Panoptic 立即就緒(無非同步載入)
document.getElementById('start-btn').disabled = false;
// 處理即時更新
camera.onVideoFrameProcessed = (event) => {
const estimation = event.realtimeEstimation;
if (!estimation) return;
updateHeartRateDisplay(estimation.heartRate);
updateConfidenceBar(estimation.confidence);
// 如果可用則顯示 SNR
if (estimation.snr) {
updateSNRDisplay(estimation.snr);
}
// 品質指示器
if (estimation.isStable && estimation.confidence > 0.7) {
showQualityIndicator('優秀');
} else if (estimation.confidence > 0.5) {
showQualityIndicator('良好');
} else {
showQualityIndicator('差');
showTip('改善光線或減少移動');
}
};
// 檢查最終結果
let scanCompleted = false;
camera.onVideoFrameProcessed = (event) => {
const results = event.healthResult;
if (results && !scanCompleted) {
scanCompleted = true;
if (results.confidence > 0.7) {
displayFinalResults(results);
} else {
showRetryOption();
}
}
};
// 開始掃描
document.getElementById('start-btn').onclick = () => {
camera.startScan();
};範例:醫療應用程式
typescript
// 醫療級配置
const camera = createVitalSignCamera({
realtimeEstimationConfig: {
estimatorType: RealtimeEstimatorType.Panoptic,
signalQualityDelay: 10, // 延長品質計算等待時間
debug: false
}
});
// 僅記錄高信心度測量
camera.onVideoFrameProcessed = (event) => {
const estimation = event.realtimeEstimation;
if (!estimation) return;
if (estimation.isStable && estimation.confidence > 0.7) {
recordMeasurement({
heartRate: estimation.heartRate,
confidence: estimation.confidence,
snr: estimation.snr,
timestamp: new Date()
});
}
};
// 儲存前驗證
let validationCompleted = false;
camera.onVideoFrameProcessed = (event) => {
const results = event.healthResult;
if (results && !validationCompleted) {
validationCompleted = true;
if (results.confidence > 0.7 && results.snr > 5) {
saveMedicalRecord(results);
} else {
requestRetry('測量品質低於醫療閾值');
}
}
};下一步
- ME-rPPG 估算器 - 與 AI 方法比較
- 選擇指南 - 選擇正確的估算器
- 訊號視覺化器 - 視覺化 PPG 訊號
- API 參考 - 完整 API 文件