【StableDiffusion】VRoidからつくる衣装LoRA制作メモ【データセット付き】
■記事の対象ユーザ
1.SDXLのLoRAを作っている(=つよつよグラボを持っている)
2.衣装LoRAを作ってみたが上手く行かない
3.データセットとキャプションをどうしたら良いか判らない
■ようするに?
はじめに
ちょっと前に「コピー機学習法」による差分LoRA作りの記事で書いたことで
「おで、LoRA、すこしわかる」程度になった気でいたんだけど、調子に乗って同じ感覚で服LoRAにも挑戦したところ、勝手が違いすぎて全く上手くいかず結局1ヶ月くらい沼に浸かることになったんよ。
コピー機学習法は変化前と変化後の2枚だけでLoRAを作る手法だから、データセットについてはあまり意識する必要がなかったんだけど、キャラクターLoRAとか服LoRAみたいな通常のLoRA作成ではデータセット(教師画像と適切なタグ(キャプション))こそが重要になるって偉い人が言ってたのよね。
そこで今回の検証ではデータセットを焦点に検証を行って、50枚位の教師画像からそれっぽい服LoRAが作れるようになったので成功例(?)として記事に残しておくよ。
1.今回の目標
自然言語で表現できたり、毎回柄が変わってても問題ないような服であれば別にいいんだけど、言語化の出来ないモノであったり柄を維持しようと思うと途端に難易度が上がってInpaintなり手書きなりで加筆修正しないと現状の画像生成AIでは表現が難しいよね。
今回はVRoid Studioのプリセットとして用意されているお菓子の装飾のある水色のパーカーセットをテーマにしてみたんだけど・・・
Khaulaちゃん試しに言語化してみて?
ローカル勢なのでDALL3みたいな自然言語に強い有料サービスにはあまり詳しくないから断言はできないけど、少なくともStableDiffusionのSDXLではこんな複雑な命令はまず受け付けて貰えないよね。
「1girl, solo, aqua parka, hood, black shorts, black shoes」くらいなら理解してくれるけど
こういう難しい衣装を(完全再現はできなくても)毎回似たような衣装として出力にできればいいな!ってことで、今回の検証ではVRoid Studioで撮影したスクリーンショットをベースに教師画像を作成し、以下くらいであれば似せることができる服LoRAを作っていくね。
■ VRoid Studio の利用ガイドラインについて
本題に入る前に少し難しい話をしておくね。
ガイドラインと利用規約によると、
プリセットにあるモデルやテクスチャなどはPixivが権利を有してるけど、禁止されていること以外であればあらゆる目的での利用を許諾されているとのことだから今回の検証に利用させていただいたよ。
VRoidStudioに限らず、学習させる素材については許諾を確認しておこうね。
2.データセットについて
私も導入記事で書いたけどLoRAを作る時のデータセットの準備としては、以下のような手順を踏むことが多いと思います。
この手順だとTaggerの閾値設定によってはアホほど沢山のタグが付与されるし、そうでなくてもどのタグが必要でどのタグが不要なのか?の正解がそもそも判らないのが辛いよね。
あと、教師画像についても毎回様々な画角やポーズを考えてVRoidStudioなり出力したVRMファイルを使って別のツールで撮影するのも中々に大変なので「ルーティン化した手法でいい感じにデータセットを作れる方法」があればいいよねって思ってました。
今回色々検証していて幸いにも「 決められた48種類のデータセット」からそれなりのLoRAを作ることに成功(?)したので、そのデータセットについて書いていくよ。(そんなに沢山の成功例があるわけじゃないから、同じようにして失敗したらマジごめん)
用意する教師画像の種類について
以下の6つの範囲について8つの方向から撮影した計48種類。
全身(full body)だけ上から(from above)と下から(from below)からも撮影して24種類、他の3つ(cowboy shot / lower body / neck focus)についても同じように撮影して全96枚にしてもいい気がしてるんだけど、48枚でも十分許容範囲の出来になったので今回は48枚に留めているよ。
それぞれどういう画像を撮影すればよいか
教師画像とキャプションの関係は、普通なら用意した画像に対して後からキャプションをつけると思うんだけど、今回は「なるべくルーティン化したい」という方針から
という発想で、先に48種類の画像を生成できるプロンプトを考えて学習のベースとなるモデルで画像を生成。出来た画像に近いものをVRoid Studioで撮影するっていう方法を採用したよ。
これなら実際にその画像が生成できているプロンプトをキャプションにすることになるのでベースモデルとの認識違いも起き辛いよね。
例として「範囲:全身」「方向:正面」で画像を生成してみたよ。
左側はAnimagine XL 3.1が生成した画像。真ん中は与えたプロンプト。右側はVRoid Studioで撮影した画像だよ。
「青文字」は「範囲」
「赤文字」は「方向」
「緑文字」は「撮影のために仮で設定した衣装のタグ」
をそれぞれ示しているよ。
緑文字の部分は画像を生成する時、何かしら衣装指定がないとその部分が描画されなかったりするから暫定的に設定した衣装タグ。
学習時はこの部分をトリガーワードに置き換えることで服装と画風の部分だけがトリガーワードに集約されることになるね。
以下はAnimagine XL 3.1で画像を作った時のプロンプトの例だけど、
Pony系のモデルでも似たようなプロンプトの組み合わせで表現できるとは・・・思う。
このルールに従って撮影した48枚が以下となるよ。
【参考】48枚分のプロンプト
参考までに画像生成時に使ったプロンプトと撮影の参考用の画像をまとめたものを貼っておくね。
※斜めは前面or背面と同じ、側面は1つで済むので全18種。
【余談】教師画像に頭部を含めてはいけない
検証を始める前から、有志の情報で「服LoRAを作る時は頭部が見えない画像を教師画像にするとよい」ということは知ってたんだけど「いうてそこまで影響でんやろ!ガハハ!」というノリで作った最初のLoRAがこちらです。
この時の教師画像はこんななんだけど、頭部へのストレスを感じる。
3.VRoid Studioで撮影
何を撮影するのかは紹介したけど、撮影するにあたりVRoid Studioでいくつか設定しておくと良い項目があるので簡単に説明しておくね。
髪型、ベースヘアーを無しにしておく
画角によっては髪の毛が映りこんでしまい撮影できる角度が制限されてしまうことがあるから、最初から髪型とベースヘアーは消しておくといいよ。
アウトラインの設定
ルックのタブの右側でアウトラインの太さの設定ができるんだけど、デフォルトだと細すぎて撮影時にアウトラインが途切れてしまうことがあるから0.1~0.2の間で設定することをオススメするよ。逆に太すぎるとLoRAが太い線を覚えたり後述のイラスト風変換の時に線が2重に認識されたりするから都度調整してくれるとうれしいです。
撮影モードの設定
撮影する時はまず右上のカメラボタンから撮影モードに移動して
撮影モードの左側メニューの撮影サイズから、右側のパラメータで撮影サイズを1024x1024pxに変更してね。大きいサイズで撮影して後からトリミングしてもいいんだけど最初からサイズ指定しておくと加工が不要だから楽よ。
完成品(今回の検証で撮影したデータ)がレンジの中にあるので取り出します。
4.アップスケールで撮影画像を高解像度化
撮り終わった?ここで大体1/3くらいだからひと休みするならこの辺で。
VRoid Studioで1024x1024で撮影した画像をそのまま使うと、シャギー(アウトラインのギザギザの部分)をLoRAが学習してしまってLoRA適用時の生成画像に影響が出ちゃいます。
アウトラインを消して撮影したとしてもシャギーは出ちゃうので、LoRAへの影響は避けられなかったのよね。
この問題を低減するために撮影画像を1024x1024pxから2048x2048pxにアップスケールした後で1024x1024pxに戻す工程を加えたよ。
私はアップスケールするのにWebUI拡張のUlimate SD upscaleを使ってるけどシャギーが低減できればアプローチはお好みでOKだし、2048x2048px→1024x1024pxへの戻し処理もPhotoShopなりGIMPなりお手持ちのツールをやっちゃってください。
これでLoRA作成の1つめの教師画像が完成。次の項から2つめの教師画像を作っていくよ。
アップスケール→縮小後の教師画像も置いておくね。
5.教師画像をイラスト風に変換
アップスケールした画像を教師画像としてもそこそこの成果は得られたんだけど、どうしてもVRoid感というか3Dっぽさが残っちゃうのよね。
この3Dっぽさは学習時にキャプションに「3d」タグを加えたり、LoRA使用時のネガティブプロンプトに「3d」タグを入れることで低減することができるんだけど
「そもそも教師画像から3Dっぽさを除いてしまえば解決するよね!」
という安直なアイディアと
「自分で3Dモデルを作った時にモデルの仕上がりが悪くてもAIが補正してくれるよね!」
という希望的観測の2つを理由に、ここでは教師画像を
・AIで線画を作成できる「Ai-Assistant」
・線画から着色できるControlNet「anytest3」
の2つを使ってAIによる補正とイラスト風着色したものに変換していくよ。
「Ai-Assistant」とは
AIを使ったイラスト支援ツールを作っているとりにくさん(@tori29umai)が公開しているツールの1つで、線画化だけでなくノーマルマップ化やシェーディングまでできる多機能な支援ツール。最新版はFANBOXで支援すると使えるようになるけど、今回の線画化だけならV3でも大丈夫。
(開発費に困っているので良かったら支援してあげて欲しい・・・)
「anytest3」とは
私のLoRA系の記事でよくご紹介している月須和さん(@nana_tsukisuwa)が公開されているControlNetシリーズの1つで、入力画像の線を維持する性能が高いControlNetだよ。
※「anytest3」と「anytest4」の効果と違いついては以下の記事で紹介しているのでよろしければ見てってね
Ai-Assistantで線画作成
※ツール自体の導入方法については上述のとりにくさんのnoteをご照覧あれ
Ai-Assistantを起動したらまず「線画化」タブに移動
「入力画像」に2048x2048pxにアップスケールした教師画像を投入
線画抽出のCannyの設定値を入れて「生成」
設定値は体感で調整になるんだけど大体はデフォルトの20/120で大丈夫だと思う・・・。
「prompt分析」で線画を生成する時のポジティブプロンプトが自動生成されるよ。(ネガティブプロンプトはデフォルトで入ってて生成はされない)
基本的にはそのままでいいですが、生成した線画がおかしい時は変なプロンプトが自動生成されていないか確認してみてね。
なるべく入力画像に忠実にさせたいので忠実度を最大に設定して「生成」
しばらくして右側に出力線画が表示されたら完成。
出来上がりを見て微妙そうならプロンプトとかCannyの値を変えてみて何度か試してみてね。
「出力先」から保存先フォルダが開くので全て作り終えたら取り出してね。
線画化後の教師画像はこちら
anytest3で着色
ここからはStableDiffusion WebUIのi2iでの作業に移るよ。
Ai-Assistantはもう使わないのでアプリを閉じてメモリを解放しておこうね。
プロンプト
ポジティブプロンプトにはモデルの推奨プロンプトに「thin outline」を
ネガティブプロンプトにはモデルの推奨ネガティブプロンプトに「3d」を
それぞれ加えて教師画像の太い線と3Dっぽさの低減を目指しているよ。
(お守り程度の効果しかでないんだけどね・・・)
# Positive Promt
__animagine__, thin outline
# Negative Prompt
__animagine_negative__, 3d
【補足】 ワイルドカードについて
__animagine__とか__animagine_negative__はWebUI拡張のワイルドカードを導入していると使える書き方で、事前に別ファイルで用意したプロンプトを呼び出すことができるので、それぞれにAnimagine XL 3.1のポジティブ・ネガティブプロンプトを設定しているよ。
ワイルドカードなしで書くと以下のような感じになるね(長い)
# ワイルドカード ( __animagine__ )
safe,masterpiece,best quality,very aesthetic,absurdres
# ワイルドカード ( __animagine_negative__ )
sensitive,nsfw,lowres,(bad),text,error,fewer,extra,missing,worst quality,jpeg artifacts,low quality,watermark,unfinished,displeasing,oldest,early,chromatic aberration,signature,extra digits,artistic error,username,scan,[abstract]
input画像
VRoid Studioで撮影した画像をアップスケール→1024x1024pxに縮小したものを設定するよ。
ControlNet「anytest3」
anytest3に線画を入力すると、線を維持しながら着色をしてくれるので入力画像にAi-Assistantで出力した線画を設定するよ。
ControlNet「Reference」
anytest3だけだと着色を失敗することがあるのですが、入力画像と同じ画像をReferenceを設定することで色合いが安定します。
変換結果
上記の設定でi2iを実行するとanytest3が線画に沿って着色してくれて生成画像から3Dっぽさが低減されるよ。ただ、残念ながら線画変換の時点で細かいディティールが失われているので、anytest3が頑張ってくれても細部までは忠実にイラスト変換が出来ないのよね・・・。
とはいえ服LoRA自体が細かい装飾の再現が難しいものなので、このレベルで似ていれば良しとしています。
イラスト風変換後の教師画像はこちら
6.正則化画像の準備
ここまでで2/3といったところ。学習までいったらしばらく待ちになるからもう少しだけ進めよっか。
学習に入る前に、LoRA作成の記事や情報で良く省略されている正則化画像にの準備をしていくよ。
LoRAはキャプションに記載されているタグに対して学習した内容を覚えていくけど、トリガーワード以外の「1girl」や「head out of frame」といったタグにも多かれ少なかれ衣装・画風の情報を学習しちゃうのよね。
登場回数の少ないタグ(close-upとか)であれば影響は少ないけど、すべての画像に含まれている「1girl」とかは教師画像の情報を多く学習しちゃいます。そこで、ベースモデルが本来持っている「1girl」の情報を正則化画像として配置することで「1girl」が教師画像の情報で汚染されることを抑制することができるんだって。
やることはシンプルで、ベースモデルでそのタグの画像を生成して所定のフォルダに配置しておき、学習時にフォルダを指定するだけ。
画像に対するキャプションは不要(ない場合はフォルダ名から取得するため)で「1girl」タグの画像であれば「1_1girl」というフォルダ作って配置するよ。
(頭の1は繰り返し回数で、教師画像と同じくらいになるよう指定する。教師画像50枚なら1girl画像を50枚用意すればいいだけなので繰り返しは1のまま正則化画像の方を増やすほうが簡単ね)
ディレクトリ構造はこんな感じ。後述の学習設定では教師画像ディレクトリに「work」を正則化画像ディレクトリに「reg」を選択してね。
[ルートディレクトリ] - + work - 10_test_cloth - + 01.png
| + 02.png
| + 03.png
| + ...
|
+ reg - 1_1girl - + 01.png
+ 02.png
+ 03.png
+ ...
検証では「1girl」のみと「全てのタグ」に対して正則化画像を用意する方法を試してみたんだけど、私のやり方が良くなかったのか全てのタグを指定する方法ではあまり良い結果が得られなかったのよね。
「1girl」だけにした方がいい感じの出力を得られたものの、LoRA利用時に「outstretched arms」を指定したりすると急にVRoidっぽい画風になったりする事象を観測しているので、共通で入れている「outstretched arms」とか「head out of frame」「standing」「solo」辺りの頻出タグは正則化画像を作っておいた方が良いような気も・・・
7.キャプションの設定
ここまでの2つの教師画像のセットが出来上がりました。
①VRoidStudioで撮影した画像をアップスケール→縮小したもの
②それをイラスト風に変換したもの
学習用フォルダに教師画像とキャプションを配置していくわけだけど、
①についてはVRoid風味を軽減させるために追加で「3d」タグを追加しておくよ。
②については既にイラスト風になっているから「3d」タグの追加は不要で
緑文字の部分をトリガーワード(今回はtest_cloth)に置き換えるだけでOK。
キャプション付きのデータセット2つも以下に置いておくね。
8.Kohya's GUIでの学習設定
いよいよ学習を開始するわけだけど、今回の検証ではデータセットに重きを置いている都合上、学習設定について深く触れないで進めさせてもらうね。
オプティマイザやUNETやTextEncoderの学習率など調整の余地があるかと思うんだけど、今回はそこの解説は省略して上手く行った時の学習設定を紹介するだけに留めておくよ。
この学習設定用のJsonファイルはサービスだからまずダウンロードして読み込んでほしい。
2つのデータセットでそれぞれLoRAを作成します。データセット以外は設定同じだからデータセットのみ置き換えて作ればOKだよ。
以下、学習設定の特記事項をつらつらと書いていくね。
学習に使ったバージョン:kohya_ss_v24.1.4
グラボ:RTX3080 10GB
学習時間:2時間~3時間
■ Model
Pretrained model name or path:Animagine XL 3.1を指定
Trained Model output name:任意のLoRA名を指定
Image folder (containing training images subfolders):教師画像の配置されているフォルダ(の1つ上のフォルダ)を指定
SDXL:✅
■ Folders
Output directory for trained model:LoRAの保存先を指定
Regularisation directory (Optional. containing regularisation images):正則化画像の配置されているフォルダ(の1つ上のフォルダ)を指定
■ Parameters
Train batch size:うちのRTX3080 10GBでは2が限界
Epoch数:10(48枚でバッチサイズ2だと10エポックで4800STEPになる)
Save every N epochs:2(チェック用に少し細かく保存)
LR Scheduler:cosine_with_restarts
Optimizer:Lion8bit
Learning rate:0.0005(5e-4)
LR warmup (% of total steps):20
Text Encoder learning rate:0.001(1e-3)
Unet learning rate:0.0005(5e-4)
Network Rank (Dimension):16
Network Alpha:8
fp8 base training (experimental):✅ VRAM節約
Gradient checkpointing:✅ VRAM節約
Shuffle caption:✅ キャプションファイルの順番をシャッフルし学習時のタグの偏りをなくすオプション
すべて設定を終えたら学習開始で2-3時間待ちます。
4090とかのつよつよGPUを持ってる人はもっと早く終わるとおもう
(羨ましい)
9.LoRAのマージ
学習が終わってたらこの項を読み始めてね。
お手元に2つのLoRAが出来上がっているわけだけど・・・
えらい人もいってるとおり、同じ効果を持つLoRAをマージするといい感じに落ち着くことがあるので先にマージ版も作っておくことをオススメするよ。
教師画像の性質上、アップスケールだけのデータセットは3Dっぽさが残りやすいだろうし、イラスト風にした方はディティールが崩れやすい
はずなのでマージすることでお互いの弱点を補ってくれることを期待ageしてるの。
■ WebUI拡張 SuperMerger
LoRAのマージにもいくつか方法があるけど、私はSuperMergerを使っているので参考までにやり方を記載しておくね。
WebUIを起動してSuperMergerタブに移動すると、画面下部に(WebUIのLoRAフォルダにある)LoRAファイルの一覧が表示されるんだけど、作成したLoRAがここにない場合は探して格納しておいてね。
マージしたいLoRAにチェックを入れたら画面上部の設定を少し変更するね。
remake dimension:今回はnetwork dim=16で作ったけどマージ時に8とか32とかに変更する場合は値を選択してね。今回はautoにしておきます。
LoRAname1:ratio1:Blocks1,LoRAname2:ratio2:Blocks2,...(":blocks" is option, not necessary):LoRAのマージ倍率を指定するエリア。デフォルトではratioは1になってるけど、1でマージすると強くなりすぎるから0.7辺りからマージして確認するといいよ。dimを変えない場合はマージはすぐ完了するし完成したLoRAの効き具合を確認しながら微調整しようね。
10.動作確認
お待ちかね、出来上がった3種LoRAの動作確認をしていくよ!
確認は以下2つのプロンプトにそれぞれのLoRAを適用して見てみるね。
マージ版以外は2epoch毎に保存しているからLoRAなし~10epochまでの6枚の
比較画像を貼っていくよ。
確認用プロンプトその1:1girlとaqua parkaのみ
# Positive Prompt
__animagine__, 1girl,test_cloth,aqua parka
# Negative Prompt
__animagine_negative__
確認用プロンプトその2:ウチの子LoRA用
# Positive Prompt
__animagine__, 1girl,solo,kazuya_bros_khaula,test_cloth,fox ear,white animal ear fluff,black hair,dark skin,aqua eyes,white pupils,blight pupils,(yellow x hair ornament:1.2),open mouth,fang,smile,simple background,(animal tail:-1),(bare sholder:-1),aqua nails,aqua parka,black shorts,cowboy shot,<lora:kazuya_bros_khaula_adafactor:0.7>,
# Negative Prompt
__animagine_negative__
プロンプトその1
アップスケール画像で学習したLoRA
マージしたLoRA
イラスト変換画像で学習したLoRA
プロンプトその2
アップスケール画像で学習したLoRA
マージしたLoRA
イラスト変換画像で学習したLoRA
LBWを適用した場合
LoRAの適用する部分を指定できるWebUI拡張LoRA Block Weight(以下LBW)を使って衣装部分だけ適用するようにしたものでも検証してみるよ。
LBWについては私も過去に記事を書いてるのでご参考まで。
(記事はSD1.5向けに書いたものだけど、SDXLではLoRAの階層数が異なっているので過去記事は本当に参考程度にしておいてね)
こちらの記事がとても分かりやすく書いてくださってます。
さっきと同じ条件にLBW設定を入れたもので再確認していくよ。
プロンプトその1+LBW
アップスケール画像で学習したLoRA
マージしたLoRA
イラスト変換画像で学習したLoRA
プロンプトその1+LBW
アップスケール画像で学習したLoRA
マージしたLoRA
イラスト風画像で学習したLoRA
総評
さらに自分でダメだしすると「solo」とか「simple background」あたりの頻出タグを複数同時に設定すると、たまに以下のような教師画像そのまんまみたいな画像が出て来てしまうことがあるのよね。
この辺は正則化画像の整理とかで上手いことできるかもしれないので、現在進行形でやってる他の服LoRAとかで実験してみるね・・・。
とはいえ、ルーティン化した方法でもこのレベルの物は作れるよっていう1つの指標にはなったかと思うので、ここからは実用しながらブラッシュアップしていけるといいなって感じです!
おわりに
この記事を書き始めた時、前提としてVRoid StudioなりUnityなりblenderなりの3Dモデルを用意して自由な方向から撮影する必要があるから、書き出しが
「まず、服LoRAを作りたい3Dモデルを作ります」
と即死2コマ過ぎて諦めかけたんだけど、別に高品質な3Dモデルである必要は無くて現在進行形で私が作ってるこんな感じの適当なモデルでも
イラスト風変換の過程でこんな感じに補正できるの事は分かっているので
そこまで悲観する必要はないかもと思ってます。(本当はBlenderと和解して、モデル開発力を磨いた方が幸せになれるんだろうけど)
今回の内容で、いい感じの服LoRAが出来た!とか全然上手くいかねーぞオラァ!とかあれば情報頂けると助かります・・・。
では、またどこかの記事でお会いしましょう。お相手はカズヤ弟と