Stable Diffusionで画像のポーズを変化させてみる

この記事は[京都大学人工知能研究会KaiRA Advent Calendar 2023](https://qiita.com/advent-calendar/2023/kyoto-kaira) 24日目の記事です。

今回やりたいことは「ある画像とポーズが与えられた時、その画像中の人物を指定のポーズに変化させる」ということです。これをStable Diffusionでやってみました。結論から言うと十分な品質での結果は得られなかったのですが、せっかくなのでアドベントカレンダーでまとめることにしました。

------

まず初めに思いつくのは[IP-Adapter](https://ip-adapter.github.io/)と[ControlNet](https://huggingface.co/lllyasviel/control_v11p_sd15_openpose)を使うやり方です。IP-Adapterはテキストプロンプトに加えて画像をプロンプトとして扱うための手法で、ある画像が与えられた時にその類似画像を生成したりできます。ControlNetの方は条件を追加で入力するための手法で、ポーズやエッジの条件を指定して画像を生成することができます。

しかし、以下のように、画像によってはIP-Adapterが上手く特徴を抽出できない場合があります(左から順にソース画像、ポーズ画像、生成画像)。生成画像へポーズ条件は十分に反映されており、服の雰囲気や背景の感じもソース画像のそれに類似しているものの、若干の変化が見られます。これでは「ソース画像のポーズを変化させた」とは言い難いです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629111/6ea3c28c-ee42-9070-3bdb-947188c9754e.png)
(ちなみにソース画像はフリーの画像サイトから持ってきたものです)

そこでどうにかしてソース画像への忠実度を高めたいと思います。

## 1. Self-AttentionをCross-Attentionに変える
1つ目のアプローチは、U-Net中のSelf-Attention部分をCross-Attentionに変えることです。そもそもStable DiffusionのU-Net中のAttentionモジュールは、Self-Attention→Cross-Attention→Feed Forwardという順で処理を行います。2つ目のCross-Attentionでは特徴マップとテキスト埋め込み(IP-Adapterなら画像埋め込みとも)とのAttentionを計算しています。このAttentionモジュールにおいて、Self-Attention部分を2つの特徴マップ同士でのCross-Attentionに変えることで、構成はクエリ側の特徴マップのものを、スタイルはキー・バリュー側の特徴マップのものを反映させるという研究があります[[1,2]](https://qiita.com/kym384/items/a299d746f679565acc3d#%E5%8F%82%E8%80%83%E6%96%87%E7%8C%AE)。式で書けば、
```math
\mathbf{Q} = \mathbf{W^Q} \mathbf{f}^{\mathrm{content}}, \,
\mathbf{K} = \mathbf{W^K} \mathbf{f}^{\mathrm{style}}, \,
\mathbf{V} = \mathbf{W^V} \mathbf{f}^{\mathrm{style}}, \,
```
```math
\mathbf{O} = \mathrm{Attention}(\mathbf{Q}, \mathbf{K}, \mathbf{V})
```
みたいな感じです。


この方法を採用してみました。
具体的には、U-Net中のすべてのAttentionモジュールとすべてのタイムステップにおいて、Self-Attentionの代わりにCross-Attentionを計算します。Cross-Attentionの方では、クエリ側に生成中の画像(の特徴マップ)、キー・バリュー側にソース画像(の特徴マップ)を入力します。ソース画像をU-Netに入力する際には、ランダムに生成したノイズをそのタイムステップでのSN比に従って付加します。

以下が結果画像です。シンプルなIP-Adapter + ControlNetよりもソース画像への忠実度がアップしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629111/2d773811-6afe-8db5-9240-571b67fc430d.png)

なお、Cross-Attentionでソース画像の情報を取ってこれるようになったためか、Classifier-free guidanceを使っても使わなくてもあまり変化がありませんでした。そのため、この段階でClassifier-free guidanceを廃止しています。

## 2. 付加するノイズをランダムにしない
次にやったことは、ソース画像に負荷するノイズを前ステップでのU-Netの出力で置き換えることです。DDIMのサンプリングでは、入力画像にかかっているノイズ=U-Netの出力と考えて、そのSN比が大きくなるように更新しているので、出力をそのままノイズに使ってしまおうという考えです。

以下が結果画像です。上と比べて、ソース画像への忠実度がさらにアップしています。画像品質も若干良くなってますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629111/e8eed78c-0d65-b46f-88bd-fce8e7aa3b49.png)

## 3. Softmaxの温度パラメータを大きくする
最後のアプローチとして、1のCross-Attentionを計算する時にSoftmaxの温度パラメータを大きくするということをやってみました。[[1]](https://qiita.com/kym384/items/a299d746f679565acc3d#%E5%8F%82%E8%80%83%E6%96%87%E7%8C%AE)の論文でAttention Mapの分散を大きくすることで品質が上がる(Attentionが必要以上に広い範囲にかかってしまうことを防いでるらしい)ということが報告されていたので、同じことをやってみましたが特に効果はなく…。その代わりにsoftmaxの温度パラメータを大きくしてみました。具体的には1.3倍にしてみます。

以下が結果画像です。全体的に陰影がはっきりしすぎている感じはありますが、足先部分などは若干忠実度がアップしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629111/625ad5e8-cef2-add1-b5b8-75d132ff5995.png)


## まとめ
正直生成品質はまだかなり悪いですが、一旦ギブアップです。
最後に、色々なポーズでの生成結果です。ポーズによって色々ハイパラを変える必要があり、特に3の温度パラメータは変えない方が良かったりもしたのであまり意味がなかったかもしれません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629111/5ab24d90-673b-29f8-02fb-db33ea3dbfac.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629111/52f86e26-6993-390b-397c-35c7c8278570.png)


## 参考文献
[1] Li Hu, Xin Gao, Peng Zhang, Ke Sun, Bang Zhang, and Liefeng Bo. Animate anyone: Consistent and controllable image-to-video synthesis for character animation. arXiv:2311.17117, 2023.
[2] Yuval Alaluf, Daniel Garibi, Or Patashnik, Hadar Averbuch-Elor, and Daniel Cohen-Or. Cross-image attention for zero-shot appearance transfer. arXiv:2311.03335, 2023.