ステータス:ドラフト(2026-10-16)、一部実測値。 ボールモデル(BlurBall)の入力サイズ別遅延時間は、自宅ラップトップ用の 8GB クラス GPU 1枚で使い捨てポッドを用いて測定しました(20回のウォームアップ後、50回×5セットの中央値)。スキップおよび ROI はノートPC CPU での合成軌跡のシミュレーションによるものです(
code/05_skip_frames.py、1秒前後)。実際の卓球動画におけるスキップの精度は未実測です。 シリーズ「ビジョンモデルを読む 3」の第5篇。オプティカルフローの原理は ビジョンモデルを読む 2 の第5篇, ボール追跡モデルの学習については同シリーズの 第9篇にあります。
目次
- 1. 直感:隣接フレームはほぼ同じ
- 2. 検出はたまに、間は追跡で
- 3. キーフレーム:特徴量を使い回す
- 4. 解像度:入力を小さくすると
- 5. ROI:予測位置の周辺のみ
- 6. 制限事項
- 7. 我々のプロジェクトとのつながり
- 参考文献
1. 直感:隣接フレームはほぼ同じ
30fps の動画では、隣接する2つのフレームの時間差は 33ms です。その間、背景はそのままであり、人物は数ピクセル動くだけです。しかし、フレームごとに重いモデルを最初から実行すると、ほぼ同じ計算を30回繰り返すことになります。本記事で紹介する手法は、すべてこの冗長性を削減するものです。
| 何を削減するか | 手法 | 代表例 |
|---|---|---|
| 削減対象(時間・フレーム数) | 検出はたまに、間は追跡 | SORT, MediaPipe, BlazePose |
| 時間(特徴量) | キーフレームでのみ特徴量を抽出し使い回す | Deep Feature Flow |
| 空間(解像度) | シーンごとに入力サイズを選択する | AdaScale |
| 空間(領域) | 予測された位置の周辺のみを見る | ROI 切り抜き |
2. 検出はたまに、間は追跡で
Bewley らによる SORT(2016)は、毎フレームの検出結果を受け取り、物体ごとに 等速カルマンフィルターで次の位置を予測し、予測されたバウンディングボックスと新しい検出ボックスを IoU でマッチングさせます(ハンガリアンアルゴリズム)。追跡部分は 2016年頃の CPU コア単体で 260Hz で動作していました(セクション 4.3、検出時間は含まれていないと解釈されます)。同じトラッカーに対して検出器を変更するだけでも MOT 精度(MOTA)が 15.1 から 34.0 に向上しました(表1)。つまり、追跡の品質は最終的に検出精度によって決まり、トラッカー自体はほぼコストがかからないということです。
この「ほぼ無料の」特性を利用すれば、検出を 必要なときだけ 行うことができます。MediaPipe の姿勢推定は、検出器を最初のフレームとトラッカーが人物をロストしたときのみ実行し、残りのフレームでは前フレームの関節位置を元に人物の周辺を切り抜いて関節モデルのみを実行します(公式ドキュメント)。BlazePose(2020)はこのアプローチにより、2017年のモバイル用 CPU コア単体で Lite モデルを使用し約 30 FPS を達成しました(表1)。
カルマンフィルターの予測ステップは1行です。
상태 x = [위치, 속도], 다음 예측 x' = F·x, F = [[1, Δt], [0, 1]] (등속 가정)
검출이 오면 예측과 검출을 불확실성 비율로 섞어 고친다(갱신 단계)
実際に試す:卓球ボールでフレームをスキップすると
等速の仮定は、ボールが 方向を変える瞬間 に破綻します。卓球ボールは 0.5秒に1回程度の頻度で卓球台にバウンドするか、ラケットに当たります。512×288 の画面上に重力・バウンド・打球が存在する合成ラリー(60fps、1,161フレーム、バウンド 29・打球 40)を作成し、検出器を k フレームに1回実行し(位置ノイズ σ=1px)、その間を直近2回の検出結果に基づく等速予測で補間しました。
| k(検出間隔) | 検出コスト | 位置誤差 中央値・p95 | バウンド・打球前後の3フレームの中央値・p95 | 10px 以上外れたフレーム |
|---|---|---|---|---|
| 1 | 100% | 1.2 · 2.5px | 1.1 · 2.3px | 0.0% |
| 2 | 50% | 1.5 · 5.4px | 1.7 · 20.1px | 3.8% |
| 3 | 33% | 1.9 · 29.3px | 2.2 · 46.8px | 9.6% |
| 4 | 25% | 2.4 · 48.7px | 3.3 · 75.7px | 15.7% |
| 6 | 17% | 5.8 · 92.5px | 7.2 · 83.6px | 34.0% |
中央値だけを見れば、3フレームごとに検出しても 2px 前後であり問題なく見えます。しかし、裾野(p95)はバウンドや打球の前後で 46.8px に達し、ボールの直径(512幅で約 5px)の9倍を超えています。 誤差がよりによって我々が知りたいイベント(バウンド)の周辺に集中してしまうのです。 人間の姿勢のように滑らかに動く対象ではうまく機能する「検出をたまにする」という手法を、判定がバウンドに依存する卓球ボールにそのまま適用することが難しい理由がここにあります。
3. キーフレーム:特徴量を使い回す
Zhu らによる Deep Feature Flow(2017)では、スキップの単位を「検出結果」ではなく「ディープな特徴量」に設定します。重い特徴量抽出ネットワーク(ResNet-101)はキーフレームでのみ実行し、中間フレームでは軽量なオプティカルフローネットワークによって求められたフローに沿ってキーフレームの特徴量をワープさせた後、軽量なヘッド部分のみを実行します。最後まで一緒に学習させます。
| タスク(論文の表 4) | キーフレーム間隔 | 毎フレーム | Deep Feature Flow |
|---|---|---|---|
| ImageNet VID 動画検出 | 10 | mAP 73.9, 4.05 fps | mAP 73.1, 20.25 fps(5.0倍) |
| Cityscapes セグメンテーション | 5 | mIoU 71.1, 1.52 fps | mIoU 69.2, 5.60 fps(3.7倍) |
(2013年当時のデータセンター向け GPU 1枚。)精度を 1〜2ポイント犠牲にすることで、3.7〜5倍高速化しました。さらに軽量なオプティカルフローネットワークを使用すると約10倍(41.26 fps)に達しましたが、mAP は 69.5 に低下しました(セクション 5.2)。オプティカルフローは「1フレームの間に少しずつ動く」ことを前提としているため、1フレームの間に直径の数倍分も飛んでいくボールには適合しません(以下のセクション 4 の表を参照)。
4. 解像度:入力を小さくすると
計算量はピクセル数、すなわち幅×高さに比例します。幅を半分にすれば計算量は4分の1になります。その代わり、小さな物体はさらに小さくなります。卓球台の長さ 2.74m が画面幅の 70% を占めると仮定し、ボール(40mm)の大きさおよび1フレームあたりの移動量を計算しました(ボールの速度 10m/s)。
| 画面幅 | ボール直径 | 1フレームあたりの移動量(60fps / 30fps) | ピクセル数(512×288 と比較) |
|---|---|---|---|
| 1920 | 19.6px | 81.8 / 163.5px | 14.1倍 |
| 1280 | 13.1px | 54.5 / 109.0px | 6.3倍 |
| 768 | 7.8px | 32.7 / 65.4px | 2.3倍 |
| 512 | 5.2px | 21.8 / 43.6px | 1 |
| 256 | 2.6px | 10.9 / 21.8px | 0.25倍 |
どの解像度であっても、ボールは1フレームの間に 自身の直径の 4.2倍(60fps)〜8.3倍(30fps) 移動します。そのため、ボールモデルは単一のフレームではなく複数のフレームをまとめて確認し、軌跡のブレさえも手がかりとして利用します(同シリーズ2の第9篇)。
独自実測:ボールモデルを4つの入力サイズで
TT Score のボールモデル(BlurBall、3フレームウィンドウ、パラメータ数 149万)を実験用 GPU で入力サイズのみを変更して測定しました。このモデルは完全畳み込み(fully convolutional)であるため、重みをそのままにして入力サイズを変更可能です(学習は 512×288 で行われているため、他のサイズの 精度は未実測です)。
| 入力 | FP32 | FP16 | 512×288 に対するピクセル比 | 512×288 に対する時間比(FP32) |
|---|---|---|---|---|
| 256×144 | 4.07ms | 4.69ms | 0.25倍 | 0.27倍 |
| 512×288 | 15.09ms | 9.77ms | 1 | 1 |
| 768×432 | 41.90ms | 24.10ms | 2.25倍 | 2.78倍 |
| 1024×576 | 82.24ms | 49.30ms | 4倍 | 5.45倍 |
(バッチ 1、1ウィンドウ、FP16 は autocast。20回のウォームアップ後の 250回の中央値であり、5セットの中央値同士は 0.1ms 以内で一致しました。)
ここから2つのことがわかります。
- 大きいサイズでは、ピクセル数よりも速く処理が遅くなりました。 1024×576 はピクセル数が4倍であるのに対し、時間は 5.45倍です。このモデルは解像度を最後まで維持したまま数十チャンネルの特徴マップを持ち歩くため、入力が大きくなると中間テンソルが GPU キャッシュに収まらなくなったためと考えられます(原因は推測であり、プロファイリングによる実測は未実施)。
- 小さいサイズでは、FP16 の方がかえって遅くなりました(4.07ms 対 4.69ms)。計算量が少なすぎて、GPU が処理を待つ時間(カーネルの呼び出し、フォーマット変換など)が大部分を占めるようになると、精度を下げても意味がありません。これについては第3篇と第6篇で改めて確認します。
30fps の予算(33ms)に推論のみを割り当てる場合、768×432 の FP16(24ms)まで収まります。しかし、第1篇で見たように予算には前処理・転送・後処理・他のセッション分のコストを含める必要があるため、512×288(FP16 9.8ms)に余裕を持たせるのが適切なサイズとなります。この値は、ボールモデルが学習されたサイズでもあります。
シーンごとにサイズを選択:AdaScale
Chin らによる AdaScale(2019)は、検出器の特徴量の上に小さな回帰器を配置し、 次のフレームで使用する入力サイズ(短い辺が 600・480・360・240)を予測します。大きな物体のみが存在するシーンでは入力サイズを小さくしても問題なく、むしろ誤検出が減って精度が向上することさえあります。ImageNet VID では 1.6倍の高速化と同時に mAP が 74.2 から 75.5 に向上しました(R-FCN、2017年当時のコンシューマー向け上位 GPU、75 から 47ms)。回帰器自体の処理は約 2ms です。卓球ではボールが常に小さいためこのアイデアをそのまま適用するのは難しいですが、「今回のシーンはボールが映っていない休憩時間だから小さく・低頻度で処理する」といった形での応用は可能です(未実測)。
5. ROI:予測した位置の周辺のみ
追跡によって次の位置が予測されていれば、その周辺の小さなウィンドウのみをモデルに入力することができます。画面全体ではなく 96×96 のウィンドウであれば、ピクセル数はわずか 6% です。その代わり、予測が外れてウィンドウの外にボールが出てしまうとロストしてしまい、その場合は画面全体をもう一度見直す必要があります。セクション 2 の合成ラリーにおいて、毎フレーム検出しつつ(σ=1px)、直近2回の予測位置からウィンドウの位置を予測しました。
| ウィンドウ | ピクセル比 | ボールがウィンドウ外(検出失敗 0%) | ボールがウィンドウ外(検出失敗 10%) | そのうちバウンド・打球前後(失敗 10%) |
|---|---|---|---|---|
| 32×32 | 0.7% | 3.71% | 4.66% | 11.95% |
| 64×64 | 2.8% | 2.50% | 2.85% | 7.36% |
| 96×96 | 6.2% | 0.35% | 0.78% | 1.84% |
| 128×128 | 11.1% | 0.35% | 0.60% | 1.61% |
ウィンドウの外に出てしまう瞬間は、やはり方向が変わる瞬間に集中します。このシミュレーションにはオクルージョン、サーブの開始(ボールが手元から突然現れる)、カメラのブレが含まれていないため、実際にはさらに頻繁に外れることが予想されます(未実測)。また、BlurBall のように複数フレームをまとめて確認するモデルでは、ウィンドウを切り抜くと前後のフレームの同じ位置も切り抜かなければならないため、ウィンドウがボールに追従して動いてしまうと「同一位置の変化」という手がかりが曖昧になってしまいます。
6. 制限事項
- セクション 2 および 5 は合成軌跡に基づくものです。実際の動画におけるオクルージョン、ブレ、ボールが画面外に出入りするケースなどは含まれていません。
- 第4節の入力サイズ別の測定では時間のみを計測しました。学習時とは異なるサイズでボールモデルがどれほど正確であるかは測定していません。
- 論文の数値はそれぞれのGPUやデータから得られた値であるため、倍率同士を比較することはできません。
7. 我々のプロジェクトとの関連
- TT Scoreはボールモデルを毎フレーム実行します。 第2節の表のようにスキップすると、バウンドの周辺で誤判定が生じるためです。その代わり、コストの低い方は「時々」実行するようにしました。卓球台の検出は試合開始時に1回(EfficientTAM、第4編)、その後は毎フレームオプティカルフローで追跡し、大きく揺れた時だけ再検出します。オプティカルフローとカット判定を毎フレーム行っても、1フレームあたり約1.7msでした(TT Score性能ドキュメントの実測、静かなノード)。
- 入力は512×288です。 スマートフォンがカメラ画面をこのサイズに縮小して送信します。第4節の表のように、これより大きければすぐに予算を超過し、小さければボールが3px未満になってしまいます。縦持ちしたスマートフォンをこのサイズに合わせると、画面の幅が162pxに縮小され、ボールがほとんど見えなくなってしまいました(性能ドキュメントの条件別テストにおけるボールの視認率5%)。撮影ガイドが横持ちを推奨する理由はここにあります。
- ROIはまだ使用していません。ボールを見失った後に再検出するコストと、ウインドウを切り取ると複数フレームの手がかりがぼやけてしまう問題を先に測定する必要があります(未測定)。
次の記事では、複数人が1つのGPUを共同利用する場合、バッチ処理がレイテンシとスループットにどのような影響を与えるかについて解説します。
TTの一言。 ボールは1フレームの間に自身のサイズの4倍も移動し、まさにバウンドする瞬間に方向を変えます。だから、私は一度もまばたきをしません — その代わり、卓球台を見るのは時々だけです!
参考文献
- Bewley, A. et al. (2016). Simple Online and Realtime Tracking. ICIP 2016. https://arxiv.org/abs/1602.00763
- Bazarevsky, V. et al. (2020). BlazePose: On-device Real-time Body Pose tracking. CVPR Workshop. https://arxiv.org/abs/2006.10204
- MediaPipe Pose ドキュメント(レガシーソリューション)。 https://github.com/google-ai-edge/mediapipe/blob/master/docs/solutions/pose.md
- Zhu, X. et al. (2017). Deep Feature Flow for Video Recognition. CVPR 2017. https://arxiv.org/abs/1611.07715
- Chin, T.-W., Ding, R., Marculescu, D. (2019). AdaScale: Towards Real-time Video Object Detection Using Adaptive Scaling. SysML 2019. https://arxiv.org/abs/1902.02910
- 我々の測定:このシリーズの実測(元データはリポジトリ外の研究記録)、TT Score性能ドキュメント 2.12・2.14節
- サンプルコードと出力:このフォルダの
code/05_skip_frames.py,code/05_skip_frames.out.txt