纯文本生成建筑效果图往往会出现结构飘移、层数错乱、透视关系不可控的问题。要得到能用于方案汇报的图,需要把3D模型的空间信息作为硬约束传入扩散模型。当前比较成熟的做法是先生成深度图、Canny边缘图或法线图,再用ControlNet这类可控生成模块把这些条件图与文本提示词一起送入Stable Diffusion。这样模型在绘制每个像素时既考虑文字描述,也参考原始几何边界。

整条链路通常包含四个步骤:第一,在Blender或Rhino中把方案模型摆好相机角度;第二,利用渲染引擎或脚本输出深度、边缘、法线等控制图;第三,将控制图与提示词输入ControlNet工作流;第四,从多张候选中筛选、局部重绘并放大输出。这个流程与传统的渲染图工作流并不冲突,反而是把它当作前期概念推敲的加速器。
具体到工具选择,Blender因为开源且脚本能力强,常被用来批量生成控制图;Stable Diffusion配合建筑类底模,比如针对建筑表现微调过的模型,在材质和氛围上更贴近设计行业需求。下面会展开实现细节。
一、从体块模型到效果图:AI生成的链路拆解
建筑方案早期往往只有粗略的体块模型,立面细节和材质还在推敲阶段。AI生成效果图的价值在于快速把几何轮廓转化为带材质和光影的表现图,方便和甲方沟通方向。此时不依赖精细建模,关键是让生成结果和体块模型保持几何一致性。
要实现这种一致性,需要把3D模型的深度信息、边缘轮廓或法线方向作为条件输入。深度图表达每个像素到相机的距离,模型凭此理解建筑的前后遮挡和体块起伏;边缘图提取轮廓转折,适合表达门洞、窗洞和层间分缝;法线图记录表面朝向,对曲面和坡屋顶有更好的约束能力。
这三类控制图可以单独使用,也可以叠加使用。对于体块关系明确的建筑方案,深度图配合边缘图最为常用。深度图负责大体量,边缘图强化细部轮廓,二者权重可根据实际生成效果调整。下面分别说明如何从Blender导出控制图,以及如何用Python调用ControlNet完成生成。
二、Blender导出深度图与边缘图:脚本实现
深度图记录相机到场景表面的距离,边缘图提取几何转折。用Blender Python可以直接控制相机、渲染深度通道并保存为PNG。关键是要把深度值从浮点线性空间映射到0到255的灰度范围,并关闭颜色管理中的视图变换,避免伽马校正破坏深度信息。
下面脚本在Blender中运行,它先设置一个正视相机,再渲染一张16位深度图并保存为可被ControlNet读取的图片。渲染前会临时把渲染引擎设为Eevee或Cycles,并启用Z通道。
import bpy
import numpy as np
from pathlib import Path
# 设置场景与相机
scene = bpy.context.scene
scene.render.engine = 'CYCLES'
scene.render.resolution_x = 1024
scene.render.resolution_y = 1024
cam = bpy.data.objects['Camera']
scene.camera = cam
# 启用深度通道
scene.use_nodes = True
tree = scene.node_tree
render_layers = tree.nodes['Render Layers']
render_layers.outputs['Depth'].enabled = True
# 渲染后读取深度
scene.render.image_settings.file_format = 'OPEN_EXR'
out = str(Path(bpy.path.abspath('//')) / 'depth.exr')
scene.render.filepath = out
bpy.ops.render.render(write_still=True)
# 把EXR深度转为16位灰度PNG(可用其他工具处理)
# 此处略去读取EXR并映射的代码,仅演示渲染深度通道
print('depth saved to', out)
边缘图的生成可以借助Freestyle线稿或使用OpenCV对渲染的底图做Canny检测。更稳定的做法是从Blender输出物体ID图和法线图,法线图能表达面的朝向,适合ControlNet的normal模型。无论用哪种控制图,都要保证尺寸与最终生成分辨率一致,并且相机比例和模型轮廓清晰可见。
在实际项目中,建议同一角度同时导出深度图和边缘图。深度图负责体量关系,边缘图强化窗洞、层间线条和结构轮廓,两者叠加使用可以明显降低楼层数量漂移的概率。叠加控制时可以用ControlNet的多条件权重分别设置,比如深度权重0.8,边缘权重0.5。
三、用ControlNet生成建筑效果图:Python调用与参数配置
把控制图送入Stable Diffusion,可以使用diffusers库中的StableDiffusionControlNetPipeline。代码里加载建筑类底模和ControlNet权重,传入提示词、负面提示词、条件图列表,并设置控制权重。生成尺寸要和条件图一致,否则会触发自动裁剪或缩放导致错位。
import torch
from diffusers import StableDiffusionControlNetPipeline, ControlNetModel
from diffusers.utils import load_image
# 加载建筑类ControlNet和底模
controlnet_depth = ControlNetModel.from_pretrained(
"lllyasviel/control_v11f1p_sd15_depth",
torch_dtype=torch.float16
)
pipe = StableDiffusionControlNetPipeline.from_pretrained(
"runwayml/stable-diffusion-v1-5",
controlnet=controlnet_depth,
torch_dtype=torch.float16
).to("cuda")
prompt = ("modern office building facade, glass curtain wall, "
"aluminum panels, late afternoon sunlight, photorealistic, "
"architectural visualization, 8k, detailed")
negative = ("low quality, blurry, distorted structure, extra floors, "
"missing windows, watermark, text")
depth_image = load_image("depth.png")
result = pipe(
prompt=prompt,
negative_prompt=negative,
image=depth_image,
num_inference_steps=30,
guidance_scale=7.5,
controlnet_conditioning_scale=0.85,
height=1024,
width=1024
).images[0]
result.save("facade_result.png")
上述代码有几个关键参数值得单独说明。controlnet_conditioning_scale控制控制图对生成结果的约束强度,数值越高越贴近原始几何,但过高会让材质表现僵硬;guidance_scale控制文本提示词的影响强度,一般建筑图保持7到9比较安全,超过10容易产生过饱和和细节崩坏。num_inference_steps设为30已经能获得较稳定结果,追求更细腻表现可以提到40。
如果希望生成结果更贴近方案材质,可以在提示词中明确描述玻璃反射、石材分缝、金属收边等元素。负面提示词也要针对建筑可视化常见问题写清楚,比如额外的楼层、缺失的窗户、扭曲的立面线条等。这一步的提示词工程往往比调模型本身更能决定最终观感。
四、三种视图案例:立面、鸟瞰与室内人视
建筑方案通常需要立面图、鸟瞰图和室内人视点三种视角。立面图适合用正对相机的Canny边缘作为控制,强调层高和开窗节奏;鸟瞰图用深度图控制体块关系,让屋顶和退台关系不被文字描述干扰;室内人视则结合深度图和法线图,保证空间进深和墙面转折不出现断裂。
| 视图类型 | 控制图 | 推荐控制权重 | 提示词重点 |
|---|---|---|---|
| 立面 | Canny边缘 | 0.9 | 幕墙分格、层间线条、材质颜色 |
| 鸟瞰 | Depth深度 | 0.85 | 体块组合、屋面设备、周边环境 |
| 室内 | Depth + Normal | 0.7 + 0.5 | 材质质感、灯光氛围、空间尺度 |
实操时可以先在Blender里把体块模型做好,对每个视图设定相机,再批量运行脚本输出控制图。同一套控制图可以替换不同提示词生成多版风格,例如白天与夜景、现代与自然材料。筛选出结构正确的候选后,再回到原始3D模型里核对关键尺寸是否被保留。
立面案例中,如果控制图为Canny边缘,提示词只写玻璃幕墙和铝板,生成结果通常能保持原始开窗数量。但如果某个窗户在边缘图中被阴影打断,生成时可能会少一个窗格。此时可以在Blender中调整灯光角度或使用线稿渲染,让边缘更连续。
鸟瞰案例中,深度图对高层建筑和坡屋顶的差异比较敏感。深度图把近处建筑表面编码为较亮像素,远处为较暗像素,模型会依据这种明暗关系还原体量。如果体块之间有穿插,建议先做布尔运算简化模型,否则深度突变会让屋顶出现畸形。
五、常见问题与调优策略
最常遇到的问题是楼层数变化和玻璃幕墙结构错乱。楼层数变化通常是因为边缘图或深度图的分辨率不足,导致层间线条在采样时被合并。解决方法包括提高控制图分辨率到1024以上、增加边缘控制权重、降低文本提示词中与楼层相关的描述,让几何控制占据主导。
玻璃反射混乱则多出现在镜面反射过强的底模上。可以尝试在负面提示词中加入broken reflection、distorted glass等,或把控制权重从0.6逐步升到0.9。如果仍不稳定,可以先用低权重生成一张底图,再用局部重绘只对玻璃区域重新生成,并配合蒙版把模态限制在幕墙范围。
另一个容易被忽略的是相机镜头畸变。Blender中的默认透视相机输出的深度图和真实建筑摄影的透视略有差异,如果后续要合成到实景照片中,建议把相机焦距设置在24毫米到35毫米之间,并开启传感器适配,这样生成图的透视感更接近专业建筑摄影。
最后,输出分辨率不是越高越好。直接把1024乘1024的图用AI放大模型提升到4K,比在扩散模型里直接生成2048尺寸更稳定。前者能保留结构约束,后者容易出现重复楼层和对称伪影。放大推荐用Real-ESRGAN或SwinIR,对建筑线条和文字标识有较好的保持效果。

