指の覆いが安定すると、すぐ BPM を計算したくなります。私も最初はそうしました。数字は出ます。ただし、数字が出ることと測る価値があることは別です。

採用された各フレームは、赤の強度値とタイムスタンプを 1 つずつ提供します。この段階の処理は、その列を正直な信号に近づけるためのものです。
This diagram could not be rendered. Its source is still available below.
View diagram source
flowchart LR
A[採用されたカメラフレーム] --> B[赤強度サンプル]
B --> C[タイムスタンプ付きバッファ]
C --> D[ベースラインドリフトを除去]
D --> E[高周波ノイズを軽く平滑化]
E --> F[正規化波形]
F --> G[ピーク検出]
生の赤値だけでは足りない
指先は実験器具で固定されていません。ユーザーは少し強く押し、またゆるめます。フラッシュで皮膚が温まり、露出が落ち着き、手が少し動きます。これらは赤値にゆっくりした変化を作ります。
30 fps を信じすぎない
30 fps と仮定してインデックスを時間に変換するのは簡単です。しかし実機ではフレーム落ちがあり、遅れたフレームは捨てられることもあります。MonoPump は各サンプルの presentation timestamp を保存します。
This diagram could not be rendered. Its source is still available below.
View diagram source
sequenceDiagram
participant C as Camera
participant B as Buffer
participant P as Preprocessor
C->>B: t0 の値
C->>B: t1 の値
C->>B: t2 の値
B->>P: 値 + タイムスタンプ
P->>P: 実サンプルレートを推定
BPM は時間の測定です。配列インデックスの測定ではありません。
トレンド除去と軽い平滑化
脈は比較的速い揺れです。指圧や露出ドリフトはもっと遅い変化です。MonoPump は局所移動平均を基線として引き、軽い移動平均でノイズを抑えます。
detrended[i] = signal[i] - average(signal around i)
This diagram could not be rendered. Its source is still available below.
View diagram source
flowchart TD
R[生の赤系列] --> D[局所基線を引く]
D --> S[3 点移動平均]
S --> N[正規化]
N --> W[UI に表示する波形]
N --> P[ピーク検出入力]
見た目のきれいな波形を信用しすぎない。目的は美しいアニメーションではなく、タイミングを守ることです。