引言

建筑外立面的安全与完好性直接关系到城市运行安全与居住环境质量。传统的外墙巡检方式往往依赖人工高空作业,不仅效率低、成本高,还存在安全隐患。

本项目《城市建筑外立面缺陷检测与维护系统》以“虚拟无人机巡检”为核心概念,通过三维GIS建模 + 无人机飞行模拟 + AI图像识别构建了一个完整的检测流程,实现了从视角漫游、目标识别到AI检测的全流程闭环。

本项目利用 GeoScene CityEngine 的建模能力,将社区建筑物 ShapeFile 数据导入场景,并通过 CGA 规则文件自动完成立体化贴图建模。在此过程中,借助 report() 机制将 building_id 等关键属性一并导出,实现了建筑物“业务数据+三维可视化”的有机结合,使模型不仅具备较好的视觉表现力,同时保留了后续分析所需的数据支撑。

在社区环境建模中,还绘制了道路、绿植等要素,形成了较高仿真度的社区场景。随后将场景导出为 Scene Layer Package (SLPK),并上传至 GeoScene Server 或 GeoScene Online 发布为服务,从而在 Web 端实现直接加载与交互。

在 Web 前端,基于 ArcGIS JavaScript SDK 加载 SceneLayer 与 SceneView,支持键盘控制场景自由漫游,用户可通过上下左右及 W/S/A/D 键实现沉浸式的无人机低空飞行模拟。在全屏模式下提供更强的沉浸体验,并通过 hitTest 实时检测前方建筑物,返回相关属性与距离信息,为后续外立面拍照与缺陷识别奠定了技术基础。

整体流程图如下:

流程图1

一、社区三维建模与属性保留

通过 GeoScene CityEngine 导入社区建筑的 Shapefile 数据,结合规则文件自动生成带贴图的三维模型。建筑贴图可根据层数、用途自动分配不同纹理。

CityEngine社区建模

CityEngine 默认导出模型时不会保留业务属性。本项目使用 report() 机制在 CGA 文件中导出建筑的 building_id 字段:

1
2
3
4
5
6
7
8
attr building_id = ""

ReportBuildingId_Lot -->
case ReportBuildingId == "Yes":
report("building_id", building_id)
NIL
else:
NIL

随后发布到 GeoScene Server 或 Online 以供前端加载。

二、无人机漫游模拟与建筑识别

1.飞行控制与视角操作

在Web端进行通过ArcGIS Maps SDK for JavaScript加载上述链接的场景到页面上,将场景区域放在一个遥控器手柄的背景窗口中来模拟真实无人机操作的感觉。

操作手柄

SceneView自身已经提供了在场景中实现视角前进后退、转向、升降等操作,但是经过测试,其中位移操作(前进/后退/左移/右移/升高/下降)的速度不均匀,不利于精细化控制。
因此我重写了SceneView.on(“keydown”) 事件,将位移操作重写为每次移动固定距离,并且阻止了前进操作导致的穿墙。利用JS的 requestFullScreen API 将左侧内容区切换为全屏效果,同时放大SceneView区域,隐藏遥控器部分,实现更加沉浸式的效果体验。

操作手柄

2. 目标建筑识别(hitTest机制)

SceneView的 hitTest() 能够检测屏幕上某个像素点对应的三维空间对象,返回相交的第一个要素。这一机制本质上是利用 GPU 的 深度缓冲区 (Depth Buffer) 实现拾取(picking),
通过将屏幕坐标反投影到三维空间,再与模型几何进行求交,返回命中的建筑体。
在本项目中,我们选取屏幕中心点作为检测位置,通过 hitTest 获取前方建筑物的属性信息,实现“目标建筑识别”:

建筑识别

在检测到目标建筑后,按回车键调用 SceneView.takeScreenshot ,对场景的中心正方形区域进行截图,模拟无人机拍照效果,并将照片发送给后端AI服务做检测。

三、AI 外墙缺陷检测模型

为满足建筑外墙缺陷检测的智能化需求,本项目构建了基于深度学习的自动识别模型。共收集 120 张缺陷图像样本,涵盖裂缝、风化、污损、脱落四类常见缺陷,每类各 30 张,并使用 Labelme 工具完成多边形语义分割标注,构建训练数据集。

模型选用 PyTorch 框架下的 DeepLabv3-ResNet50 预训练网络,并结合迁移学习与微调策略,在小样本条件下实现了对多类缺陷的有效建模。通过 20 个 epoch 的训练,验证集损失(val_loss)最终收敛至 0.05 以下,表现出较好的收敛性与泛化能力。

该模型集成至系统流程中,前端由 SceneView 截图模拟无人机拍摄外墙画面并上传至后端,AI 模型完成语义分割推理并返回缺陷类别、区域和面积,前端以高亮方式直观呈现。整体实现了数据采集、标注、模型训练、推理与可视化展示的完整闭环,展示出 AI 与 GIS 三维可视化融合的创新应用价值。

AI检测流程

完整的AI缺陷检测部分包括数据标注、掩膜生成、模型训练与推理服务搭建。若想了解更详细的训练流程、关键代码实现,请参阅后续专题文章

AI外墙缺陷检测模型实现详解 —— 从标注到Flask部署

番外篇:Cesium实现

在 ArcGIS 版本的系统基础上,我尝试使用 CesiumJS 完成一版复刻,实现了相同的无人机漫游与目标识别功能。两种方案在架构上的最大差异在于:Cesium 不直接支持 SceneLayer 属性拾取,因此我采用了视觉模型与逻辑模型分离的策略。

由于通过 CityEngine 导出的 glb 上传至 Cesium ion 后生成的 3D Tiles 不携带 building_id 属性,我首先保留该 Tiles 模型用于视觉展示(贴图、光照、真实感),然后根据原始建筑边界 GeoJSON 数据,使用 extrudedHeight 拉伸生成与真实建筑体完全贴合的立方体,这些立方体用于逻辑检测与属性访问。

1
2
3
4
5
6
7
8
Cesium.GeoJsonDataSource.load("buildings.geojson").then((ds) => {
viewer.dataSources.add(ds)
ds.entities.values.forEach((entity) => {
entity.polygon.extrudedHeight = entity.properties.height
entity.polygon.material = Cesium.Color.WHITE.withAlpha(0.01) // 几乎透明
entity.polygon.outline = false
})
})

这样场景中实际存在两种模型:

视觉层 3D Tiles 模型,提供真实贴图与阴影
逻辑层 GeoJSON 拉伸体,拥有 building_id 属性,用于检测与计算距离

GeoJSON 拉伸体与 3D Tiles 模型贴合叠加效果

防止穿墙策略

与 ArcGIS 的 hitTest 不同,Cesium 没有内置碰撞检测。为避免相机穿过建筑,我在每次移动前调用射线检测:若射线命中距离小于一定阈值(例如 3 米),则阻止前进。

1
2
3
4
5
6
7
8
9
const ray = viewer.camera.getPickRay(new Cesium.Cartesian2(
viewer.canvas.clientWidth / 2,
viewer.canvas.clientHeight / 2
));
const res = await viewer.scene.pickFromRayMostDetailed(ray, [tileset]);
if (res && Cesium.defined(res.position)) {
const dist = Cesium.Cartesian3.distance(viewer.camera.positionWC, res.position);
return dist > 3; // 小于3米时视为碰撞
}

排除 3D Tiles:渲染与逻辑的分离策略

在进行射线检测时,如果不做特殊处理,Cesium 的拾取函数会优先命中表层的 3D Tiles,但其返回的 object.id 为空,无法获取 building_id。

因此,我使用了 pickFromRayMostDetailed(ray, exclude) 的参数 exclude 列表,在其中显式排除 Tileset,从而让射线“穿透”贴图表面,直接命中后方的逻辑检测体。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const scene = viewer.scene
const canvas = scene.canvas
const p = new Cesium.Cartesian2(canvas.clientWidth / 2, canvas.clientHeight / 2)

// 生成拾取射线(相机中心点)
const ray = viewer.camera.getPickRay(p)

// 排除 3D Tiles
const exclude = []
if (tileset) exclude.push(tileset)

// 射线拾取
const res = await scene.pickFromRayMostDetailed(ray, exclude)

let building_id = 0, distance = 0

if (Cesium.defined(res) && res.object) {
const ent = res.object.id
const pid = ent.properties?.building_id
building_id = typeof pid?.getValue === 'function' ? pid.getValue() : 0

if (Cesium.defined(res.position)) {
const camPos = viewer.camera.positionWC
distance = Cesium.Cartesian3.distance(camPos, res.position)
}
}

拍照截图

Cesium 提供 scene.canvas.toDataURL() 方法,可直接获取当前画面截图。

结语与展望

本项目是我在 2025 易智瑞杯大学生 GIS 软件开发竞赛 中的参赛作品,展示了 GIS三维可视化、AI识别与无人机模拟技术的融合创新。 目前系统基于虚拟无人机模拟实现完整流程,未来我们计划接入真实无人机视频流,实现实时画面传输与缺陷识别