Shap-E Text-to-3D Generator によるテキストからの3次元形状生成デモ
【概要】
Shap-EはOpenAIが公開した条件付き拡散モデルであり,テキストプロンプトから3次元形状メッシュを生成する。本ページでは,Python開発環境の準備から,Shap-Eによる3次元形状生成の実行までを解説する。
【目次】
【関連する外部ページ】
https://github.com/openai/shap-e(Shap-E公式リポジトリ)
【サイト内の関連情報】
https://www.kkaneko.jp/cc/dev/aiassist.html(NVIDIA CUDA,Visual Studio,Cursorなどのインストール解説)
第1章 Python開発環境,ライブラリ類
ここでは、最低限の事前準備について説明する。機械学習や深層学習を行う場合は、NVIDIA CUDA、Visual Studio、Cursorなどを追加でインストールすると便利である。これらについては別ページ https://www.kkaneko.jp/cc/dev/aiassist.htmlで詳しく解説しているので、必要に応じて参照してください。
Python 3.12 のインストール
Pythonのインストールを行い、Pythonのプログラムを実行する環境を整える。扱う環境は、Windows搭載パソコンである。金子研究室では、Python 3.12.10を推奨する。
[Windows での Python 3.12 のインストール手順を見るには、ここをクリック]
Windows での Python 3.12 のインストール
以下のいずれかの方法でPython 3.12をインストールする。Pythonがインストール済みの場合、この手順は不要である。
方法 1:winget によるインストール
【インストールコマンドの実行方法】
管理者権限でコマンドプロンプトを起動する(手順:Windowsキーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」)。そして、コマンド全体をコマンドプロンプトにコピー&ペーストする。
--scope machine を指定することで、システム全体(全ユーザー向け)にインストールされる。このオプションの実行には管理者権限が必要である。インストール完了後、コマンドプロンプトを再起動するとPATHが反映される。
REM Python 3.12 をシステム領域にインストール
winget install --id Python.Python.3.12 -e --scope machine --silent --accept-source-agreements --accept-package-agreements --override "/quiet InstallAllUsers=1 PrependPath=1 Include_test=0 Include_pip=1 Include_launcher=1 InstallLauncherAllUsers=1 TargetDir=\"C:\Program Files\Python312\""
if not "%ERRORLEVEL%"=="0" ( color 0c & echo Python 3.12 のインストールに失敗しました & ping 127.0.0.1 -n 6 >nul & color )
REM Python と Scripts を PATH 先頭に追加
powershell -NoProfile -Command "$p='C:\Program Files\Python312'; $s=\"$p\Scripts\"; if(Test-Path $p){$k=[Microsoft.Win32.Registry]::LocalMachine.OpenSubKey('SYSTEM\CurrentControlSet\Control\Session Manager\Environment',$true); $c=$k.GetValue('Path','',[Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames); $t=$k.GetValueKind('Path'); $new=$c; if((';'+$new+';') -notlike \"*;$p;*\"){$new=$p+';'+$new}; if((';'+$new+';') -notlike \"*;$s;*\"){$new=$s+';'+$new}; if($new -ne $c){$k.SetValue('Path',$new,$t)}; $k.Close()}"
REM 現在のセッションにも反映(システムPATHを再取得して連結)
for /f "usebackq tokens=2,*" %A in (`reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v Path`) do set "PATH=%B"
REM pip / wheel の更新
python -m pip install --no-user -U pip wheel
if not "%ERRORLEVEL%"=="0" ( color 0c & echo pip / wheel の更新に失敗しました & ping 127.0.0.1 -n 6 >nul & color )
方法 2:インストーラーによるインストール
- Python公式サイト(https://www.python.org/downloads/)にアクセスし、「Download Python 3.x.x」ボタンからWindows用インストーラーをダウンロードする。
- ダウンロードしたインストーラーを実行する。
- 初期画面の下部に表示される「Add python.exe to PATH」にチェックを入れてから「Customize installation」を選択する。このチェックを入れ忘れると、コマンドプロンプトから
pythonコマンドを実行できない。 - 「Install Python 3.xx for all users」にチェックを入れ、「Install」をクリックする。
インストールの確認
コマンドプロンプトで以下を実行する。
python --version
バージョン番号(例:Python 3.12.x)が表示されればインストール成功である。「'python' は、内部コマンドまたは外部コマンドとして認識されていません。」と表示される場合は、インストールが正常に完了していない。
Python の開発環境 Visual Studio Code のインストールと Python 用の設定
Python の開発環境Visual Studio Code(プログラムを編集するソフトウェア。以下、VS Code)を整える。
[Windows での Visual Studio Code のインストールと Python 用の設定手順を見るには、ここをクリック]
Windows での Visual Studio Code のインストールと Python 用の設定手順
1. VS Code と拡張機能のインストール
以下のコマンドにより,既存の VS Code を削除し,全ユーザー共有の設定で再インストールしたうえで,拡張機能(VS Code に機能を追加するソフトウェア)をまとめて導入する.
【インストールコマンドの実行方法】
管理者権限でコマンドプロンプトを起動する(手順:Windows キーまたはスタートメニュー → cmd と入力 → 右クリック → 「管理者として実行」)。そして,コマンド全体をコマンドプロンプトにコピー&ペーストする。
インストールコマンド
REM ============================================================
REM Microsoft Visual Studio Code
REM ============================================================
REM Build Tools + Desktop development with C++(VCTools)+ 追加コンポーネント(一括)
REM 未インストール時: winget で新規インストール
REM インストール済み時: setup.exe modify でコンポーネント追加(バージョンは変更しない)
winget list --id Microsoft.VisualStudio.BuildTools 2>nul | findstr /i "BuildTools" >nul 2>&1
if %ERRORLEVEL% EQU 0 (
for /f "usebackq delims=" %P in (`"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -products Microsoft.VisualStudio.Product.BuildTools -property installationPath`) do start /wait "" "C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe" modify --installPath "%P" --add Microsoft.VisualStudio.Workload.VCTools --add Microsoft.VisualStudio.Workload.MSBuildTools --add Microsoft.VisualStudio.Component.VC.CMake.Project --add Microsoft.VisualStudio.Component.VC.Llvm.Clang --add Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset --add Microsoft.VisualStudio.Component.Windows11SDK.26100 --add Microsoft.VisualStudio.Component.VC.v143.x86.x64 --includeRecommended --quiet --norestart --nocache
if not "%ERRORLEVEL%"=="0" ( color 0c & echo Build Tools のコンポーネント追加に失敗しました & ping 127.0.0.1 -n 6 >nul & color )
) else (
winget install --scope machine --id Microsoft.VisualStudio.BuildTools -e --silent --disable-interactivity --force --accept-source-agreements --accept-package-agreements --override "--quiet --wait --norestart --nocache --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --add Microsoft.VisualStudio.Workload.MSBuildTools --add Microsoft.VisualStudio.Component.VC.CMake.Project --add Microsoft.VisualStudio.Component.VC.Llvm.Clang --add Microsoft.VisualStudio.Component.VC.Llvm.ClangToolset --add Microsoft.VisualStudio.Component.Windows11SDK.26100 --add Microsoft.VisualStudio.Component.VC.v143.x86.x64"
if not "%ERRORLEVEL%"=="0" ( color 0c & echo Build Tools のインストールに失敗しました & ping 127.0.0.1 -n 6 >nul & color )
)
REM 全ユーザー共有の拡張機能フォルダ
if not exist "C:\ProgramData\vscode-extensions" mkdir "C:\ProgramData\vscode-extensions"
icacls "C:\ProgramData\vscode-extensions" /grant "Everyone:(OI)(CI)M" /T
REM スタートメニューのショートカットを --extensions-dir 付きで再作成
if exist "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio Code" rmdir /s /q "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio Code"
if exist "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio Code.lnk" del "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio Code.lnk"
powershell -NoProfile -Command "$s=New-Object -ComObject WScript.Shell; $lnk=$s.CreateShortcut('C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio Code.lnk'); $lnk.TargetPath='C:\Program Files\Microsoft VS Code\Code.exe'; $lnk.Arguments='--extensions-dir \"C:\ProgramData\vscode-extensions\"'; $lnk.Save()"
REM ショートカットの検証
powershell -NoProfile -Command "$s=New-Object -ComObject WScript.Shell; $lnk=$s.CreateShortcut('C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Visual Studio Code.lnk'); Write-Host 'TargetPath:' $lnk.TargetPath; Write-Host 'Arguments:' $lnk.Arguments"
REM ファイル / フォルダ右クリックの「Code で開く」を登録
reg add "HKLM\SOFTWARE\Classes\*\shell\VSCode\command" /ve /d "\"C:\Program Files\Microsoft VS Code\Code.exe\" --extensions-dir \"C:\ProgramData\vscode-extensions\" \"%1\"" /f
reg add "HKLM\SOFTWARE\Classes\Directory\shell\VSCode\command" /ve /d "\"C:\Program Files\Microsoft VS Code\Code.exe\" --extensions-dir \"C:\ProgramData\vscode-extensions\" \"%1\"" /f
reg add "HKLM\SOFTWARE\Classes\Directory\Background\shell\VSCode\command" /ve /d "\"C:\Program Files\Microsoft VS Code\Code.exe\" --extensions-dir \"C:\ProgramData\vscode-extensions\" \"%V\"" /f
REM --extensions-dir 付きで起動する code.cmd ラッパを作成
REM (%* を echo で書くと対話的 cmd で失われるため、PowerShell で [char]37+'*' を書き出す)
powershell -NoProfile -Command "$pct=[char]37; $q=[char]34; $c='@echo off'+[char]13+[char]10+$q+'C:\Program Files\Microsoft VS Code\bin\code.cmd'+$q+' --extensions-dir '+$q+'C:\ProgramData\vscode-extensions'+$q+' '+$pct+'*'+[char]13+[char]10; [IO.File]::WriteAllText('C:\ProgramData\vscode-extensions\vscode.cmd',$c,[Text.Encoding]::ASCII)"
REM 拡張機能のインストール
set "CODE=C:\Program Files\Microsoft VS Code\bin\code.cmd"
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --uninstall-extension GitHub.copilot
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --uninstall-extension GitHub.copilot-chat
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension ms-python.python
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension ms-python.vscode-pylance
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension ms-python.debugpy
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension MS-CEINTL.vscode-language-pack-ja
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension saoudrizwan.claude-dev
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension rust-lang.rust-analyzer
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension tamasfe.even-better-toml
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension anthropic.claude-code
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --install-extension almenon.arepl
"%CODE%" --extensions-dir "C:\ProgramData\vscode-extensions" --list-extensions --show-versions
REM settings.json を作成(自動更新オフ、Python、Claude Code 設定)
if not exist "%APPDATA%\Code\User" mkdir "%APPDATA%\Code\User"
python -c "import json,os;data={'update.mode':'none','update.enableWindowsBackgroundUpdates':False,'extensions.autoUpdate':False,'python.defaultInterpreterPath':r'C:\Program Files\Python312\python.exe','claudeCode.environmentVariables':[{'name':'ANTHROPIC_API_KEY','value':'not-needed'},{'name':'ANTHROPIC_AUTH_TOKEN','value':'ollama'},{'name':'ANTHROPIC_BASE_URL','value':'http://localhost:11434'},{'name':'ANTHROPIC_MODEL','value':'glm-4.7-flash'},{'name':'CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC','value':'1'}]};p=os.path.join(os.environ['APPDATA'],'Code','User','settings.json');open(p,'w',encoding='utf-8').write(json.dumps(data,indent=4));print('Done:',p)"
REM 自動更新の抑止ポリシー(settings.json に加えて、レジストリ側でも明示的にオフ)
reg add "HKLM\SOFTWARE\Policies\Microsoft\VSCode" /v "UpdateMode" /t REG_SZ /d "none" /f
echo === セットアップ完了 ===
2. Python インタプリタの選択
同一マシンに複数の Python がインストールされている場合,VS Code で使用する Python 本体(インタプリタ:Python プログラムを解釈・実行するソフトウェア)を選択する必要がある.
- コマンドパレット(コマンド名で機能を呼び出す VS Code の入力欄)を開く(
Ctrl+Shift+P) Python: Select Interpreterと入力する
- 表示される一覧から,使用する Python(例:
C:\Program Files\Python312\python.exe)を選択する.
必要なライブラリをシステム領域にインストール
管理者権限のコマンドプロンプトで以下を実行する。管理者権限のコマンドプロンプトを起動するには、Windows キーまたはスタートメニューから「cmd」と入力し、表示された「コマンドプロンプト」を右クリックして「管理者として実行」を選択する。
REM PyTorch をインストール(GPU対応版)
set "CUDA_TAG=cu128"
set "PYTHON_PATH=C:\Program Files\Python312"
"%PYTHON_PATH%\Scripts\pip" install --no-user -U numpy torch torchvision torchaudio --index-url https://download.pytorch.org/whl/%CUDA_TAG%
pip install --no-user git+https://github.com/openai/shap-e.git
pip install --no-user trimesh matplotlib ipywidgets
第2章 Shap-E Text-to-3D Generator
ソースコード
# プログラム名: Shap-E Text-to-3D Generator
# 特徴技術名: Shap-E (条件付き拡散モデル)
# 出典: Jun, H., & Nichol, A. (2023). Shap-E: Generating conditional 3D implicit functions. arXiv:2305.02463
# 特徴機能: 条件付き拡散モデルによる暗黙関数パラメータの生成。テキストプロンプトから3Dアセットを生成し,
# NeRFとテクスチャメッシュの多表現出力に対応するフレームワークである
# 学習済みモデル: OpenAI公式Shap-E学習済みモデル(text300M: テキスト条件,transmitter: 3D表現変換)
# 公式URL: https://github.com/openai/shap-e
# 方式設計(本実装の要点):
# 入力: テキストプロンプト(文字列)
# 出力: 3D形状メッシュ(PLY/OBJ/STL)を保存する(本実装では形状のみを対象とする)
# 処理手順:
# 1. テキストから潜在表現を生成
# 2. decode_latent_mesh(公式API)でメッシュ抽出
# 3. メッシュ品質処理(重複面・縮退面の除去,法線処理)と中心化(スケールは変更しない)
# 4. 形式別に保存および可視化
# 調整可能な設定値(本実装の既定値):
# GUIDANCE_SCALE: 生成品質と多様性のバランス(推奨域に合わせ 5.0)
# GENERATION_STEPS: Karrasサンプリングのステップ数(64)
# 前準備:
# pip install --no-user -U numpy torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128
# pip install --no-user git+https://github.com/openai/shap-e.git
# pip install --no-user trimesh matplotlib ipywidgets
import os
import numpy as np
import torch
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D # 可視化に使用
import trimesh
from trimesh.repair import fix_normals
from shap_e.diffusion.gaussian_diffusion import diffusion_from_config
from shap_e.models.download import load_model, load_config
from shap_e.diffusion.sample import sample_latents
from shap_e.util.notebooks import decode_latent_mesh
import warnings
warnings.filterwarnings("ignore", message="exception rendering with PyTorch3D")
warnings.filterwarnings("ignore", message="falling back on native PyTorch renderer")
# 調整可能な設定値
GUIDANCE_SCALE = 5.0 # 推奨域に合わせる
GENERATION_STEPS = 64 # Karrasステップ数
SEED = 42 # 乱数シード(再現性)
OUTPUT_DIR = "output" # 出力ディレクトリ
VISUALIZATION_SIZE = (12, 8) # 可視化サイズ(インチ)
# 出力ディレクトリ作成
os.makedirs(OUTPUT_DIR, exist_ok=True)
# 乱数シードの設定
torch.manual_seed(SEED)
np.random.seed(SEED)
# ガイダンス表示
print("=== Shap-E Text-to-3D Generator ===")
print("概要: テキストプロンプトから3Dモデルを生成します")
print("操作方法: プロンプトを入力後、Enterキーを押してください")
print("注意事項: 初回実行時はモデルのダウンロードに時間がかかります")
print("=" * 40)
def load_shap_e_models():
"""Shap-Eモデルの読み込みと実行デバイスの決定を行う"""
print("Shap-Eモデルを読み込んでいます...")
# GPU/CPU自動選択
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f'デバイス: {str(device)}')
# GPU使用時の最適化
if device.type == 'cuda':
torch.backends.cudnn.benchmark = True
# Shap-Eモデルと拡散設定の読み込み
xm = load_model('transmitter', device=device)
model = load_model('text300M', device=device)
diffusion = diffusion_from_config(load_config('diffusion'))
return xm, model, diffusion, device
def generate_3d_from_text(prompt, model, diffusion, device):
"""テキストから潜在表現を生成する"""
print(f"テキストプロンプト: {prompt}")
print("3D形状を生成しています...")
# デバイスに応じたFP16/FP32選択
use_fp16 = (device.type == 'cuda')
# 潜在表現の生成(Karrasサンプリングを使用)
latents = sample_latents(
batch_size=1,
model=model,
diffusion=diffusion,
guidance_scale=GUIDANCE_SCALE,
model_kwargs=dict(texts=[prompt]),
progress=True,
clip_denoised=True,
use_fp16=use_fp16,
use_karras=True,
karras_steps=GENERATION_STEPS,
)
return latents
def extract_mesh_from_latent(latent, xm):
"""潜在表現からメッシュを抽出する(公式API: decode_latent_mesh を使用)"""
# 公式経路でメッシュ抽出
mesh_obj = decode_latent_mesh(xm, latent)
tri_mesh = mesh_obj.tri_mesh()
# 頂点・面の取得(Tensor/Numpy両対応)
if hasattr(tri_mesh.verts, 'cpu'):
vertices = tri_mesh.verts.cpu().numpy().astype(np.float32)
else:
vertices = np.array(tri_mesh.verts, dtype=np.float32)
if hasattr(tri_mesh.faces, 'cpu'):
faces = tri_mesh.faces.cpu().numpy().astype(np.int32)
else:
faces = np.array(tri_mesh.faces, dtype=np.int32)
# Trimeshオブジェクトを作成
mesh = trimesh.Trimesh(vertices=vertices, faces=faces)
# メッシュの品質処理(重複面・縮退面の除去,法線処理)
print("メッシュの品質向上処理を実行しています...")
mesh.remove_duplicate_faces()
mesh.remove_degenerate_faces()
fix_normals(mesh) # 公式API(trimesh.repair)で法線処理
# 中心化(スケールは変更しない)
mesh.vertices -= mesh.vertices.mean(axis=0)
print("Shap-Eによる3D形状生成が完了しました(形状のみ、色情報なし)")
return mesh
def save_3d_mesh(mesh, filename_base):
"""3Dメッシュを複数形式(PLY/OBJ/STL)で保存する"""
print("3Dメッシュを保存しています...")
# PLY形式で保存
ply_path = os.path.join(OUTPUT_DIR, f"{filename_base}.ply")
mesh.export(ply_path)
print(f"PLYファイルを保存しました: {ply_path}")
# OBJ形式で保存
obj_path = os.path.join(OUTPUT_DIR, f"{filename_base}.obj")
mesh.export(obj_path)
print(f"OBJファイルを保存しました: {obj_path}")
# STL形式で保存
stl_path = os.path.join(OUTPUT_DIR, f"{filename_base}.stl")
mesh.export(stl_path)
print(f"STLファイルを保存しました: {stl_path}")
def visualize_3d_mesh(mesh, title="Generated 3D Model"):
"""3Dメッシュを可視化する"""
print("3Dモデルを可視化しています...")
vertices = mesh.vertices
faces = mesh.faces
# 頂点数のチェック(0の場合は可視化を中止)
if len(vertices) == 0:
print("警告: 頂点が存在しません。可視化をスキップします。")
return
# 3Dプロット
fig = plt.figure(figsize=VISUALIZATION_SIZE)
ax = fig.add_subplot(111, projection='3d')
# メッシュの可視化
ax.plot_trisurf(vertices[:, 0], vertices[:, 1], vertices[:, 2],
triangles=faces, alpha=0.9, cmap='viridis')
# 軸ラベルとタイトル
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title(f'{title}\nVertices: {len(vertices)}, Faces: {len(faces)}')
# 軸範囲の調整
x_range = vertices[:, 0].max() - vertices[:, 0].min()
y_range = vertices[:, 1].max() - vertices[:, 1].min()
z_range = vertices[:, 2].max() - vertices[:, 2].min()
# 範囲が0の場合のデフォルト値設定
max_range = max(x_range, y_range, z_range) / 2.0
if max_range == 0:
max_range = 1.0
mid_x = (vertices[:, 0].max() + vertices[:, 0].min()) * 0.5
mid_y = (vertices[:, 1].max() + vertices[:, 1].min()) * 0.5
mid_z = (vertices[:, 2].max() + vertices[:, 2].min()) * 0.5
ax.set_xlim(mid_x - max_range, mid_x + max_range)
ax.set_ylim(mid_y - max_range, mid_y + max_range)
ax.set_zlim(mid_z - max_range, mid_z + max_range)
# 範囲の表示
print(f"X軸範囲: {x_range:.3f}")
print(f"Y軸範囲: {y_range:.3f}")
print(f"Z軸範囲: {z_range:.3f}")
if z_range < 0.01:
print("警告: Z軸の範囲が小さいです。モデルが平面的になっている可能性があります。")
plt.tight_layout()
plt.show()
# モデル読み込み
xm, model, diffusion, device = load_shap_e_models()
# ユーザー入力
prompt = input("3D生成用のテキストプロンプトを入力してください: ")
# 3D形状生成
latents = generate_3d_from_text(prompt, model, diffusion, device)
# メッシュ抽出(公式API経路に一本化)
mesh = extract_mesh_from_latent(latents[0], xm)
# ファイル名ベースの作成
filename_base = prompt.replace(' ', '_').replace('/', '_').replace('\\', '_')[:50]
# 3D出力の保存
save_3d_mesh(mesh, filename_base)
# 可視化
visualize_3d_mesh(mesh, f"Generated: {prompt}")
print("\n処理が完了しました。")
print("生成された3Dモデルは以下の形式で保存されています:")
print("- PLYファイル: 3D編集ソフトで使用可能")
print("- OBJファイル: 汎用3D形式")
print("- STLファイル: 3Dプリンタ用")
# 推奨プロンプト
print("\n3D形状生成のヒント:")
print("- 単一のオブジェクトを指定(例: 'a chair', 'a vase')")
print("- 立体的な形状を明示(例: '3D model of a tree', 'volumetric sphere')")
print("- シンプルで明確な記述を使用")