人物回避字幕(完全/できるだけ被らない)
0. 2つの目標を区別する
- 「完全に被らない」:各文字枠と各フレームの人物マスクとの積集合が0。代わりに文字は両脇/上部の狭いカラムにのみ配置でき、フォントサイズが制限されます。
- 「できるだけ被らない」:羽の端/背景に重なるのは許可し、顔と体は確実にクリアにします。大きなフォントスタイル(S4/S6など)を引き続き使用でき、近景フレームのみチェックします。
本スキルはデフォルトで「完全に被らない」を実行し、検証可能なデータを提供します。ユーザーが「炸裂/大字/アート文字」と言った場合は、ほぼ後者になります。
1. コアアルゴリズム(高速版:bboxのみ)
ピクセル単位の正確なマットは求めず、人物のバウンディングボックスのみを1/4解像度で計算するため、非常に高速です。
- 背景板
bg_half.npy(1280×540、subject-color-gradeの2.1/3.1を参照)。 - 各フレームを 640×270 に縮小し、背景板との差を計算:
d = |frame-bg|.max(axis=2)、閾値 38(低い閾値だとLOVEの電飾/光跡が誤検出されます)。 MaxFilter(5)で膨張 → 最大連結成分(BFS、640×270なら高速)→ bboxを×4してフル解像度に復元。- 歌詞の句ウィンドウごとに各フレームのbboxを結合(一句の中で人物は動くため、句全体での最幅範囲を使用)、各句の
bounds = (left,right,top,bottom)を取得。 - レイアウト:テキスト列を
left-50の左側 /right+50の右側 / 上部 / 下部に配置。フォントサイズは使用可能な幅に応じて縮小。 - フレームごとの検証:各文字枠を640×270にマッピングし、各フレームのマスクとの積集合を求め、最悪のヒット数を報告。0でなければ全体のフォントサイズを縮小して再検証し、0になるまで繰り返し。
2. 直接再利用可能な実装
字幕\build\avoid_side2.py(推奨、完全版:pass1でbbox計測 → layout → verify → レンダリング → キーフレーム):
$py='C:\Users\35530\.dsh\dsh-runtimes\dsh-primary-runtime\dependencies\python\python.exe'
& $py '字幕\build\avoid_side2.py'
このスクリプトは古い動画(0001-4956)の15.4秒のクリップを固定処理します。動画/クリップを変更する場合は以下の定数を修正します:
SRC/OUT/T0,T1CUES(各句の開始・終了、クリップ相対)EL内のフォントサイズ/位置候補(L/Rカラム、y、fs)LEFT_MARGIN/ 右側使用可能幅ロジック 生成物:NEON_avoid_15s.ass+ レンダリング動画 + キーフレームテーブル。 旧バージョン(合成デモ):avoid_demo.py、avoid_debug.py、avoid_layout.py(占有ヒートマップ分析_占位与选位.jpg)。
3. 本プロジェクトの実測データ(古い動画 0:51–1:06.4)
- 固定下部レイアウト:6/6句が人物に重なり、人物領域の遮蔽率 7%–12%。
- サイドカラム回避:0/6句が人物に重なり、1句あたりの遮蔽 ≤0.2%。フレームごとの検証 0ピクセル。
- 各句の使用可能なサイドカラム(古い動画、全幅2560):左カラム 約0–500px、右カラム 約2100–2560px。句ごとに異なるため、毎回動的に計算する必要があります。
- 人物が画面中央で羽を広げている場合、幅の占有率は約48%–82%。近景/クローズアップではほぼ画面を占有 → クローズアップフレームでは文字を上下の隅にのみ配置可能。
4. レイアウト戦略(被らない場合でも見栄えよく)
- 主歌詞は左カラムへ、装飾語は右カラムへ配置し、「左右の掛け合い」のような印象を演出。
- 上部に長いフレーズ(
MAKING EVERYBODY GOなど)を配置し、下部には小さな文字・等幅情報のみを残す。 - 各句には1つの「視覚的主役」のみを置き、他の語は小さな文字にして、句全体が大きくてサイドカラムに収まらないのを避ける。
- 文字枠の見積もりは控えめに:ASCII幅 ≈ fs×0.66、CJK幅 ≈ fs×1.06。10–14pxのパディングを残す。
5. 検証チェックリスト
- 各句ウィンドウのbboxが羽根の先/頭頂部を見逃していないか(
分析_占用区域.jpgを確認) - フレームごとの検証で worst hit = 0(スクリプトが出力)
- 3–4フレームを抽出して確認:文字が端に寄りすぎていないか/切れていないか、小指や羽に重なっていないか
- 近景/クローズアップフレームを個別に抜き打ちチェック
- 「できるだけ被らない」を許可する場合、どのフレームが羽に重なったかを記録(許容)
6. 既知の落とし穴
- 背景のLOL電飾/光跡がフレーム差で誤検出される可能性 → 閾値38 + 最大連結成分で通常除去可能。それでもダメなら空間的な事前情報(人物は中央)を追加。
- 人物の影が人物として誤検出される可能性(bboxが大きくなる)→ 回避処理上は安全(影も避ける)ですが、サイドカラムはより狭くなります。
- フィルタ
MaxFilterは640×270で約8px(フル解像度換算)の外側拡張となるため、検証時に追加のパディングを拡大しないように注意。 - 新しい動画や新しいカメラ位置に変更した場合、すべてのboundsを再計算する必要があります。古い動画の数値は再利用できません。