GenCAD 詳細教學
本教學對應 repo commit
f5484cf(2025-07-14),最後驗證日 2026-05-20。 涵蓋專案定位、安裝、核心架構、CLI 詳細用法、應用情境、資安掃描、FAQ、進階技巧、整合建議共 11 個章節。
1. 專案定位
1.1 是什麼
GenCAD 是 University of Maryland (Ferdous Alam 等人) 發表於 TMLR 2025 的「影像條件 CAD 生成 (Image-conditioned CAD Generation)」系統。給定一張 2D sketch、影像或渲染圖,系統會生成對應的參數化 CAD command sequence,再透過 OpenCascade (OCC) 還原成 .stl / .step 等 3D 檔案。
1.2 為什麼重要
- CAD 表示是可編輯的:不像 NeRF / Gaussian Splatting / Mesh 生成,CAD command sequence 保留了「
extrude、sketch、circle、arc」等可解釋語意,工程師可手動微調 - 比 DeepCAD 進一步:DeepCAD 解決 CAD-only autoencoder;GenCAD 加上 CLIP-style image conditioning + Diffusion Prior,能從 image 直接驅動生成
- 可作為通用框架:核心三段式 (sequence autoencoder + contrastive align + latent diffusion) 可移植到「分子序列、protein domain、生醫信號」等領域
1.3 與相關工作的關係
| 工作 | 關係 |
|---|---|
| DeepCAD (ChrisWu1997, 2021) | GenCAD 直接借用 cadlib/ 與 utils/cad_dataset.py,CAD 序列定義完全相容 |
| DALL·E / Stable Diffusion | 借鑑 CLIP-style alignment + diffusion prior 概念,但 latent space 是 CAD 命令而非 pixel |
| DreamFusion / Magic3D | 都是 image→3D,但 DreamFusion 輸出 NeRF/mesh,GenCAD 輸出可編輯參數 |
| pythonocc-core | OpenCascade 的 Python binding,負責 CAD 命令 → STL 轉檔 |
1.4 一句話總結
把「sketch / 影像」翻成「可編輯的 CAD 命令序列」的三段式生成系統 — Transformer autoencoder 編碼 CAD 命令,CLIP 對齊影像與 CAD latent,Diffusion Prior 從影像分布抽樣 latent。
2. 安裝指南
2.1 系統需求
| 項目 | 最低要求 | 建議 |
|---|---|---|
| OS | Linux x86_64 | Ubuntu 22.04 |
| Python | 3.10 | 3.10 |
| GPU | CUDA 11.x 相容 NVIDIA | A100 / RTX 4090 |
| RAM | 16 GB | 32 GB |
| Disk | 5 GB (含 checkpoint) | 20 GB |
pythonocc-core | 7.9.0 | conda 安裝(pip 沒得裝) |
2.2 方案 A — Docker(推薦)
1# 1. clone repo
2git clone https://github.com/ferdous-alam/GenCAD
3cd GenCAD
4
5# 2. 預先下載資料集 + checkpoint(必須先做)
6# Dataset: https://drive.google.com/drive/folders/1M0dPr5kILGY9HTRCHox1vLLDhhxJWl_C
7# 放到 data/
8# Checkpoints: https://drive.google.com/drive/folders/1Ej7wdtlqT5P-SoUf3gsZXD8b78XqhiI5
9# 放到 data/ckpt/
10
11# 3. build image(會解 conda env,需 10–15 min)
12docker build -t gencad:latest .
13
14# 4. 訓練 CSR
15docker run --gpus all -it gencad:latest \
16 conda run -n gencad_env python train_gencad.py csr -name test -gpu 0
17
18# 5. 推論(含 xvfb headless 渲染)
19docker run --gpus all \
20 -v $(pwd)/data/images:/app/data/images \
21 -v $(pwd)/assets:/app/assets \
22 -v $(pwd)/results:/app/results \
23 -it gencad:latest /bin/bash
24
25# 容器內:
26xvfb-run --server-args="-screen 0 2048x2048x24" \
27 python inference_gencad.py -image_path data/images -export_img -export_stl
2.3 方案 B — conda + pip(手動)
1# 1. 建立 env
2conda create -n gencad_env python=3.10 -y
3conda activate gencad_env
4
5# 2. pythonocc-core 只能用 conda 裝(pip 沒有)
6conda install -c conda-forge pythonocc-core=7.9.0
7
8# 3. 其他依賴用 pip
9pip install -r requirements.txt
10# 內容:torch torchvision transformers opencv-python scikit-learn x_clip
11# ema_pytorch tensorboardX tensorboard einops h5py plyfile trimesh
12
13# 4. headless 視覺化需額外裝 xvfb
14sudo apt-get install -y xvfb libgl1 libxrender1 libsm6 libxext6 mesa-utils
2.4 安裝流程圖
flowchart TD
A[Clone repo] --> B{選擇方案}
B -->|Docker| C[build gencad:latest
~10–15 min]
B -->|conda + pip| D[conda env + pythonocc-core]
D --> E[pip install -r requirements.txt]
E --> F[apt install xvfb 等 OpenGL libs]
C --> G[Download dataset + checkpoint
從 Google Drive]
F --> G
G --> H{用途}
H -->|訓練| I[python train_gencad.py csr/ccip/dp]
H -->|推論| J[xvfb-run python inference_gencad.py]
2.5 常見安裝問題
| 問題 | 解法 |
|---|---|
ModuleNotFoundError: No module named 'OCC' | 沒裝 pythonocc-core。pip 裝不了,必須 conda install -c conda-forge pythonocc-core=7.9.0 |
libtiff.so.6: undefined symbol jpeg12_write_raw_data | conda env 內 libjpeg / libtiff 版本衝突。重建 env 或 conda update --all |
RuntimeError: Found no NVIDIA driver | 容器內沒掛 GPU。Docker 需 --gpus all 旗標 |
torch.OutOfMemoryError: CUDA out of memory | 改小 ConfigAE 內 batch_size,預設 = 2 已經很小 |
3. 核心架構解析
3.1 三段式 pipeline 總覽
flowchart LR
subgraph Stage1["Stage 1: CSR Autoencoder (CAD-only)"]
A1[CAD command sequence
例如 sketch→extrude] --> A2[Transformer Encoder]
A2 --> A3[Latent z_cad
256-d]
A3 --> A4[Transformer Decoder]
A4 --> A5[Reconstructed CAD seq]
end
subgraph Stage2["Stage 2: CCIP (Image–CAD alignment)"]
B1[Sketch / Image] --> B2[ResNet/ViT Image Encoder]
A3 -.-> B3[Pretrained CSR Encoder
frozen]
B2 --> B4[InfoNCE / CLIP loss]
B3 --> B4
B4 --> B5[Aligned image embedding]
end
subgraph Stage3["Stage 3: Diffusion Prior (DP)"]
C1[Image embed] --> C2[ResNet1D Denoiser]
C2 --> C3[GaussianDiffusion1D
EMA + auto_normalize]
C3 --> C4[Sampled z_cad]
end
subgraph Inference["Inference"]
D1[Test image] --> D2[CCIP image encoder] --> D3[DP sampler]
D3 --> D4[CSR decoder]
D4 --> D5[CAD vec → vec2CADsolid → STL]
end
3.2 各模型檔詳細解析
| 檔案 | 大小 | 角色 | 關鍵類別 |
|---|---|---|---|
model/autoencoder.py | 8.3KB | CSR Transformer autoencoder | VanillaCADTransformer |
model/ccip_model.py | 18KB | CLIP-style 對比學習,含 CLOOB / DCL 損失 | CLIP, GenCADClipAdapter |
model/image_encoder.py | 11.5KB | ResNet 影像編碼器 | ResNetImageEncoder |
model/image_encoder_vit.py | 4.2KB | 備用 ViT 影像編碼器 | ViT |
model/cond_ldm.py | 20.7KB | 1D 條件 Latent Diffusion | GaussianDiffusion1D |
model/denoising_net.py | 14.8KB | ResNet1D 去噪網路 (借用 Yura52/rtdl) | ResNetDiffusion |
model/mlp_prior.py | 14.1KB | MLP-based prior(備選方案) | (相關類別) |
3.3 三個 Config 對應三段訓練
| Config | 對應 | 主要參數 |
|---|---|---|
ConfigAE (configAE.py 5.8KB) | CSR autoencoder | batch_size=2, lr=1e-3, num_epochs=10, warmup_step=2000, num_workers=12 |
ConfigCCIP (configCCIP.py 3.5KB) | image–CAD 對齊 | (見檔內 batch / lr 等) |
ConfigDP (configDP.py 3.2KB) | Diffusion Prior | timesteps, objective, ema_decay, auto_normalize |
每個 config 都有
__init__自動建exp_dir並提示「Overwrite? (y/n)」— 訓練時若想自動化,需手動改overwrite=True。
3.4 CAD command DSL (cadlib/)
借用自 DeepCAD,定義了 CAD 命令的低階表示:
| 檔案 | 用途 |
|---|---|
cadlib/macro.py | 常數定義:EXT_IDX, LINE_IDX, ARC_IDX, CIRCLE_IDX, EOS_IDX, MAX_TOTAL_LEN=60, N_ARGS=17 等 |
cadlib/sketch.py | Sketch 級結構(line / arc / circle 組成 loop) |
cadlib/extrude.py | Extrude 操作(sketch → 3D solid) |
cadlib/curves.py | 曲線基元(419 行) |
cadlib/visualize.py | vec2CADsolid — CAD vec → OCC TopoDS_Shape |
每筆 CAD command vector 是 (60, 17) 的 int 矩陣:60 步序列、17 維 (1 維 command type + 16 維 args,部分用 -1 padding)。
3.5 推論流程 (inference_gencad.py:280 行)
sequenceDiagram
participant U as User
participant I as inference_gencad.py
participant CLIP as GenCADClipAdapter
participant DP as GaussianDiffusion1D
participant DEC as CSR Decoder
participant OCC as OpenCascade
U->>I: -image_path data/images -export_stl
loop 每張圖
I->>CLIP: embed_image(img)
CLIP-->>I: image_embed
I->>DP: sample(cond=image_embed)
DP-->>I: latent (1,1,256)
I->>DEC: decoder(z=latent)
DEC-->>I: batch_out_vec (B,60,17)
I->>I: 找 EOS_IDX → 截斷
I->>OCC: vec2CADsolid(cad_vec)
OCC-->>I: TopoDS_Shape
I->>OCC: write_stl_file → .stl
end
4. CLI 詳細用法
4.1 訓練 CSR (Stage 1)
1# 基本
2python train_gencad.py csr -name <exp_name> -gpu 0
3
4# 從 checkpoint 繼續
5python train_gencad.py csr -name <exp_name> -gpu 0 \
6 -ckpt "model/ckpt/ae_ckpt_epoch1000.pth"
| 旗標 | 必填 | 說明 |
|---|---|---|
csr | ✓ | 子命令,固定 |
-name, --exp_name | ✓ | 實驗名稱,會建立 proj_log/<name>/CSR/ |
-gpu, --gpu | (預設 0) | GPU index,不支援多卡 |
-ckpt, --ckpt_path | optional | resume 用的 checkpoint 路徑 |
4.2 訓練 CCIP (Stage 2)
1python train_gencad.py ccip -name <exp_name> -gpu 0 \
2 -cad_ckpt "model/ckpt/ae_ckpt_epoch1000.pth"
-cad_ckpt 必填:CCIP 需要凍結 CSR encoder。
4.3 訓練 DP (Stage 3)
1python train_gencad.py dp -name <exp_name> -gpu 0 \
2 -cad_emb 'data/embeddings/cad_embeddings.h5' \
3 -img_emb 'data/embeddings/sketch_embeddings.h5'
兩個 h5 檔都必填。需先用訓練好的 CSR / CCIP encoder 把全部 CAD seq 和 image 都 forward 過一次、存到 h5。
4.4 推論
1# headless server
2xvfb-run --server-args="-screen 0 2048x2048x24" \
3 python inference_gencad.py \
4 -image_path data/images \
5 -export_img \
6 -export_stl
| 旗標 | 預設 | 說明 |
|---|---|---|
-image_path | (必填) | 輸入影像資料夾,會掃 *.png |
-export_img | False | 輸出生成的 STL 用 OCC 渲染的 PNG |
-export_stl | False | 輸出 .stl 檔 |
推論過程:
load 3 checkpoints (diffusion / clip / cad decoder) → 逐張影像 → save_view → write_stl_file。
4.5 STL 視覺化
1python stl2img.py -src path/to/stl -dst path/to/save/images
5. 應用場景
| 場景 | 是否適用 | 備註 |
|---|---|---|
| 從手繪 sketch 生成可編輯 CAD | ✅ 原生用途 | TMLR 2025 paper 主軸 |
| 從產品照片重建 CAD | ⚠️ 部分 | training data 偏簡單形狀,複雜照片效果未知 |
| 自動化機械零件設計 | ⚠️ 評估中 | 視 dataset 涵蓋範圍 |
| 結構生成 (非 CAD) | ❌ 需大改 | cadlib/ 是 CAD 專用 DSL |
| 作為 sequence-conditional diffusion 框架借鑑 | ✅ 推薦 | DP + CSR 設計可移植到其他結構化序列領域 |
| 教學 / 論文復現 | ✅ 推薦 | Docker 完整、checkpoint 齊全 |
6. 資安掃描報告
掃描日期:2026-05-20 / 範圍:
*.py+model/+trainer/+utils/+config/+cadlib/
6.1 紅黃綠燈總結
| 等級 | 數量 | 摘要 |
|---|---|---|
| 🔴 高風險 | 0 | 無外部 API 呼叫、無 secrets 洩漏、無真 eval/exec |
| 🟡 中風險 | 2 類 | (1) torch.load 大量使用 (11 處) — pickle 反序列化潛在 RCE;(2) cadlib/visualize.py:136 有 os.system + .format 模板 |
| 🟢 低風險 | — | 其餘為 model.eval() 模式切換、URL 註解、相對路徑 makedirs |
6.2 詳細發現
🟡 風險 1:torch.load 大量未指定 weights_only
1# inference_gencad.py:177, 194, 214
2ckpt = torch.load(diffusion_ckpt_path, map_location="cpu")
3clip_checkpoint = torch.load(clip_ckpt_path, map_location='cpu')
4cad_ckpt = torch.load(cad_ckpt_path)
5# trainer/*.py 還有 7 處類似
- 影響:PyTorch < 2.6 預設
weights_only=False,會用pickle反序列化,載入不明來源的 checkpoint 可能執行任意程式碼 - 緩解:(1) 只用官方 Google Drive checkpoint;(2) PyTorch 2.6+ 改用
torch.load(path, weights_only=True)
🟡 風險 2:os.system 帶 .format 模板
1# cadlib/visualize.py:136
2os.system("rm tmp_out_{}.stl".format(name))
- 影響:若
name來自不可信輸入並含 shell metacharacter (例如; rm -rf /),會 command injection - 實務評估:本專案
name通常是內部 ID / 序號,直接外部利用機會低,但仍建議改為os.remove(f"tmp_out_{name}.stl")或shlex.quote
6.3 觀察到的好習慣
- 全部
os.makedirs路徑都是相對路徑或 config-derived,無任意路徑寫入 - 註解中的 URL 皆為學術引用 (
arxiv.org,github.com/...),無實際下載行為 - 無 hardcoded 密鑰 / API key / database URI
- 無
subprocess(shell=True)、無pickle.load、無__import__動態載入
6.4 結論
整體風險:🟡 中等(學術研究使用無問題)。 主要風險集中在「載入第三方 checkpoint」場景。建議:(1) 升 PyTorch ≥ 2.6 並加
weights_only=True;(2) 修visualize.py:136;(3) 不要從不明來源下載.pt檔案。
7. FAQ
Q1: cannot find EOS 是什麼意思?
A: Inference 時 CSR decoder 沒在 MAX_TOTAL_LEN=60 步內生成 EOS_IDX,code 用 try/except 跳過。原因通常是:(1) checkpoint 未訓練到收斂;(2) 輸入影像超出 training distribution;(3) Diffusion sample 不穩定。多跑幾次 inference 或調整 DP 的 sampling steps 通常會緩解。
Q2: 為什麼 GPU 沒被用?
A: train_gencad.py 只支援單 GPU。確認 -gpu 0 有傳、確認 torch.cuda.is_available()、Docker 確認 --gpus all。Issue #16 詳細討論。
Q3: pythonocc-core 為何不能 pip? A: pythonocc-core 是 OpenCascade 的 SWIG-generated binding,依賴 C++ build 與 OCCT 動態庫,conda-forge 預編譯,pip 沒得裝(除非自己 build)。
Q4: 可以換 ViT 嗎?
A: 可以。model/image_encoder_vit.py 已備 ViT 類別,把 train_gencad.py 內 image_encoder = ResNetImageEncoder(...) 換成 image_encoder = ViT(...) 即可,但要確認 output dim 與 CCIP 對齊。
Q5: 訓練要多久?
A: 論文未明示具體 GPU 時數。從 ConfigAE 預設 num_epochs=10 + batch_size=2 推測,CSR 在單 A100 上應在幾天內。完整 3 stage 預估 1–2 週。
Q6: 沒 GPU 可以跑嗎? A: 推論勉強可(CPU 慢數倍);訓練實務上不行。
8. 進階技巧
8.1 替換影像編碼器
- 在
model/加新 encoder class,輸出 dim 與 CCIP latent 對齊(預設 256) train_gencad.py內image_encoder = ...換新類別- 重新訓練 CCIP 與 DP(CSR 不需重訓)
8.2 自製 CAD 資料集
- 收集
.step/.brep檔 - 用 DeepCAD 提供的 JSON schema 轉成 command sequence (
utils/json2vec.py) - 用
utils/cad_dataset.py的CADDataset介面包裝 - CSR 從新資料集 from scratch 或 fine-tune
8.3 加 weights_only=True 補丁
在所有 torch.load(...) 後面加 weights_only=True(PyTorch ≥ 2.6),消除 RCE 風險:
1# repo 內統一改寫
2grep -rln "torch.load(" --include="*.py" \
3 | xargs sed -i 's/torch\.load(\(.*\))/torch.load(\1, weights_only=True)/g'
4# 注意:sed 不會處理已有 weights_only 的;手動驗證
8.4 用 TensorBoard 監控
1tensorboard --logdir proj_log/<exp_name>/CSR/log --port 6006
8.5 多 GPU(需自行改)
原碼用 model.to(device) 而非 DataParallel/DDP。要改:
model = nn.DataParallel(model)(簡單但慢)- 改用
accelerate/torch.distributed完整 DDP
9. 整合進其他工作流
- 可借鑑設計:三段式 (sequence autoencoder + contrastive align + diffusion prior) 可移植到「分子結構 / protein domain / 生化路徑」等結構化序列領域
- 建議讀法:先讀
model/autoencoder.py與model/cond_ldm.py,跳過cadlib/與 OCC 相關
9.2 與本知識庫其他 Layer 配合
| Layer | 用途 |
|---|---|
gh-tutorial-qd (本流程) | 取得本份教學 + qd HTML |
docling | 若要把 paper PDF 轉成 markdown 深度閱讀 |
paper-search | 用 paper read: arxiv:2409.16294 拉本論文與被引清單 |
paper-qa-lite | 用 paper-search 拉的 paper 集做 RAG 問答 |
gitnexus | 把 GenCAD codebase 建符號圖,深入追 VanillaCADTransformer 等類別 |
9.3 衍生 / 後續題目
- Image-to-Molecule:把 CAD command sequence 換成 SMILES / SELFIES,CSR 改成 SMILES Transformer,pipeline 可直接套
- Image-to-Circuit:把 CAD 換成 SPICE netlist 或 Verilog token
- Conditional CAD editing:image + 文字描述 → 微調 CAD,多模態條件擴展
10. 重點摘要 Checklist
- 三段式:CSR (CAD autoencoder) → CCIP (image-CAD CLIP) → DP (diffusion prior)
- 主 entry:
train_gencad.py {csr,ccip,dp}+inference_gencad.py - 依賴最大坑:
pythonocc-core只能 conda 裝 - 推論需
xvfb-run(OCC viewer 需 X server) - CAD 表示是
(60, 17)int 矩陣(60 步序列 × 17 維 command+args) - 資安:🟡 中(torch.load 反序列化 + 1 處 os.system)
- 訓練不支援多 GPU
- Checkpoint / dataset 從 Google Drive 下載(信任邊界)
- 借用大量 DeepCAD 程式碼(
cadlib/、utils/cad_dataset.py)
11. 進一步閱讀
| 資源 | 連結 |
|---|---|
| GenCAD Paper (TMLR 2025) | https://openreview.net/pdf?id=e817c1wEZ6 |
| GenCAD arXiv | https://arxiv.org/abs/2409.16294 |
| GenCAD Project Page | https://gencad.github.io/ |
| DeepCAD (上游) | https://github.com/ChrisWu1997/DeepCAD |
| pythonocc-core | https://github.com/tpaviot/pythonocc-core |
| x_clip (CLIP impl 借用) | https://github.com/lucidrains/x-clip |
| ema_pytorch (EMA 工具) | https://github.com/lucidrains/ema-pytorch |
| rtdl (denoising net 借用) | https://github.com/Yura52/rtdl |
| GaussianDiffusion1D (架構靈感) | https://github.com/lucidrains/denoising-diffusion-pytorch |
| Issue tracker | https://github.com/ferdous-alam/GenCAD/issues |
本教學由
gh-tutorial-qdskill 自動生成 / 2026-05-20 / commitf5484cf。 若有錯誤或更新,請更新inbox/2026-05-20-tutorial-GenCAD.md並重編 qd / HTML。
Comments