TT Lab
ブログ

한국어 English 日本語 中文

はじめる
ブログ

ブログ

イベントと審判: 軌跡からバウンドを抽出しルールでスコア付けする、66.9%から93.1%まで

状態: ドラフト(2026-10-13)、実測値を反映。 正解率はすべてOpenTTGamesの実際の試合12編(サーバーが分かるラリー275個)で直接測定した値であり、バージョンごとに日付と条件を付記しています。学習型イベント検出とラリー終了判定の再設計実験は進行中のため結果を記載していません。TT4D・PathCRFの数値は論文の値です。 作成ルール: 実測データが基本であり、測定できなかったものは「未実測」と表示します。

目次

1. 軌跡からイベントへ

第1レイヤーが提供するのはフレームごとの (시각, x, y, 신뢰도) がひとつです。スコアをつけるにはこれをイベントの列に変換しなければなりません。エンジンが出力するイベントは4つです。

イベント 定義(側面カメラ)
bounce(バウンド) テーブル上面の帯の中でボールの画面yが増加し(下降)、減少し始める(上昇)フレーム。ただし、水平方向を維持する場合のみ
net(ネット) ボールがネット付近をテーブルの高さより上で通過し、水平速度が0.7倍以下に減少するか反転する
out(アウト) バウンドの後にボールがテーブルのエンドの外側に出て、テーブルの高さより下に落ちる
end(終了) ボールが1秒間見えないか、最後のバウンドから1.5秒間新しいバウンドがない

直感: バウンドはV、打球もV

画面のyは下方向に大きくなります。ボールがテーブルに落ちて跳ね上がると、yは大きくなってから小さくなります。この「V」がバウンドの基本形状です。問題は テーブルの上でラケットで打つボールもVを描くということです。そこでもうひとつ確認します。テーブルに弾んだボールは同じ方向に飛び続けますが、ラケットに当たったボールは引き返します。実際の試合12編において、本物のバウンドの97.9%は水平方向を維持し、打球の前後3フレーム以内の偽のバウンドは73.8%が水平方向が反転していました。

# ttscore/events.py detect_events() 에서 줄임
going_down = before.x is not None and c.y > before.y      # 같은 y 가 이어지면 그 앞의 다른 y 와 비교
going_up = n.y < c.y
if (going_down and going_up and table.on_surface(c.x, c.y)
        and c.t - last_bounce_t >= MIN_BOUNCE_GAP_S         # 0.12초 — 같은 바운드를 두 번 세지 않게
        and keeps_direction(i)                              # 앞뒤 가로 이동이 둘 다 2px 이상이고 반대면 타구
        and not near_net_touch(i)):                         # 네트에 걸린 공의 V 는 버린다
    emit(Event(c.t, "bounce", table.ball_side(c.x, c.y), conf=min(p.conf, c.conf, n.conf),
               vx=vx_at(i), vx_in=vx_at(i, after=False)))

「同じyが続けばその前の別のyと比較」という1行にも理由があります。ヒートマップ座標は整数ピクセルであるため、動きの遅い区間では同じ値が続き、「等しい」を「下降」としてカウントすると、上昇するボールでバウンドが発生してしまいました。

定数にはそれぞれ根拠がある

ルールエンジンの弱点は、数値を感覚で決めやすいことです。そのため、定数ごとに実測の根拠をコードのコメントに記載しました。

定数 値 根拠(実際の試合12編、2026-10-11)
END_AFTER_BOUNCE_S 1.5秒 ラリー内のバウンド間隔の98%(1,087個中1,066個)が1.5秒以内
REVERSAL_MIN_PX 2px 本物のバウンドの97.9%が方向維持、打球付近の偽物の73.8%が方向反転
NET_SLOW_RATIO 0.7 ネットにかかったボール(Extendedのnet終了83個)の前後水平速度比は−0.44…−0.03、ネットの上をそのまま通過したボール(OpenTTGamesのnet 1,268個)は0.75…1.01
GAP_ZERO_S 0.25秒 埋められなかった空白がこれだけあれば信頼度0。埋める限界(6フレーム)を超えると「見落としたバウンドはない」と信じることはできない

最後の行と対をなすのが fill_gaps です。ボールが身体に遮られて6フレーム(60fpsで0.1秒)以下の間見えない場合、直線で補間し、補間された点の信頼度を両端の半分に引き下げます。その区間で発生したバウンドを自動的に「要確認」へ誘導するためです。

2. シンパン: 「ダレが打ったか」は見ない

서브 대기 서브처럼 보이는 공만 받음 서버 쪽 바운드 + 네트 쪽 속도 ≥ 0.7 서브 진행 네트 닿음 = 렛 후보 리시버 쪽 바운드 1초 안 서버 쪽에 또 · 바운드 없이 끝 랠리 기대하는 쪽: S S 에 바운드 → 다음은 반대쪽 서브 실패 리시버 득점 S 쪽 선수가 진다 같은 쪽에 또 바운드 → 투 바운드 테이블 밖으로 떨어짐 → 아웃 아무 일 없이 끝남 → 못 받음 「누가 쳤나」는 보지 않는다. 바운드가 떨어진 쪽의 선수가 받아 넘겨야 할 차례다. 0.25초 안의 같은 쪽 두 바운드는 다음 이벤트까지 판정을 미룬다(가짜일 수 있다).
図: 審判の状態遷移

審判エンジン(ttscore/referee.py)の核心となる考え方は、序文のひとつの文章にあります。 誰が打ったかは映像から直接見ず、バウンドの順序から推論します。 ボールがS側にバウンドした場合、次はS側の選手が打って反対側に1回落とさなければなりません。そうできなければ(同じ側に再びバウンド、バウンドせずに外に出る、何事もなく終了する)、S側の選手が失点します。サーブのみ例外で、サーバー側に1回、そしてレシーバー側に1回落ちなければなりません。

このようにすると、「ラケットの接触」という、映像から見つけるのが最も困難なイベントなしでスコアをつけることができます。その代わり、バウンドをひとつ見落としたり偽のバウンドがひとつ混ざったりすると、「どちらが打つ番か」が丸ごと狂ってしまいます。そのため、審判の残りのルールのほとんどは 偽のバウンドを排除する装置です。

水平速度というひとつの数値

バウンドイベントには、バウンド直後の水平速度 vx(テーブルの長さ/秒)が含まれています。画面のピクセルではなくテーブルの長さで割った値であるため、カメラの距離や解像度に関係ありません。審判はこの数値で3つのものを区別します。

  1. サーブの開始。 スコアボードのサーバー側のバウンドであり、かつボールがネット側へ0.7テーブル/秒以上移動していなければサーブとして受け付けません。実際のサーブ271個の最初のバウンドはすべて1.07以上であり、ラリー外のサーバー側のボール(サーブ前の自分の側でのバウンド、相手に渡すボール)は、サーブのように見えた4個を除いて0.61以下でした。
  2. ラリー中の偽のバウンド。 ラリー中のS側の本物のバウンドは相手が打ったボールであるため、S側のエンドに向かって、すなわちネットから離れながら進みます。ネット側へ向かう「バウンド」は、ネットの上を通過するボールや打球を誤読したものであるため破棄します。このルールひとつで実際のラリーの勝者が235から241に増加しました。
  3. ボールを返す行為。 レシーバーがサーバーにボールを投げ返すと、レシーバー側からネット側へ弾んでサーバー側に落ちます。「サーブのように」見えますが、スコアボードのサーバーの反対側から始まるため受け付けません。両方を受け付ける変形は、実際の5試合の誤判定を3から16に増加させました。

速いツーバウンドは後回しにする

同じ側の2つのバウンドの間隔が0.25秒よりも短い場合、本物のツーバウンドなのか、バウンド直後の打球をバウンドとして読み取ったものなのかを区別できません。実測において、このような判定39件のうち16件(41%)が誤っていました。残りの判定の誤答率は8%でした。そのため、この判定は 次のイベントまで保留します。 次のバウンドが反対側であれば(リターンが落ちる)、2番目のバウンドは偽物だったので破棄してラリーを続行します。このルールにより判定が変更された実際のラリー9件は、すべて「不正解」から「正解」になりました。代償は時間です。その判定は最大1.5秒遅れて出力されます。

信頼度と「要確認」

ラリーの信頼度は、そのラリーのイベントたちの信頼度の中での 最小値です。イベントの信頼度は、検出の信頼度と、直前の空白の信頼度のうち小さい方です。0.6を下回るとスコアボードに「要確認」が表示されます。判定はそのまま反映しつつ、人間に一度確認を促すというものです。

ここで2つの数値を区別しなければなりません。

信頼度を保守的に引き下げれば確認なしの誤りは減るものの要確認が増え、逆にすればその逆になります。以下の歴史は、これら2つの数値の間の綱引きでもあります。

3. 66.9%から93.1%まで: バージョンごとに変更したことと代償にしたこと

条件(すべての行で同一): OpenTTGames実際の試合12編、Extended OpenTTGamesラリー終了ラベル、サーバーが分かるラリー275個、BlurBall座標、録画データの採点。日付はいずれも2026-10-11–12です。

バージョン 変更点 勝者 要確認 確認なしの誤り 判定なし バウンドの精度 / 再現率
初期 ボール座標 → 空白の補間 → イベント → 審判 66.9% (184) 76.4% 2.9% 10.2% 0.789 / 0.971
2 打球≠バウンド(水平方向を維持する場合のみバウンド)、最後のバウンドから1.5秒で終了 79.6% (219) 85.1% 1.8% 1.5% 0.831 / 0.958
3 遠方の境界を許容 「8px + ボール半径」(データセットのマスクの端) 82.5% (227) 85.5% 1.5% 0.7% 0.825 / 0.965
4 SAM 2.1の端(3編) 84.7% (233) 85.8% 1.5% 0.0% 0.823 / 0.965
5 サーブ認定ルール、ラリー中のネット側の「バウンド」を破棄、要確認の再設計 88.7% (244) 41.5% 5.1% 0.4% 0.823 / 0.965
6 ネット判定(サーブレット)、速いツーバウンドの保留 93.1% (256) 41.1% 3.6% — 0.832 / 0.963

バージョンごとに支払った代償を記載すると以下のようになります。

そして2026-10-13のベースライン

バージョン6の93.1%はSAMの境界で測定されましたが、その境界ファイルが残っていません。研究を新しく開始するにあたり、ベースラインをデータセットのマスクの端と最新のエンジンで再設定し、今回は 実際にデプロイされたリアルタイムのパス(直近2.5秒をサンプルごとに再処理する方式)でも計測しました。

パス 勝者 確認なしで不正解 確認が必要 判定なし バウンドの適合率 / 再現率
録画の採点 91.3% (251) 13 108 3 0.835 / 0.965
配信リアルタイムパス 90.2% (248) 15 129 2 0.800 / 0.970

同じエンジン、同じボール座標であっても、パスを変えるだけで3つのラリーが異なりました。録画はラリーをすべて見てから判断し、リアルタイムは直近の2.5秒間だけを見てその都度判断するためです。 録画による採点は、リアルタイムのパフォーマンスを誇張してしまいます。 そのため、今後のすべての実験では両方のパスを併記します。

4. 誤差はどのレイヤーで発生するのか:正解を入力してみる

レイヤーを分けたおかげで、同じ採点を3種類の入力で実行できます。モデルが検出したボール、データセットの正解ボール座標、データセットの正解バウンドです。正解のボールを入力しても外れる場合、その誤差はボール検出のせいではありません。正解のバウンドを入力しても外れる場合、イベント抽出のせいでもありません。

エンジン版 モデルのボール 正解のボール 正解のバウンド 範囲
2版(79.6%版) 79.6% 85.8% 90.2% モデルのボールは275ラリー、正解の入力は正解が存在するラリー
5版(88.7%版) 88.7% 90.2% 93.5% モデルのボールは275ラリー、正解の入力は正解が存在する246ラリー
2026-10-13のベースライン 93.5% 89.0% 90.2% 3つすべて同じ246ラリー

第2版と第5版では、正解を入力するほどスコアが上昇しました。このことから、「残りの誤差の大部分はボール検出ではなく イベント抽出で発生している」と読み解くことができ、実際、第5版の偽バウンド25件のうち11件は打球をバウンドと誤読したもので、5件はネット際でサイドが反転したもの、4件はバウンドを見逃したものでした。

しかし、最新のエンジンでは モデルのボールが正解のボールや正解のバウンドよりも高くなっています。 これらの数値を「上限」として読み解いてはならない理由がここにあります。

つまり、正解の入力は「完璧な入力」ではなく「別の入力」なのです。エンジンがモデルのボールの特性(イベントの外部まで続く座標、水平方向の速度)に合わせて調整されている分、正解の入力との比較はレイヤー別の誤差を切り分けるためのツールとしてのみ使用し、上限としては使用しません。

現在残っている誤差

2026-10-13のベースライン(録画、275ラリー)において、不正解だった、または判定がなかった27件のタイプです。

タイプ 件数
偽バウンド 7
バウンドの見逃し 4
終了判定におけるサイドのずれ 4
終了(end)が来ない 3
打球をバウンドと誤読 2
サイドの反転・早期判定・ネット際のサイド反転・アウトの誤判定 各1

イベント(バウンド)側が27件中14件、ラリーの終了側が8件です。得点の原因別に見ると、アウトが92.8%(138件中128件)、ネットが92.6%(81件中75件)、ウィナーが84.4%(32件中27件)、ツーバウンドが75.0%(4件中3件)でした。

悪条件下での性能

7試合(57ラリー)に劣化を加えて計測しました(録画採点、勝者一致数)。

条件 一致 / 57 確認なしで不正解
クリーン 50 3
暗い 35 2
30fps(エンジンも30fps) 41 9
低解像度 320×180 42 2
長時間の露出 46 2
スマホ 360p 60fps 500kbps圧縮 50 1

30fpsではボール検出の精度がほとんど低下しないにもかかわらず(パート2)、スコアが大きく低下し、確認なしの不正解が最も多くなりました。バウンド瞬間の時間解像度が半分になるためです。 このエンジンは、不正解を隠す方向に崩壊します。 そのため、撮影ガイドでは60fpsを推奨しています。

5. 今後の展望:3D極値ルールと制約付きViterbi

TT4D式3D極値ルール

現在のルールは、2D画面上で「V字」を探します。画面のy軸にはボールの高さとカメラからの距離が混ざっているため、視点が変わるとルールが不安定になります(パート3の末尾のカメラの問題)。

TT4D(arXiv 2605.01234, ACM MM 2026)は、単一カメラの中継映像からボールの軌跡を 3D空間に復元した上で イベントを検出します。ルールは驚くほどシンプルです。

3Dの正解データ(合成およびTT3D)において、±2フレーム基準でバウンドのF1が0.92、打球のF1が0.83と報告されています(論文、適合率・再現率は別途記載なし)。打球の数値が低い理由として、著者らは選手の近くでボールが見えにくくなることを挙げています。

我々のエンジンの2Dルールと比較すると、同じ考え方の3D版と言えます。「V字」は z の極小値であり、「水平方向が反転すれば打球」は x の極値です。3Dに拡張すれば視点に関わらず同じルールになり、高さを把握することで空中のボールを平面に誤って投影してしまう問題も解消されます。その代わり、単一カメラから3Dを復元するステップが新た必要になります。この復元を、我々のサイドカメラのスマホ映像で行えるかどうかが次の実験の疑問点です(進行中、未計測)。同系統のオープンソース実装の一部はGPLライセンスであるためコードは流用せず、手法のみを実装する予定です。

制約付きViterbi:ルールを「許可された遷移」として定義する

現在のエンジンはイベントを1つずつ受け取り、その都度判定を下しています。1つの偽バウンドが入力されると、「次はどちらが打つ番か」が逆転し、それ以降の判断がすべて狂ってしまいます。人間はこのような場合、後を振り返って前を修正します。「このバウンドが本物だとすれば、その後の順序がルール上あり得ない。したがって、このバウンドは偽物だったはずだ。」

この考え方を計算に落とし込んだものが 制約付きViterbiデコーディングです。

  1. 時点ごとに、「サーバー側のバウンド」、「レシーバー側のバウンド」、「打球」、「何もなし」といった 状態候補にスコアを割り当てます。スコアはボール、音声、姿勢などのシグナルから得られます。
  2. 卓球のルールを 許可された遷移として記述します。サーブ → サーバー側のバウンド → レシーバー側のバウンド → 打球 → サーバー側のバウンド … は許可、同じ側のバウンドが2回続いた後のラリー継続は禁止(得点が発生するはず)といった具合です。禁止された遷移のスコアは非常に低く(実質的に −∞)設定します。
  3. Viterbiアルゴリズムを使用して、 スコアの合計が最も大きい、ルール上可能な1つのパスを探索します。動的計画法であるため、ラリーの長さに比例する時間で処理が完了します。
  4. 最適なパスと2番目のパスのスコア差が小さい場合、そのラリーは「確認が必要」となります。これは現在の「信頼度の最小値」よりも根拠が明確な信頼度となります。

サッカーにおいて同様の考え方を示したPathCRF(arXiv 2602.12080, KDD 2026)は、 モデルはそのままにしてデコーディングのみを変更し、 イベントのF1スコアを65.34%から73.14%に向上させ、ルール違反を2.80%から0%に削減しました(論文)。卓球はサッカーよりもルールがはるかに厳格であるため、さらに大きな効果が期待できると推測されます。PathCRFのコードはMPL-2.0であるため流用せず、その手法を我々のエンジンに合わせて独自に実装する予定です。

進行中の実験

次の実験はまだ結果が出ていないため記載しません(進行中)。

実験の原則はすでに定めています。ハイパーパラメータは学習に使用していない検証用試合でのみ選定し、テスト用の7試合は最後に1回だけ参照します。また、ルールエンジンはテスト用の試合を確認しながら調整されたものであるため、 ルールベースラインのテストスコアは楽観的なものになっているという点を、新しい手法と比較する際に併記します。

ティティの一言: 審判はラケットを見ていません。ボールがどこに落ちたのかを数えるだけでも、ほとんどすべて正解できます。ただし、1つの偽バウンドによって順序がまるごと狂ってしまうため、ルールの大部分は偽物を取り除くために使われます。

参考

ログインするといいねできます

コメント

まだコメントはありません。

ログインするとコメントできます