見出し画像

脳内キャラクターのLoRAを簡単に作りたい(切実)

今回は、前回の手法をより具体的に(主に画像データの用意とキャプショニング)説明します。
一部、前回の手法と関係のない話もあるので、そちらは番外として下にぶら下げておきます。
前回の手法は下記の記事をご覧ください。


スクリーンショット撮影の手間を低減する

従来はHoney Select 2のスタジオモードを起動してから手動でキャラクターを回転させていたが、Honey Select 2にはVNGEというモーションやカメラ制御を保存して紙芝居を作れるMODが存在するので、一度撮影用のシーンを作ってしまえば使い回しができる。
その上、Honey Select 2のシーンはpngファイルで配布できる。もし流用するなら全裸にしてから使うこと。

※png貼るとwebpになるのでzipにしてあります。
※筆者のVNGEのバージョンは36.7なので、最新のVNGEとは互換性が無い可能性があります。あらかじめご了承下さい。

画像の加工はPythonに任せる

先程の撮影用シーンで39枚の画像データを作ったわけだが、背景が透過なので、非透過の白い背景にするついでに画像サイズも正方形にする。
GPTに聞いて適当に書いたコードが以下の通り。

from PIL import Image, ImageFilter
import glob

print("start")

files = glob.glob("*.png") # pngファイルのリストを取得
for i, file in enumerate(files): # リストを順番に処理
    img = Image.open(file) # 画像ファイルを読み込む
    width, height = img.size # 画像の幅と高さを取得する
    left = (width - height)/2 # 切り出す左端の座標
    top = (height - height)/2 # 切り出す上端の座標
    right = (width + height)/2 # 切り出す右端の座標
    bottom = (height + height)/2 # 切り出す下端の座標
    img = img.crop((left, top, right, bottom)) # 画像を切り出す(正方形)
    datas = img.getdata() # 画像のデータを取得する
    newData = [] # 新しいデータのリスト
    for item in datas: # データのリストをループで処理する
        if item[3] == 0: # アルファ値が0なら(完全透明なら)
            newData.append((255, 255, 255, 255)) # 白色で不透明にして追加する
        else: # アルファ値が0でなければ
            newData.append(item) # 元のデータをそのまま追加する
    img.putdata(newData) # 新しいデータで画像を更新する

    new_fname = '{:03d}.png'.format(i+1) # 新しいファイル名(連番.png)
    img.save(new_fname) # 別名で保存する
    
print("finish")

ちゃんとコードが書ける人からすると穴があるのかもしれないが、やりたいことは出来ているのでヨシとする。

キャプションを固定する

VNGEで画角ごとの順番(=ファイル名)も固定されたので、あらかじめ用意したキャプションを流用することにした。

これの先頭に呼び出し用のキャプションを追記するだけで、毎回キャプションを剪定する必要もなくなる。
なお、筆者はキャラクターの特徴はすべてキャプションから消す派のため、このような手法を取っている。
また、キャプションの順番がほぼ固定されたので、キャプションのシャッフルをやめた(ss_shuffle_captionをFalse)

学習パラメータについて

前回の記事からパラメータを一部変更(LierLa→C3Lier)しているので一応記載しておく。
ただし、conv_alphaの適切な値などはよくわからんので、参考までに。

  • "ss_learning_rate": "1e-4"

  • "ss_unet_lr": "1e-4"

  • "ss_text_encoder_lr": "2e-5"

  • "ss_lr_warmup_steps": "250"

  • "ss_network_dim": "128"

  • "ss_network_alpha": "64"

  • "ss_network_args": { "conv_dim": "64", "conv_alpha": "32" }

  • "ss_shuffle_caption": "False"

番外①:dimのresizeについて

上記のパラメータの通り、dim=128のC3LierにしたことでLoRAのファイルサイズが肥大化した。
主にファイルサイズを下げる目的と、ついでに良い感じに不要な部分がカットできないかという目論見でresize_lora.pyを使ってdim=32に下げてみた。
結論としてはresizeしない方が良いかなという所感。
65枚ほど目視チェックした経緯が下のツイートにぶら下がっているので参考までに。

番外②:Block Weightによる層別探索

自分の中でセオリーを確立して、これで楽になるなと思うと新しい沼が現れる現象に名前を付けたい。
作成したLoRAの不要な層を切る(Weightを0にする)ことで、塗りや線が汚くなるのを防ぐという話。
率直に言って、明らかに切ってOKな層(OUT09~11など)を排除する程度に留めたほうがよい。LoRAごとにこの作業を精密にやっていると本当の地獄を見る。

おわりに

延々とキャラクターLoRA(しかも脳内キャラクター)を作り続けているけど、そもそもオリジナルのキャラクターを作って喜んでいる層ってどれくらいいるんですかね?
ちなみに、Honey Select 2を用いながら3Dっぽさを軽減するという手法自体は、ポーズ作成にも応用できることは確認済みなので、そろそろポーズLoRAも作ってみたいなと思いながらBlock Weightに遊ばれるだけで1ヶ月が過ぎていました。

最後にポーズと服の学習に転用した例を置いて終わります。


この記事が気に入ったらサポートをしてみませんか?