今回も例の通りAIの話をしていきます。
前回まではAIイラストの話ばかりしていたのですが、GPT-4 APIを使わせていただく機会があって最近はAIキャラクター方面に注力していました。
前半はイラストで、後半はAIキャラクターのクオリティを向上させていく話でもしようかなと思います。
(下書き自体は3月の下旬から4月半ば辺りまでちょこちょこ書いていたんですが、あっという間に情報が古くなってしまって悲しい…。)
AIでイラストを作った時に、「めっちゃかわいくできたのに、ここだけ破綻してる…」みたいな残念なことは誰しも体験してることと思います。
なので、それをなんとかする方法を実践してみたのでその話をしていきます。
このように(他の要素に手を加えず)破綻した手を修正したり、表情差分を作ったりなどができるようになるという話です。
・i2iでInpaintを利用し、修正範囲を限定的にする。
・手形状のDepth画像(あるいはCanny画像)を利用して、Controlnetを使い、その部分のみ修正を加える
何も特別なことをしていませんが効果的です。
このイラストをベースに解説します。
今回はグーになっている左手がおかしなことになっているのでこれを修正します。
Promptを埋める
今回行うことは、要はi2iによって元の絵と同じテイストでInpaint部分を書き換えることです。
そのため、t2iで生成したイラストのPromptをそのままi2iのPromptに転記する必要があります。
i2iのInpaintで修正範囲をMaskする
img2imgタブにはInpaintの項目があります。画像内の任意の部分に対して編集をかけるものです。
そのタブで画像を読み込みます。その後マウスで適当に黒塗りしておきます。
Depth画像を適切な位置に合わせる
Photoshopでやっても良いし、適当な手のDepth画像がなければDepth-libを使ってWebUI内でこれを行っても良いです。
Controlnetで指定する
この時CanvasのWidthとHeightは合わせることが大事です。
あとはGenerateするだけ
(若干ガチャ要素があって何回か試行錯誤する必要があります。)
それでも絵のテイストを守りながら形状を直すのは絵に関する知識が必要なので、自分みたいな絵心がない人が手で修正するよりも遥かに早く修正できたので価値はあるのかなと思いますね。
実写系にも応用が効く手段なのでその点も大きいです。
表情差分を作るイラストの例も見てみます。
この例では、眉と口を任意の形状にすることを考えています。
以下のようにInpaint指定しています。(厳密でなくても適当で大丈夫です。)
これを先程と同様にやっていきます。
(今回はDepthでは顔の凹凸をうまく取得できなかったため、Canny(輪郭)によって制御しています。)
右のCanny画像を見てわかるように、眉と口の形状を自分で書いてControlnetに渡しています。
Photoshopで雑に矩形を配置したりしました。
このCanny画像を描くのがやや手間ですが、こちらは狙った表情がほぼ100%出るので前の例ほどの苦労はありません。
以上が差分生成方法の解説でした。
失敗例:
当たり前ですが、Inpaintで変更部分を限定しないとこのように全く別物の画像が生成されてしまいます。
Inpaint部分にControlnetを与えるのではなく表情プロンプトを与えてt2iで再生成する方法もうまくいくそうです。
Controlnetを使ってまで細かい指定をしなくて良いという場合はこの方法のほうが簡単に済みそうなので良さそう!
今回表情差分作りたいな~と思った時に、なかなかt2iで顔のアップ画像を作るのが難しかったので紹介しておきます。
例えば自分は事前にこのような画像を生成していました。
ControlnetのOpenPoseで確実に正面を向くように指定しただけのt2i画像です。
そしてこれをPhotoshopで拡大し、顔のアップ画像にします。
あとはこの画像をControlnetのcannyのソースとしつつ再度t2iで生成します。
こうすることで、安定して顔のアップ画像を作ることができました。
(Hires fixすると更に良いです。)
以下の記事を参考にやってみました。
AIイラストはノイズを収束させるという画作りの関係上、どうしても手や指、瞳の虹彩などの細部の表現の破綻を免れることができません。
ピクセルアート化することによってそういった細部の情報量を削った絵にするというのはAIと相性は良いだろうなと思いますね。
個人的に興味深かったツイートを貼ります。
基準となる色ベクトルを用意して、塗りで使われる色のベクトルを近傍探索して減色したらもしかして良い感じになるのかな…。
あとは、AIイラストは基本的に塗りや背景・ディテールがリッチすぎるという指摘があり、確かにそうだな…とも思いました。
その辺りの情報量をうまいことおとしてくれる手法が見つかるとAIイラスト感が一気に減って良い感じになりそう。
Controlnetが進化していろんな機能が追加されることとなりました!
一番興味深いのは、OpenPoseで顔と手が使えるようになったことですね。これができるとAIに伝えられる意図がかなり増えるので、喜ぶ人はいっぱいいるんじゃないでしょうか。
この間こんなものを作りました。
ChatGPT APIを使って何を言わせるかについて様々な研究やアプローチがありますが、キャラクターのふるまいも同じくらい重要だよなと思って個人的に色々と調べて作ってみたという経緯です。
(あとは自分に寄り添ってくれるかわいいAIキャラクターがほしい!というのもあります。)
色々と参考にしたのはこの本です。
この本は人間が当たり前にやっている会話にはルールがあるという話をしていて、その中からいくつか特になるほど!と思ったことを挙げてみます。
会話の交代時間
会話においては、発話の終了から200ミリ秒で話者が交代する。
→人間は発話を聞きながら予想したり回答を考えたりしてるので、このような早い時間で回答を行うことができる。
えっと…は重要な意味を持っている
話者交代が非常に短い間で発生してしまうので、人間は言葉に詰まった時に「まだ自分は発話するよ」というアピールとして「えっと…」と言う。
沈黙は様々な意味を持つ
沈黙が1秒を超えると、会話に問題があると感じる。
また、質問に対して沈黙をすると、「肯定的な応答をしたくない」という合図になる。(例えば、「ジュース買ってきて」と言って、「いいよ」と「・・・いいよ」の受け答えでは、意図が全然違う。)
そういった知見から今回の動画では、「なるべく回答の遅延を減らす」「発話途中に沈黙を作らないように、(えっと…)を入れる」ということをやってみたのでした。
実際にやってみると普通に何も気にせず発話させる時に比べてニアちゃんとの会話が人間のものに近づいたので、正解!!という感じの実装ができて良かったです。
AIキャラクターを作る、というのは人間のあらゆるパラメータを数値に表してそれを再構築していくことなんだなぁと思いますね。
なので、AIをうまく扱う方法を研究しながらも、同時に人間のこともちゃんと勉強していかないといけません。
そんなわけで次やるべきことは、キャラクターの記憶です。
今のところ、性格付けやふるまいについては最低限実装できているなという自分の中での納得感があるのですが、残念ながらまだ「記憶」ができていません。
会話の積み重ねによってキャラクターが自分のことをどんどん知っていってやがて俺が思いもしなかったようなことを発言してほしい…!
という思いから以下の本を買って読んでみましたが、なかなか良い本です。
書いてある内容で一番なるほどね~と思ったのは、以下のような内容です。
人間は特定のことを忘れてしまうけれど、抽象化したり大事なことだけを覚えておくことはできる。
詳細を忘れて大量の情報を処理しつつも、様々な経験を抽象化したものを組み合わせることで自分の中に概念を形成したり知識を吸収することができる。
確かに会話履歴をベクターストアに貯めて、会話時に近似した情報を引っ張ってくるだけじゃたぶん会話じゃなくて連想ゲームになってしまいますね。
そういうわけで直近の課題は、その人間らしい記憶の保持のやり方をスムーズに行うことができるかということになります。
パッと今考えたところで行くと
・会話を即時記憶として忘れても良い内容と長期記憶として保持する情報に分ける
・ChatGPTAPIを使って要約する
・長期記憶ベクターストアを更新する
・会話時にはそれを引っ張ってくる。
を繰り返すとそれっぽくならないかな…?と思いました。
もちろん実践してみないことには何もわかりませんが…。
短期記憶が長期記憶へと変化するメカニズムはさっき上で書いた本の下巻にどうやら書いてあるので読んでみたいなと思います。
来月の記事ではそこらへんの内容を理解した上でAIキャラクターに対する解像度が上がったよ~という記事が書ければ良いですね!
今月は以上となります!
最近はボイチェン(RVC)もめっちゃ盛り上がってて、「AIは遊びを考えられる奴が勝ち!」というのを感じています。
こういう技術で遊ぼう的な雰囲気、あまりにも大好きなので自分も少年の心を持ちながら情報を追っていければなと思います。
お読みいただきましてありがとうございました!