日本の家は狭い。でも複数楽器を弾いてアンサンブル動画を作りたい。そこで SAM2 と Ultralytics を使って人物をセグメンテーションし,複数の演奏動画を合成する仕組みを作った。
背景:狭い部屋でアンサンブル動画を作りたい
日本に住んでいると,どうしても部屋が狭い。楽器をいくつも並べるスペースはほぼない。
一方,私はギター・ベース・ドラム・鍵盤など複数の楽器を弾く,いわゆる multi-instrumentalist だ。
YouTube などでよく見る「一人アンサンブル動画」や「ループパフォーマンス動画」を作りたいと思っても,各楽器を別々のカットで撮影して合成する必要がある。昔ながらのアプローチは,グリーンバック(クロマキー)を使う方法だが,狭い部屋でグリーンバックを展開するのも一苦労だ。
もっと手軽にできないか? → 2024 年に登場した SAM2 (Segment Anything Model 2) を使えば,グリーンバックなし・通常の室内撮影だけで人物をきれいにくり抜けるはず,と考えた。
SAM2 とは
Meta が 2024 年に公開した Segment Anything Model 2 (SAM2) は,画像だけでなく 動画に対してもリアルタイムにセグメンテーション ができるモデルだ。
- 1 フレーム目に対象を指定するだけで,以降のフレームも追跡してマスクを生成してくれる
- オブジェクトの一時的な隠れ(オクルージョン)にも対応している
- 論文: SAM 2: Segment Anything in Images and Videos (Ravi et al., 2024)
Ultralytics を使う理由
Meta 公式の SAM2 API を直接使う方法もあるが,依存関係のセットアップが煩雑だったり,API がやや扱いにくい面がある。
そこで Ultralytics を使う。Ultralytics は YOLO シリーズで有名なフレームワークで,最新版では YOLO と SAM を同一の Python API で扱える。
1pip install ultralytics
1from ultralytics import SAM 2 3model = SAM("sam2_b.pt") # SAM2 Base モデルをロード
これだけで SAM2 が使える。モデルの重みは初回実行時に自動ダウンロードされる。
処理パイプライン
全体の流れは以下のとおりだ。
1入力動画 (各楽器の演奏動画) 2 ↓ 3 SAM2 でフレームごとに人物マスクを生成 4 ↓ 5 マスクを使って人物領域を切り抜き → RGBA 動画として書き出し 6 ↓ 7 背景動画 (or 画像) の上に各パート動画を重ねて合成 8 ↓ 9 合成動画の完成
① SAM2 で人物をセグメント
1from ultralytics import SAM 2import cv2 3import numpy as np 4 5model = SAM("sam2_b.pt") 6 7# 最初のフレームでクリックポイントを指定して人物を追跡 8results = model.track( 9 source="guitar_take.mp4", 10 points=[[320, 240]], # 画面中央付近の人物をクリック 11 labels=[1], # 1 = foreground 12 stream=True, 13) 14 15masks = [] 16for r in results: 17 if r.masks is not None: 18 masks.append(r.masks.data[0].cpu().numpy()) 19 else: 20 masks.append(None)
② マスクを使って RGBA 動画を生成
1cap = cv2.VideoCapture("guitar_take.mp4") 2fourcc = cv2.VideoWriter_fourcc(*"mp4v") 3out = cv2.VideoWriter("guitar_masked.mp4", fourcc, 30, (width, height)) 4 5for i, mask in enumerate(masks): 6 ret, frame = cap.read() 7 if not ret or mask is None: 8 break 9 alpha = (mask * 255).astype(np.uint8) 10 rgba = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA) 11 rgba[:, :, 3] = alpha 12 out.write(rgba)
③ 背景の上に合成
1# 背景画像の上に各パートを alpha blending で重ねる 2def composite(bg, fg_rgba): 3 alpha = fg_rgba[:, :, 3:4] / 255.0 4 fg_rgb = fg_rgba[:, :, :3] 5 return (fg_rgb * alpha + bg * (1 - alpha)).astype(np.uint8)
GPU vs Apple Silicon の推論速度
Google Colab の T4 GPU と MacBook Pro M4 (Apple Silicon) で推論速度を比較したところ,それほど大きな差が出なかった。
| 環境 | 1 フレームあたりの推論時間 (目安) |
|---|---|
| Google Colab (T4 GPU) | 約 30〜50 ms |
| MacBook Pro M4 (MPS) | 約 40〜60 ms |
これはなぜか?Ultralytics 側で モデルの量子化・TensorRT / CoreML への変換・バッチ処理の最適化 など,推論を高速化するための工夫が多数施されているためと考えられる。Apple Silicon の Metal Performance Shaders (MPS) バックエンドも有効活用されている。
実際のところ,今回のユースケース(数十秒〜数分の短い演奏動画)では,どちらの環境でも十分なスループットが出た。
結果
各楽器のテイク動画から人物をくり抜いて合成した結果,グリーンバックなしでも十分きれいに合成できた。

↑ ギター・ベース・ドラムの 3 パートを合成した例(プレースホルダ)

↑ SAM2 が生成したフレームごとのマスク(プレースホルダ)
まとめ
- Ultralytics を使えば SAM2 を 1 行でロードでき,依存関係のトラブルなしに使える
- YOLO による人物検出と SAM2 によるセグメンテーションを 同一 API で組み合わせられる
- GPU (Colab T4) と Apple Silicon M4 の推論速度は意外なほど近く,M4 Mac だけでも実用的なパイプラインが組める
- グリーンバックなしの室内撮影から手軽に合成演奏動画が作れるようになった