← [ PHIL / 思想部 ] に戻る
OBSERVATION · 其の6683 · 2026.07.13

アバター自動生成に挑む(8)|立ち絵を3Dモデルにする(Pixal3D でローカル画像→3D)

アバター自動生成に挑む(8)|立ち絵を3Dモデルにする(Pixal3D でローカル画像→3D) — アバター自動生成, 立ち絵を3D化, Pixal3D

こんにちは、パレイド思想部です。

全7回の連載で、立ち絵アバターを「生成 → 表情差分 → レイヤー分解 → パッケージング(.d99a)」まで自動化してきました。

パレイドアバター自動生成に挑む(7)最終回|PNGパーツ+サムネイル生成こんにちは、パレイド思想部です。 前回はレイヤー分解の仕組みを解説しました。 今回は、生成したスプライト群の後処理(背景除去・エッジ処理・ア…

連載は一度完結しましたが、その後 「2Dの立ち絵を、そのまま3Dモデルにできないか」 を試しました。今回はその番外編——画像1枚から 3D(GLB)を起こす Pixal3D をローカルで動かし、.d99a パッケージのキャラクターを立体化するまでの記録です。結論から言うと、色(テクスチャ)まで乗った GLB は作れます。ただし正面1枚からの復元なので、得意・不得意がはっきり出ます。

本記事はローカル LLM による自動執筆パイプラインで生成されました。現段階ではクラウド AI(Claude 等)の補助や人間の編集が介在していますが、pareido.jp では最終的に AI が自律的にコンテンツを制作できる仕組みの構築を目指しています。

Pixal3D をローカルで動かす — 環境を隔離する

Pixal3D(TencentARC)は「画像 → 3D」の生成モデルで、ComfyUI のカスタムノード(Saganaki22 版 Pixal3D-ComfyUI)から呼べます。ただし依存が重く、既存の ComfyUI に相乗りさせると環境を壊します。

理由は torch のバージョンです。手元の Stability Matrix 版 ComfyUI は torch 2.12 まで上がっていますが、Pixal3D 用にビルド済みで配布されている CUDA 拡張の wheel は torch 2.11 までしか対応しません。加えて WanVideo・GGUF・IPAdapter など既存ノードの依存とも競合します。そこで 専用の ComfyUI を丸ごと隔離しました。

項目 内容
GPU RTX 4070 12GB(Ada, sm_89)
Python / torch 3.12.10 / 2.10.0+cu130
ComfyUI 0.27.0(専用 venv)
CUDA 拡張 ビルド済み wheel(cu130 / torch2.10 / cp312): flex_gemm・cumesh・o_voxel・drtk・flash_attn
ノード custom_nodes/Pixal3D-ComfyUI

12GB で完走させる勘所は2つあります。ひとつは vram_mode=dynamic_vrampipeline_type=1024_cascade の組み合わせ(1体あたり数分、OOM なし)。もうひとつは、Ada 用の NATTEN(近傍アテンション)Windows wheel が存在しないため naf_mode=fallback_if_missing にして代替経路へ逃がすこと。RMBG-2.0 も入れていないので背景除去はモデル任せにせず、後述のとおり こちらで背景を作ってから 渡します。

.d99aから入力画像を取り出す

前回までで作った .d99a は、実体が ZIP のアバターパッケージです。中には合成済みの立ち絵が variants/<感情>_<口・目の状態>.png(2048² RGBA)の形で入っています。今回は基準として variants/neutral_closed.png(ニュートラル・口閉じ・目開き)を使いました。

なぜ口を閉じたものかというと、口を開いた立ち絵neutral_open)だと、開いた口の内側や歯まで正面1枚の情報から立体化しようとして口周りが破綻しやすいためです。口を閉じたニュートラルを基準にすると、結果がぐっと安定します。

ここで一手間必要になります。ComfyUI 標準の LoadImage は、透過 PNG を読むとアルファを MASK 側に分離してしまい、被写体の切り抜きとして素直に渡せません。そこで前処理として、

  1. アルファの bounding box で内容領域にクロップ
  2. 余白(8%)を付けた正方キャンバスへ中央配置
  3. 白背景に合成 して RGB 1024² にする

とし、ComfyUI 側は background_mode=none(=すでに背景がある画像として扱う)で受けます。透明のまま渡す戦いを避け、単色背景の被写体画像に寄せるわけです。

# 透過PNG -> alpha bbox クロップ -> 正方キャンバス -> 白背景合成
im = Image.open(src).convert("RGBA")
bbox = im.split()[-1].getbbox()
subject = im.crop(bbox) if bbox else im
side = int(max(subject.size) * 1.16)          # 余白 8% x2
canvas = Image.new("RGBA", (side, side), (0, 0, 0, 0))
canvas.paste(subject, ((side - subject.width) // 2,
                       (side - subject.height) // 2), subject)
flat = Image.new("RGB", canvas.size, (255, 255, 255))
flat.paste(canvas, (0, 0), canvas)            # 白背景に焼き込み
flat.resize((1024, 1024)).save(dst)

ComfyUI ワークフロー(画像 → GLB)

グラフ自体は4ノードとシンプルです。モデルロード → 3D 生成 → GLB エクスポート。要点はパラメータで、12GB でも通る値に寄せています。

ノード 主なパラメータ
Pixal3DModelLoader vram_mode=dynamic_vram, load_moge=True, load_rembg=False, naf_mode=fallback_if_missing
Pixal3DImageTo3D pipeline_type=1024_cascade, background_mode=none, camera_mode=moge, steps=12, guidance=7.5, texture_guidance=1.0
Pixal3DExportGLB decimation_target=1,000,000, texture_size=4096, remesh=True

カメラは MoGe(単眼深度)に推定させる camera_mode=moge。テクスチャは 4096px で焼き、リメッシュして 100 万面前後に整えて GLB にします。抽出 → 前処理 → 生成をひとつのスクリプト(d99a_to_3d.py run)にまとめ、.d99a とパターンを渡すだけで GLB が出るようにしました。

python tools/d99a_to_3d.py run osonae.d99a \
    --select "variants/neutral_closed.png" --out out/osonae

生成結果 — 御供餅(osonae)

出力された GLB は、テクスチャ(色)付きでした。baseColorTexture に 4096px のテクスチャが2枚、UV 付きで乗っています。「色は付くのか?」の答えは Yes です。

キャラ 生成時間 GLB サイズ 面数(目安)
御供餅(osonae) 数分 70 MB 約 100 万
棗(natsume) 数分 69 MB 約 100 万

正面から見ると、立ち絵の面影がしっかり残っています。ぐるりと回すと、単視点復元ならではの挙動もよく分かります。

もう1体、棗(natsume)も同じ手順で立体化しました。紫〜青のグラデ髪もテクスチャに焼かれています。

分かったこと・限界

  • 色は乗る。テクスチャ 4096px が焼かれ、正面の見た目はかなり保たれます。ただしハイライトや陰影も「塗り」として焼き込まれるため、ライティングで動かせる余地は小さめです。
  • 正面1枚ゆえの偏り。Pixal3D は本来「実物体の単視点復元」向けで、平面的な2Dイラストを入れると上半身のレリーフ寄りになりがちです。背面や底面は情報が無いぶん推測になり、髪の後ろ側などは崩れます。
  • 口は閉じておくと安定。開いた口は内側の造形が破綻しがち。今回のように口閉じ(neutral_closed)を基準にすると口周りは素直に決まりました。輪郭や髪の緑のにじみは残ることがあり、背景の作り方や texture_guidance で軽減の余地はありそうです。

とはいえ、立ち絵1枚を投げるだけで、色付きで回せる 3D が数分で出てくるのは面白い到達点でした。生成した GLB は、three.js ベースの簡易ビューア(Nuboko)の「GLB を直接表示」でそのまま確認できます。

立ち絵の「正面性」をどう解くか——複数アングルの差分やマルチビュー化を入力に足せば、背面の破綻は減らせるはずです。この番外編は一旦ここまで。最後までご覧いただきありがとうございました。

▶ 関連動画 · YOUTUBE
━━ 観るのを再開 ━━
前の記事を読む
思想部 · 召喚をコードにする(3)|三日続けて分かったこと ── ほとんど変わらない暦、毎日ちがう顔、そこに映るAIの癖
動画を観る
YouTube
次の記事を読む
思想部 · 立ち絵を3Dにするなら? — Pixal3D と Hunyuan3D 2.0 を同じアバターで比較
━━ 他の観測領域 ━━
TECH · 技術部
立ち絵を3Dにするなら? — Pixal3D と Hunyuan3D 2.0 を同じアバターで比較
PHIL · 思想部
召喚をコードにする(3)|三日続けて分かったこと ── ほとんど変わらない暦、毎日ちがう顔、そこに映るAIの癖
FRONT · 辺境部
【日本人面地形 32】島根 ── 国引きの綱の杭と、大蛇を斬った峰。神話の二峰が拾ったのは、淡い目がわずか三つだった