色々試してみる
前回 マスクはバウンディングボックスであるべきということがわかった。
今回は、そのほかの条件をどういうのがうまくいくのかを試してみようと思う。
入力プロンプト
"empty background, high quality, wall, ivy, bricks"
リファレンスは必須か?
リファレンスがどうかを試してみた。基本設定から入力リファレンスをなくした状態
結果、リファレンスなしでも生成可能。 リファレンスがなくともグレーエリアに純粋にノイズが乗っかりそこを再構築していくが、周りに合わせて作るので、大きく周りと変化がない場合はリファレンスは不要なのだろう。
リファレンスおよびプロンプトは必須か?
リファレンスとプロンプトを同時に不使用にしてみた。基本設定から入力リファレンスとプロンプトをなくした状態
どういうこと?? 入力イメージとマスクは健在なのだけど、
とりあえず、promptを無しっていうのは問題なのか?代わりに、 " " (空白)にしてみたところ。
とこれも成功。ここまででわかったことはpromptは何かしろは必須。ただ、今回のタスクのように一部を変更するrepaintingタスクではあまり寄与してないかも。というのも周りの情報がグレーの部分、つまりノイズの状態をどんどん更新していって、本来あるべきものになるというセオリーなんだと思う。 と思ったけど・・・
同じ条件で何度か試した中ではこういうものも・・・ 誰なん?
マスクは必須か?
ここまで来て、グレーに塗りつぶされていさえすれば、マスクは不要なのでは?という考えに至る。
試してみた。
使用してるのは入力動画と空白プロンプトのみ。
想像では、グレーの部分にはノイズが入ってそこが良いように埋められると思ったのだけど、どうやらマスクがないと、元の構造を変更しないという制約になるみたいです。
全面真っ黒なマスクを与えてみると、
全面真っ白なマスクを与えてみると、
コードから追ってみましょう。
wan_vace.py の prepare_source メソッドおよび vace_encode_frames メソッドのロジックをみると、
1 . 入力の準備 (prepare_source)
まず、動画とマスクがどう処理されるか。
# vace/models/wan/wan_vace.py
if sub_src_mask is not None:
# A. マスクあり (Inpaintingモード)
# src_video: 入力動画 (例: 人物部分をグレーに塗った動画)
# src_mask: 0=保護, 1=書き換え対象 のバイナリマスク
pass
else:
# B. マスクなし (I2V / V2Vモード)
# src_video: 入力動画 (例: グレーの四角がある動画)
# src_mask: 全域 1.0 (全画素が「書き換え対象」扱い)
src_mask[i] = torch.ones_like(src_video[i])
2 . Conditionの生成 (vace_encode_frames)
次に、これらがどうやってモデルへの入力(Latent)に変換されるか。
VACEは入力を inactive (保護) と reactive (作用) の2つのチャンネルに分けてエンコードします。
# vace/models/wan/wan_vace.py
# マスク: 1.0 = 書き換え(Reactive), 0.0 = 保護(Inactive)
masks = [torch.where(m > 0.5, 1.0, 0.0) for m in masks]
# 【Inactiveチャンネル】: 保護領域の映像が入る。マスク内はゼロ(黒)。
# i * (1 - m) なので、m=1 (マスク内) は消える。
inactive = [i * (1 - m) + 0 * m for i, m in zip(frames, masks)]
# 【Reactiveチャンネル】: 書き換え領域の映像が入る。マスク外はゼロ(黒)。
# i * m なので、m=1 (マスク内) の映像だけが残る。
reactive = [i * m + 0 * (1 - m) for i, m in zip(frames, masks)]
# これらを結合してDiTに渡す
latents = [torch.cat((u, c), dim=0) for u, c in zip(inactive, reactive)]
ケース1: マスクなし(実験結果:色が少し変わっただけで出力)
- 設定: src_mask = None (コード内で全域 1.0 に変換される)。
- Inactive: (1 - 1.0) = 0 なので、全域真っ黒(情報なし)。
- Reactive: 1.0 なので、入力動画(グレーの四角付き)がそのまま入る。
- モデルの挙動:
• Reactiveチャンネルを通じて「元の動画」が完全に見えている。
• モデルはこれを「書き換えのベース映像(I2Vのソース)」として使う。
• プロンプトで強い指示がないため、「元の動画をできるだけ再現する」 動きをする。
• 結果、グレーの四角もそのまま再現された。
ケース2: マスクあり + 入力動画グレー塗り(実験結果:Inpainting成功/失敗)
- 設定: src_mask で人物領域を指定 (1.0)。src_video のその場所はグレー (0.0)。
- Inactive: マスク外は背景映像が入る。マスク内は黒(ゼロ)。
- Reactive: マスク外は黒。マスク内は「グレー(0.0)」が入る。
- モデルの挙動:
• Inactive情報(背景)は「保護」される。
• Reactive情報(マスク内)は「0.0(無)」。
• 「書き換えろと言われた場所(Reactive)に、情報(映像)がない」。
• モデルは参照すべき元ネタがないため、学習した知識と周辺ピクセル(Self-Attention)を使って、ゼロから描画(Inpainting) せざるを得ない。
• → これがRemoval成功のメカニズム。
ケース3: マスクあり + 入力動画そのまま(17日目の失敗例)
- 設定: src_mask (人物シェイプ) あり。src_video は人物の形にグレーに塗りつぶされてる。
- Reactive: マスクに「人物の形状」 が入る。
- モデルの挙動:
• 「書き換えろと言われた場所に、人物がいるな」
• 「じゃあ、この人物をベースにして、プロンプト(背景)に近づけようか……
いや、動きもあるしな……」
• → どっちつかずでよくわからない人が出てくる。
結論
• マスクなし は「全域Reactiveモード」であり、入力動画がガイドとして機能する(I2V)。
• マスクあり は、マスク内をReactive、外をInactiveに分ける。
• Removalの成功条件 は、Reactiveチャンネルに渡す情報を 「無(グレー)」 にして、
モデルにガイドを与えない、余計なものを想定させない。
• つまりここでも ボトルネック戦略 なのである。
Day 17の振り返り:勝因は「引き算」
Day 17の実験結果を整理しましょう。
| 設定 | 結果 | 評価 |
|---|---|---|
|
A. 全部盛り (人型マスク + 背景Ref + そのままの動画) |
大失敗 青い謎の人物が出現 |
失敗: 情報過多・矛盾 |
|
B. 最低限戦略 (BBoxマスク + Refなし + グレー塗りつぶし) |
ほぼ成功 人物は消滅。背景も綺麗。 |
成功: 情報ボトルネック |
なぜ、情報を減らした(Refを捨て、マスクを雑にした)方がうまくいったのでしょうか?
マスクの形状
人型マスクの敗因
「人型マスク」はモデルにとって 人 を想起させてしまうほか何物でもないのです。
BBoxマスクの勝因
一方、BBox(矩形)は単純な形です。圧縮されても「四角い穴」であることは変わりません。
モデルにとって 「ここからここまで、ガッツリ欠損しています!」 というメッセージが明確に伝わったのです。
グレー(127) = 無(0.0)
そして決定打となったのが 「グレー塗りつぶし」 です。
画像データ(0〜255)は、モデルに入力される際、通常 [-1.0, 1.0] の範囲に正規化されます。
- 黒 (0) → -1.0
- 白 (255) → 1.0
- グレー (127) → 0.0
ニューラルネットワークにおいて、0.0 は「無(特徴量ゼロ)」 を意味します。
マスク領域をグレーで塗りつぶすということは、モデルに対して 「ここには何の情報もありません(バイアスゼロです)」 と宣言することと同義です。
リファレンス画像を与えず、入力もゼロにする。
完全に情報を遮断されたモデルは、仕方なくこう考えます。
「情報がない……なら、周囲のピクセル(マスク外の背景)から文脈を読んで、自分で描くしかない(Self-Attention)」
これが、Inpainting(背景補完)が成功した真の理由です。AutoEncoderのところで深掘りした 「情報ボトルネック戦略」 そのものです。
VFX素材提供:ActionVFX(Free Assets)
VFX assets courtesy of ActionVFX










