ステータス:ドラフト(2026-10-13)、実測反映(否定的な結果を含む)。 分類実験と劣化実験は、2026-10-11~12にCPUの一時ポッドとノートPCで測定した値です。終端(スコア)の効果は実際の音ではなく、正解の時刻から作成した 擬似onset のみで測定しました。スマホの録音条件は未測定です。論文の数値は「論文」と表記しました。 作成ルール:実測データが基本であり、測定できなかったものは「未測定」と表記します。
目次
- 1. なぜ音なのか
- 2. 原理その1:onset検出
- 3. 原理その2:表面分類
- 4. 実測:きれいな録音ではほぼ完璧だった
- 5. 実測:条件が悪くなると
- 6. 否定的な結果:実際の録音では効果を確認できなかった
- 7. 組み込むとしたらこのように
- 参考
1. なぜ音なのか
卓球場で目を閉じていてもラリーを追うことができます。「ポコッ」というテーブルの音と、「パコッ」というラケットの音が交互に聴こえます。音が魅力的な理由は3つあります。
- 映像が弱い場所で持ちこたえる。 暗かったり、ボールがブレたり、選手の体に隠れたりしても音は聴こえます。パート2でボールの検出が大きく崩れた条件(暗さ0.685、隠蔽0.842)は、音には関係ありません。
- 時間が細かい。 60fpsの映像は16.7msごとに1枚ですが、44.1kHzの音は1ms以内に44個のサンプルがあります。バウンドの瞬間をフレームよりも正確に特定できます。
- 打球とバウンドを直接区別する。 パート5で最もよくあるミスである「打球をバウンドと誤読する」ことに対して、音は「その瞬間聴こえたのはラケットの音だった」と直接答えることができます。
2. 原理その1:onset検出
onset とは、音が突然始まる瞬間です。ボールがテーブルに当たる音は、数ms以内に大きく上昇して消える短い衝撃音であるため、onsetを見つければバウンド時刻が得られます。
直感的には「音の強さが直前よりも急に大きくなった場所」です。計算はだいたい3段階です。
- onset強度曲線を作る。 短いウィンドウ(数ms)ごとにエネルギーを測定するか、周波数成分ごとに直前のウィンドウより増加した分だけを加算します(spectral flux)。増加分だけを見る理由は、音が続いている間ではなく 始まる瞬間だけを捉えようとするためです。
- 基準線に追従する。 周囲の騒音レベルは刻々と変化するため、固定の閾値の代わりに直近の平均(移動平均や指数移動平均)の何倍かを閾値として使用します。
- ピークを選ぶ。 閾値を超える局所的極大値をonsetとし、近すぎるピークは1つに統合します。
この分野の古典的なサーベイはBello et al.のonset検出解説(IEEE Trans. Speech and Audio Processing, 2005)であり、Pythonのlibrosaは onset.onset_detect として「onset強度曲線からのピーク選択」を提供しています。
卓球の音に関する論文(Gossard et al., arXiv 2409.11760, IEEE STAR 2025)は、よりシンプルな道を選びました。10kHzのハイパスフィルター(5次バターワース)で低い騒音をカットし、1msウィンドウのエネルギーを指数移動平均と比較します。ボールが衝突する音は高周波成分が強いため、人間の話し声や足音の大部分がフィルターで排除されます。きれいな録音では精度0.98・再現率1.00であり、話し声を混ぜても0.98・0.95でした(論文、指向性マイクを選手側に50cm~2m配置した録音)。
3. 原理その2:表面分類
onsetを見つけたら、「何の衝突音か」を分類します。onset直後の短い断片(TT Soundsは15ms)を切り出して特徴量を抽出し、分類します。
特徴量とは、音の「音色」を数値で要約したものです。私たちの実験では77次元を使用しました。人間の耳の周波数感覚に合わせたMFCC 20個の平均と標準偏差、スペクトルの重心や広がりといった形状指標、周波数帯別の対数エネルギーなどです。テーブルは広い板なので低く長い響きがあり、ラケットはゴムと木なので短く鈍い音がします。この違いが特徴量に表れます。
分類器はシンプルなもので十分でした。ロジスティック回帰、ランダムフォレスト、ヒストグラムベースの勾配ブースティング(HistGradientBoosting)を比較しました。論文では小さなCNNによる表面分類F1 0.97、ノートPCのCPUで4.2msが報告されています(論文)。
4. 実測:きれいな録音ではほぼ完璧だった
TT Sounds(テュービンゲン大学、CC BY-NC 4.0)の15msサンプル5,702個を使用しました。ラケット3,396・テーブル777・床290・その他1,239であり、元の115個の録音から切り出したものです。
重要な決定が1つありました。データセットが提供した80/20の分割は、 同じ録音から切り出した隣接サンプルが学習とテストの両方に含まれます。 隣接サンプルはほぼ同じ音であるため、テストは実質的に暗記した内容を再び問うことになります。そのため、 元の録音単位で5分割し、テストには初聴きの録音のみが入るようにしました。データセットの分割方法で測定すると、0.1~0.8%p高く測定されました。
| タスク | ロジスティック | ランダムフォレスト | HistGB | テーブルの再現率 / 精度(ロジスティック) |
|---|---|---|---|---|
| テーブル vs ラケット | 99.3% | 98.9% | 99.1% | 98.3% / 98.1% |
| テーブル vs 残りの3つ | 98.8% | 98.8% | 98.9% | 97.0% / 94.5% |
| 4つ | 97.4% | 97.5% | 97.6% | 97.3% / 96.3% |
特徴量抽出は1サンプルあたり4.7ms、予測は0.001~0.04ms(CPU)でした。リアルタイム処理として十分です。
5. 実測:条件が悪くなると
同じサンプルのテスト分割に対してのみ劣化を加えました。話し声は実際のコーチの音声を混ぜ、音楽と残響は合成です。「テーブルの音か」の再現率 / 精度です。
| 条件 | きれいな音のみで学習 | 劣化を混ぜて学習 |
|---|---|---|
| きれい | 0.946 / 0.972 | 0.891 / 0.991 |
| ホワイトノイズ SNR 20dB | 0.623 / 0.992 | 0.960 / 0.979 |
| ホワイトノイズ SNR 10dB | 0.009 / 1.0 | 0.945 / 0.960 |
| 話し声 SNR 0dB | 0.738 / 0.740 | 0.860 / 0.923 |
| 隣のテーブルのバウンド 0dB | 0.983 / 0.407 | 0.940 / 0.605 |
| マイク8m(残響合成) | 0.421 / 0.968 | 0.852 / 0.911 |
2つのことが明らかです。
- きれいな音だけで学習した分類器は、雑音に対して脆弱である。 ホワイトノイズ SNR 10dBでは、テーブルの音を0.9%しか見つけられませんでした。雑音・話し声・距離は学習時に混ぜておけば、ほとんどが回復します(0.85~0.96)。
- 隣のテーブルの音は、混ぜて学習させても区別できない。 精度が0.61~0.77にとどまりました。隣のテーブルのバウンドも同じテーブルの音だからです。15msの断片だけでは「自分たちのテーブル」のものかどうかを知ることはできません。卓球台が複数ある卓球場で、 音だけでバウンドを判定してはならない 理由がここにあります。
6. 否定的な結果:実際の録音では効果を確認できなかった
ここまでは綺麗に別途録音された音でした。本当の疑問は「試合映像と一緒に撮影された音でも機能するのか」ということです。
最初にぶつかった壁はデータでした。 OpenTTGamesの映像には音声トラックがありません(ffprobeで12本すべて映像ストリームが1つだけであることを確認)。映像・音声・バウンドの正解データが揃っている公開データを見つけることができませんでした。
そのため、映像に音声が含まれているT3Set(アマチュア多球練習、CC BY-NC-SA 4.0)を使用しました。映像ファイル(mkv)に音声(AAC 44.1kHz)が同じコンテナに含まれているため、時間的な同期は保証されます。8ラウンド(選手8名)に上記の分類器を適用してみました。
| 観察 | 値 | 期待 |
|---|---|---|
| ほぼ無音のラウンド | 8個中2個(onset 0個、1個) | 0 |
| ラケットセンサー(IMU)が測定した打球時刻±30ms内のラケット音 | 打球8~16個中1~5個 | ほぼすべて |
| 打球間のテーブル音の数 | 0~15に分散 | 多球練習であれば2付近 |
実際の練習場の録音でバウンドを区別できるという根拠は得られませんでした。 評価基準自体も脆弱でした。ラケットセンサーの時計と映像ファイルのファイル名(秒単位)のズレがラウンドごとに-1.5秒から+3秒まで異なり、打球時刻の同期からして揺らいでいました。そのため、音はエンジンに組み込みませんでした。
シミュレーション:音があった場合のスコアは?
映像と音声と正解が揃ったデータがないため、実際の試合12試合の正解バウンド・打球時刻から 偽のonset を作成し、「このような品質の音があった場合」を測定しました。実際の音ではない点を改めて強調します。設計上、音は判定を変更せず「要確認」のみを変更する方式であるため、勝者の精度はすべての行で93.1%のまま変わりません。
| 音質(シミュレーション) | 確認なしで誤り | 要確認 |
|---|---|---|
| 音なし(基準) | 10 | 41.1% |
| きれいな近接マイク(再現率0.95、時間揺らぎ5ms、同期済み) | 8 | 41.8% |
| T3Setレベル(再現率0.2、ラベル30%入替)をそのまま信頼 | 7 | 54.2% |
| 同じ音、「音の品質が低い」と判定して無視 | 10 | 41.1% |
| 音と映像が100msズレ、同期なし | 3 | 77.8% |
| 100msズレ、同期により除外 | 8 | 41.8% |
読み方はこうです。きれいで同期された音は、確認なしでの誤判定2件を人間の前に引き上げます。同期されていない音はラケット音がバウンドの位置に重なり、要確認を2倍に増やします。人間がほぼすべてのラリーをもう一度確認しなければならないため、使い物になりません。 音を使うには、音声と映像のズレの推定と「この音は信頼できるか」の判定が先決です。
7. 組み込むとしたらこのように
エンジンに組み込む際の設計はすでに決めてあります。
- バウンド候補の±20ms(60fpsの1フレーム)以内に「テーブル」のonsetがあれば、そのバウンドの信頼度を上げる。
- テーブルの帯の中にあるVであるにもかかわらず、その瞬間の音が「ラケット」であれば打球とみなす(パート5の「打球をバウンドと誤読する」対策)。
- ボールが見えていない間に聴こえたテーブルの音は「音のみのバウンド」として確認画面にのみ表示し、審判には渡さない(どちら側のサイドかわからないため)。
- 映像の候補がない場合、音単体でバウンドをカウントしない(隣のテーブル対策)。
- 音ごとに品質スコア(0~1)を算出し、低い場合はその音を使用しない。 存在しない証拠を反対の証拠として使用しない。
その前に必要なものは1つだけです。 撮影ガイド通りに撮影したスマホ映像に対し、人間がバウンド時刻を付与したテストセット。 スマホのマイク、卓球場の響き、隣のテーブルの音において上記の数値がどうなるかは、そのテストセットがなければ測定できません(未測定)。事前学習済みの汎用オーディオ埋め込みを用いて雑音に強い分類器を作る方法も調査しましたが、まだ実験の段階には至っていません(進行中)。
ティーティーのひと言。 静かな部屋で録音した「ポコッ」という音は99%聞き取れましたが、実際の卓球場の音ではまだ聞き取れませんでした。できなかったことも記録しておくことが、次に迷わないための近道です。
参考
- Gossard et al., Sound-Based Spin Estimation in Table Tennis: https://arxiv.org/abs/2409.11760
- TT Sounds データセット: https://github.com/cogsys-tuebingen/tt_sounds (README に CC BY-NC 4.0)
- Bello et al., A Tutorial on Onset Detection in Music Signals, IEEE Trans. Speech and Audio Processing 13(5), 2005
- librosa
onset.onset_detect: https://librosa.org/doc/0.10.2/generated/librosa.onset.onset_detect.html - T3Set: https://zenodo.org/records/15516144 (CC BY-NC-SA 4.0)
- 私たちの測定: リポジトリ
docs/tt/PERFORMANCE.md2.7(音声実験)、2.9.6、コードexperiments/sound/·experiments/fusion/sound_robust.py