DenseDiffusion 完整教學

Repository: https://github.com/naver-ai/DenseDiffusion Stars: 507 | Forks: 35 | License: Apache-2.0 Tags: diffusion, dense-control, ICCV 論文: Dense Text-to-Image Generation with Attention Modulation (ICCV 2023) 作者: Yunji Kim, Jiyoung Lee, Jin-Hwa Kim, Jung-Woo Ha (NAVER AI Lab), Jun-Yan Zhu (CMU)

2. 核心架構

2.1 系統架構圖


graph TD
    A["使用者輸入"] --> B["Layout Masks
空間佈局遮罩"] A --> C["Segment Prompts
區段文字描述"] A --> D["Master Prompt
全局文字描述"] B --> E["Mask Preprocessing
遮罩前處理"] C --> F["CLIP Tokenizer
文字分詞"] D --> F F --> G["CLIP Text Encoder
文字編碼器"] G --> H["Text Embeddings
文字嵌入"] E --> I["Self-Attention Reg Maps
自注意力調控圖"] E --> J["Cross-Attention Reg Maps
交叉注意力調控圖"] E --> K["Size Reg Maps
面積調控圖"] H --> L["Modified UNet Forward
修改後的 UNet 前向傳播"] I --> L J --> L K --> L L --> M["DDIM Scheduler
DDIM 排程器"] M --> N["Generated Image
生成影像"] style A fill:#e1f5fe style L fill:#fff3e0 style N fill:#e8f5e9

2.2 注意力調變機制

DenseDiffusion 的核心是 mod_forward 函式,它替換了 UNet 中所有 Attention 層的 __call__ 方法。調變邏輯如下:

Cross-Attention 調變 (creg):控制文字 token 與空間位置的對應關係。對於每個文字 token,根據其所屬 segment 的 mask 強化對應區域的 attention score,同時抑制非對應區域。

Self-Attention 調變 (sreg):控制空間位置之間的相互影響。同一 segment 內的 pixel 之間的 attention 被強化,不同 segment 之間的 attention 被抑制,確保各區域的視覺特徵保持獨立。

時間步衰減函式

1treg = (timestep / 1000)^5

前 30% 的 diffusion 步驟進行調變(COUNT/32 < 50*0.3),之後關閉調變讓模型自由生成細節。這個設計確保佈局在早期步驟被固定,後期專注於高頻細節。

2.3 資料流程


sequenceDiagram
    participant U as 使用者
    participant P as Preprocessor
    participant T as Text Encoder
    participant UN as UNet (Modified)
    participant S as DDIM Scheduler

    U->>P: Layout masks + segment prompts
    P->>P: 建立 binary masks (每個 segment)
    P->>P: 多解析度插值 (64x64, 32x32, 16x16, 8x8)
    P->>T: 全局 prompt + 各 segment prompt
    T->>T: Token 對齊:segment prompt tokens 對應到 master prompt 中的位置
    T-->>UN: cond_embeddings (條件嵌入)

    loop 每個 timestep (共 50 步)
        S->>UN: noisy latent
        Note over UN: 前 15 步 (30%):啟用注意力調變
        UN->>UN: Cross-Attn: token-region 對齊
        UN->>UN: Self-Attn: region 內聚合
        UN->>UN: Size regularization
        UN-->>S: predicted noise
        S->>S: DDIM denoise step
    end

    S-->>U: 生成影像

2.4 關鍵超參數

參數符號預設值作用
Cross-attention weightw^c (creg)1.0文字-區域對齊強度,越高則物件越嚴格限制在指定區域
Self-attention weightw^s (sreg)0.3區域間隔離程度,越高則不同區域的視覺特徵越獨立
Size regularizationsizereg1.0面積自適應調整強度,防止大區域主導小區域
Timestep threshold30%15/50 步前 30% 步驟做調變,後 70% 自由生成
Max segmentsMAX_COLORS12最多支援 12 個獨立區域

3. 安裝與設定

3.1 環境需求

  • Python 3.8+
  • CUDA-capable GPU(建議 VRAM >= 8 GB,Stable Diffusion v1.5 基底)
  • Hugging Face 帳號與 access token(用於下載 SD v1.5 權重)

3.2 安裝步驟

 1# 1. 建立虛擬環境(使用 uv,符合 AIKT 規範)
 2uv venv .venv --python 3.10
 3source .venv/bin/activate
 4
 5# 2. Clone repository
 6git clone https://github.com/naver-ai/DenseDiffusion.git
 7cd DenseDiffusion
 8
 9# 3. 安裝依賴(注意版本鎖定)
10uv pip install -r requirements.txt
11
12# requirements.txt 內容:
13# diffusers==0.20.2
14# transformers==4.28.0
15# gradio==3.43.2
16# accelerate

版本警告:程式碼在啟動時會檢查 diffusers.__version__ != '0.20.2' 並強制退出。這是因為 mod_forward 函式直接 monkey-patch UNet 的 Attention 層內部 API,不同版本的 diffusers 會改變此 API。若需升級,必須對照新版 diffusers 的 Attention.__call__ 簽名重寫 mod_forward

3.3 設定 Hugging Face Token

1# 方式一:環境變數
2export HF_TOKEN="hf_xxxxxxxxxxxxxxxxxxxxxxxx"
3
4# 方式二:修改 gradio_app.py 第 77 行
5# HF_TOKEN = 'hf_xxxxxxxxxxxxxxxxxxxxxxxx'
6
7# 方式三:huggingface-cli 登入(推薦)
8huggingface-cli login

3.4 啟動 Gradio 介面

1python gradio_app.py
2# 預設啟動於 http://0.0.0.0:7860

3.5 常見安裝問題

問題原因解決方案
Please use diffusers v0.20.2版本不符uv pip install diffusers==0.20.2
CUDA out of memoryVRAM 不足使用 variant="fp16" (已預設) 或降低 batch size
模型下載失敗HF Token 未設定執行 huggingface-cli login
Gradio 介面無法連線防火牆或 port 衝突--share 參數或改 port

4. 使用方式與程式碼範例

4.1 範例一:Gradio 互動式介面

Gradio 介面提供完整的四步驟工作流:

 1# gradio_app.py 已包含完整流程,直接啟動即可
 2# python gradio_app.py
 3
 4# 四步驟操作流程:
 5# Step 1: 在 canvas 上用不同顏色繪製佈局
 6# Step 2: 為每個顏色區段(segment)輸入文字描述
 7# Step 3: 調整全局描述文字(預設為各 segment 文字的串接)
 8# Step 4: 調整超參數並生成
 9
10# 超參數建議:
11# - w^c (creg) = 1.0:標準文字-區域對齊
12# - w^s (sreg) = 0.3:適度的區域隔離
13# - sizereg = 1.0:完全啟用面積自適應

4.2 範例二:程式化批次生成(生醫影像應用)

以下範例展示如何將 DenseDiffusion 用於程式化的批次生成,適合生醫影像合成場景:

 1"""
 2DenseDiffusion 程式化批次生成範例
 3適用場景:批次合成具有指定組織佈局的病理影像
 4"""
 5import torch
 6import numpy as np
 7from PIL import Image
 8import torch.nn.functional as F
 9import diffusers
10from diffusers import DDIMScheduler
11
12# ---- 載入模型 ----
13device = "cuda"
14pipe = diffusers.StableDiffusionPipeline.from_pretrained(
15    "runwayml/stable-diffusion-v1-5",
16    variant="fp16",
17    torch_dtype=torch.float16,
18).to(device)
19pipe.scheduler = DDIMScheduler.from_config(pipe.scheduler.config)
20pipe.scheduler.set_timesteps(50)
21sp_sz = pipe.unet.sample_size  # 通常為 64
22
23# ---- 定義佈局與描述 ----
24# 模擬一個簡化的組織佈局:
25#   - 背景(白色): 正常組織
26#   - 區域 1(左半): 染色較深的區域
27#   - 區域 2(右半): 染色較淺的區域
28
29def create_rectangular_masks(h, w):
30    """建立簡易矩形佈局遮罩"""
31    bg_mask = np.ones((h, w), dtype=np.float32)
32    region1 = np.zeros((h, w), dtype=np.float32)
33    region2 = np.zeros((h, w), dtype=np.float32)
34
35    # 左半部分為區域 1
36    region1[:, :w//2] = 1.0
37    # 右半部分為區域 2
38    region2[:, w//2:] = 1.0
39    # 背景為兩個區域的補集
40    bg_mask = 1.0 - np.clip(region1 + region2, 0, 1)
41
42    return [bg_mask, region1, region2]
43
44masks = create_rectangular_masks(512, 512)
45prompts = [
46    "a high resolution microscopy image of tissue",   # master prompt
47    "background with uniform pink staining",           # bg segment
48    "densely packed dark purple nuclei cluster",        # region 1
49    "sparse pale eosinophilic cytoplasm region",        # region 2
50]
51
52# ---- 前處理遮罩 ----
53def preprocess_mask(mask_np, h, w, dev):
54    mask = torch.from_numpy(mask_np).float().unsqueeze(0).unsqueeze(0).to(dev)
55    mask = F.interpolate(mask, size=(h, w), mode='nearest')
56    return mask
57
58layouts = torch.cat([
59    preprocess_mask(m, sp_sz, sp_sz, device) for m in masks
60])
61
62# ---- 建立調控圖 (與 gradio_app.py 邏輯一致) ----
63sreg_maps = {}
64reg_sizes = {}
65sizereg_val = 1.0
66
67for r in range(4):
68    res = int(sp_sz / np.power(2, r))
69    layouts_s = F.interpolate(layouts, (res, res), mode='nearest')
70    layouts_s = (
71        layouts_s.view(layouts_s.size(0), 1, -1)
72        * layouts_s.view(layouts_s.size(0), -1, 1)
73    ).sum(0).unsqueeze(0)
74    reg_sizes[int(np.power(res, 2))] = (
75        1 - sizereg_val * layouts_s.sum(-1, keepdim=True) / np.power(res, 2)
76    )
77    sreg_maps[int(np.power(res, 2))] = layouts_s
78
79print(f"已建立 {len(sreg_maps)} 個解析度的 self-attention 調控圖")
80print(f"解析度: {list(sreg_maps.keys())}")
81# 輸出: 解析度: [4096, 1024, 256, 64]

4.3 範例三:評估佈局精確度 (IoU 計算)

DenseDiffusion 提供了評估生成影像佈局精確度的工具,使用 cross-attention map 與目標 mask 之間的 IoU(Intersection over Union; 交集比聯集):

 1"""
 2評估生成影像的佈局精確度
 3對應 repo 中的 eval_iou.ipynb
 4"""
 5import torch
 6import numpy as np
 7
 8def compute_layout_iou(attention_maps: dict, target_masks: list,
 9                       resolution: int = 64) -> dict:
10    """
11    計算 cross-attention map 與目標 layout mask 之間的 IoU
12
13    Parameters
14    ----------
15    attention_maps : dict
16        從 UNet 中間層提取的 cross-attention maps
17        key = spatial_resolution^2, value = tensor [B, H*W, 77]
18    target_masks : list[np.ndarray]
19        每個 segment 的目標 binary mask
20    resolution : int
21        評估的空間解析度
22
23    Returns
24    -------
25    dict
26        包含每個 segment 的 IoU 分數與整體平均
27    """
28    results = {}
29    ious = []
30
31    for seg_idx, mask in enumerate(target_masks):
32        # 將目標 mask resize 到評估解析度
33        mask_tensor = torch.from_numpy(mask).float().unsqueeze(0).unsqueeze(0)
34        mask_resized = torch.nn.functional.interpolate(
35            mask_tensor, size=(resolution, resolution), mode='nearest'
36        ).squeeze().flatten()
37
38        # 從 attention map 提取對應 token 的空間分佈
39        attn_key = resolution * resolution
40        if attn_key in attention_maps:
41            attn = attention_maps[attn_key]  # [B, H*W, 77]
42            # 取該 segment 對應 token 範圍的最大 attention
43            seg_attn = attn[0, :, seg_idx].detach().cpu()
44
45            # 二值化 attention map (Otsu threshold 或簡單閾值)
46            threshold = seg_attn.mean()
47            attn_binary = (seg_attn > threshold).float()
48
49            # 計算 IoU
50            intersection = (attn_binary * mask_resized).sum()
51            union = ((attn_binary + mask_resized) > 0).float().sum()
52            iou = (intersection / (union + 1e-8)).item()
53
54            results[f"segment_{seg_idx}"] = {
55                "iou": round(iou, 4),
56                "mask_coverage": round(mask_resized.sum().item()
57                                       / mask_resized.numel(), 4),
58            }
59            ious.append(iou)
60
61    results["mean_iou"] = round(np.mean(ious), 4) if ious else 0.0
62    return results
63
64# 使用範例
65# target_masks = [bg_mask, tumor_mask, stroma_mask]
66# iou_results = compute_layout_iou(attention_maps, target_masks)
67# print(f"平均 IoU: {iou_results['mean_iou']}")

5. 在生醫影像合成生態系中的定位

5.1 Domain 2-D 子領域定位

DenseDiffusion 屬於 Domain 2-D: Diffusion Models for Medical Images 子領域,與 conditional_DDPM、SD-Messenger 並列。其獨特定位在於:


graph LR
    subgraph "Domain 2-D: Diffusion for Medical Images"
        A["conditional_DDPM
條件式 DDPM
需要訓練"] --> D["生醫影像合成"] B["DenseDiffusion
免訓練注意力調變
空間佈局控制"] --> D C["SD-Messenger
跨模態訊息傳遞
模態轉換"] --> D end subgraph "上游基礎設施" E["MONAI GenerativeModels
醫學生成模型框架"] F["Stable Diffusion v1.5
預訓練基底"] end subgraph "下游應用" G["VICTRE
虛擬臨床試驗"] H["medigan
統一合成 API"] I["foundation-cancer
癌症影像 biomarker"] end F --> B E --> A D --> G D --> H D --> I style B fill:#fff3e0,stroke:#ff9800

5.2 與同領域工具的比較

特性DenseDiffusionconditional_DDPMSD-MessengerControlNet
需要訓練否 (Training-free)
空間佈局控制強 (多區域)弱 (全域條件)強 (邊緣/深度)
基底模型SD v1.5自建 DDPMSD 系列SD 系列
多區域描述最多 12 區域不支援不支援不直接支援
醫學影像特化需 domain adaptation可直接訓練可直接訓練需 fine-tune
推論速度快 (僅修改 attention)標準標準略慢

5.3 Blue Ocean 分析:DenseDiffusion 在生醫的獨特機會

  1. 病理切片佈局合成:傳統方法只能控制「有無腫瘤」,DenseDiffusion 可以控制「腫瘤在左上角、基質在中央、淋巴浸潤在邊緣」的精確佈局
  2. 多器官 CT 合成:一張 CT 切片中有肝臟、腎臟、脾臟等多器官,每個器官需要獨立的外觀描述
  3. 藥物反應視覺化:模擬藥物治療前後的組織變化,控制不同區域的反應程度
  4. 稀有表型資料增強:透過精確的空間控制,合成臨床上罕見但具有特定空間特徵的病例

6. 與其他工具的整合

6.1 與 MONAI GenerativeModels 整合

 1# 概念流程:使用 MONAI 的 segmentation 輸出作為 DenseDiffusion 的佈局輸入
 2
 3# Step 1: MONAI 語義分割 → 產出多類別 mask
 4# Step 2: 將 MONAI mask 轉換為 DenseDiffusion 的 binary_matrixes 格式
 5# Step 3: 為每個類別撰寫描述性 prompt
 6# Step 4: 使用 DenseDiffusion 生成合成影像
 7
 8def monai_masks_to_dense_layout(segmentation_output, class_names):
 9    """
10    將 MONAI segmentation 輸出轉換為 DenseDiffusion 格式
11
12    Parameters
13    ----------
14    segmentation_output : np.ndarray
15        shape (H, W),每個 pixel 的值代表類別 index
16    class_names : list[str]
17        每個類別的文字描述
18
19    Returns
20    -------
21    binary_matrixes : list[np.ndarray]
22        每個類別的 binary mask
23    prompts : list[str]
24        segment 描述列表
25    """
26    binary_matrixes = []
27    prompts = []
28
29    unique_classes = np.unique(segmentation_output)
30    for cls_idx in unique_classes:
31        mask = (segmentation_output == cls_idx).astype(np.float32)
32        binary_matrixes.append(mask)
33        if cls_idx < len(class_names):
34            prompts.append(class_names[cls_idx])
35
36    return binary_matrixes, prompts

6.2 與 medigan 整合

medigan 提供統一的生成模型 API。DenseDiffusion 可作為 medigan 的 backend generator(後端生成器)之一:

 1# 概念整合:將 DenseDiffusion 包裝為 medigan 相容的 generator
 2
 3# medigan 標準介面
 4# generators.generate(model_id="dense_diffusion_pathology",
 5#                     layout=layout_masks,
 6#                     prompts=segment_prompts)
 7
 8# DenseDiffusion 提供的獨特功能:
 9# - 佈局導向的條件生成(其他 medigan generator 通常不支援)
10# - 免訓練,可快速適配新的描述詞彙
11# - 透過 prompt engineering 適配不同的醫學影像 domain

6.3 與 AIKT Pipeline 整合

在 AI-Knowledge Template 流程中的定位:

AIKT Layer整合方式
Layer 9 (paper-search)搜尋 DenseDiffusion 後續應用論文,追蹤醫學影像 attention modulation 研究
Layer 10 (paper-qa-lite)對 DenseDiffusion 論文做 RAG 問答,深入理解技術細節
Layer 12 (gh-tutorial-qd)本教學即為 gh-tutorial-qd 的產物
Layer 15 (paper-tutorial)將 DenseDiffusion 論文與相關醫學應用論文做整合教學
Layer 18 (research-pipeline)在 pre-IND 研究管線中,用 DenseDiffusion 合成影像 biomarker 訓練資料
Layer 19 (tu-plan-generator)ToolUniverse 可查詢 DenseDiffusion 相關的 imaging biomarker 標準

6.4 與 VICTRE 虛擬臨床試驗整合

DenseDiffusion 可為 VICTRE 虛擬臨床試驗提供更多樣化的合成影像:

  • VICTRE 產出 phantom → DenseDiffusion 將 phantom segmentation 作為佈局輸入
  • 為不同組織區域指定真實的影像外觀描述
  • 產出多樣化的合成影像供虛擬 reader study 使用

7. 優缺點分析

7.1 優點

面向說明
免訓練不需任何額外訓練資料或 GPU 訓練時間,大幅降低進入門檻
精確空間控制最多 12 個獨立區域,每個區域可有獨立的文字描述
輕量級僅修改 attention forward pass,不增加模型參數
程式碼簡潔核心邏輯集中在 gradio_app.pyutils.py 兩個檔案,約 400 行
可組合性基於 Stable Diffusion 生態系,可與 ControlNet、IP-Adapter 等技術疊加
即時互動Gradio 介面支援即時繪製佈局、即時調整參數
Apache-2.0 授權商業友善的開源授權

7.2 缺點與限制

面向說明影響程度
版本鎖定嚴格綁定 diffusers==0.20.2,無法使用最新版 diffusers 的功能與效能改進
Monkey-patch 架構直接替換 Attention __call__,與其他 attention 修改技術(如 xFormers, Flash Attention)衝突
自然影像基底基於 SD v1.5 預訓練權重,醫學影像需要 domain-specific fine-tuning 才能獲得真實的組織外觀
2D 限制僅支援 2D 影像生成,無法直接處理 3D volumetric(體積)醫學影像
無定量醫學驗證論文評估以自然影像為主,缺乏 FID/IS 等醫學影像生成品質指標
全域變數架構sreg_mapscreg_maps 等使用全域變數,不支援並行推論
區域上限 12複雜的醫學影像(如全景病理切片)可能需要更多區域

7.3 生醫應用的實際建議

  1. 短期可行:使用 DenseDiffusion 做概念驗證(PoC),驗證「佈局引導的醫學影像合成」是否在目標任務上有價值
  2. 中期投入:將 SD v1.5 替換為醫學影像 fine-tuned 的 diffusion model(如 RoentGen、MedDiffusion),保留 DenseDiffusion 的 attention modulation 邏輯
  3. 長期方向:考慮 3D 擴展(將 2D attention modulation 推廣到 3D UNet),或整合 SDXL/SD3 的更新架構

7.4 與 GAN 方法的比較(生醫脈絡)

面向DenseDiffusion (Diffusion)Patho-GAN 等 (GAN)
影像品質高,但依賴預訓練基底的 domain 適配度可直接在目標 domain 訓練,品質穩定
多樣性高,每次推論可產出不同變化受 mode collapse 風險
空間控制強(本專案核心優勢)通常依賴條件 GAN 架構,靈活度較低
訓練成本免訓練(但可能需要 fine-tune 基底)需從頭訓練或 fine-tune
推論速度較慢(50 步 DDIM)單步前向傳播,極快
隱私保護可透過 prompt-only 控制生成,不直接接觸真實資料訓練時必須接觸真實資料

附錄:檔案結構

 1DenseDiffusion/
 2├── gradio_app.py          # 主程式:Gradio 介面 + UNet attention monkey-patch
 3├── utils.py               # 工具函式:mask 前處理、sketch/prompt 處理
 4├── inference.ipynb         # 推論範例 Notebook
 5├── eval_iou.ipynb          # IoU 評估 Notebook
 6├── requirements.txt        # 依賴鎖定(diffusers==0.20.2)
 7├── dataset/
 8│   ├── valset.pkl          # 驗證集 prompt metadata
 9│   ├── valset_layout.tar.gz   # 驗證集佈局影像
10│   ├── testset.pkl         # 測試集 prompt metadata
11│   ├── testset_instances.pkl  # 測試集 instance metadata
12│   └── testset_layout.tar.gz  # 測試集佈局影像
13├── figures/                # README 用的說明圖
14├── LICENSE                 # Apache-2.0
15└── NOTICE                  # 第三方授權聲明