Town10 幕墙图像病害识别
模块将无人机巡航相机图像转换为可复查的幕墙候选区域,输出裂缝、污渍、剥落与玻璃构件的类别、 置信度和像素边框。玻璃构件不计入病害数量;巡航采集与识别可分别运行,也可通过标准图像话题连接。
与已有模块的关系
本 PR 只新增识别层,不重复实现 MuJoCo 场景、网络、路线或采集封装:
| 模块 | 职责 | 本 PR 的关系 |
|---|---|---|
src/air/mujoco_facade_capture(#586 已合并) |
MuJoCo 幕墙场景、无人机路线、网络/传感器采集与 ROS 封装 | 直接复用,不修改、不复制 |
src/air/town10_facade_cruise_capture |
OpenHUTB Town10 原生巡航采集,输出 capture_*.png 和 /town10/image_raw |
消费其输出,不新增场景/路线 |
本模块 town10_facade_defect_detection |
ONNX 四类检测、带框图像/JSON、ROS 2 图像接口 | 新增的检测层 |
584/#585 的 MuJoCo 幕墙训练与闭环评估仍是独立模块;本模块不依赖它们,也不修改其代码。
新的交互验证环境是本模块自带的 ROS 图像接口测试:tests/verify_ros_topic.py 发布带行补齐的
rgb8 图像到 /town10/image_raw,校验输出的 bgr8 带框图像、时间戳/相机坐标系和 JSON 字段;
场景、网络和路线仍由 mujoco_facade_capture / town10_facade_cruise_capture 提供。
识别效果
原生 Town10 在线巡航图像
OpenHUTB Town10 的原生相机完成 12 个航点采图,随后使用同一 ONNX 模型识别全部 12 张照片。
以下展示 capture_000、capture_006、capture_011 的原图与模型输出。


阈值 0.25 时共输出 115 个候选框:玻璃构件 113 个、污渍候选 2 个;裂缝与剥落候选均为 0。 同一构件可能在多个相邻航点反复出现,此处统计为逐图预测框数。 在线照片尚无人工病害标签,不能据此计算识别精度,也不能将污渍候选视为已确认病害。 十二图完整识别结果及图像摘要
标注验证图像
下图左侧为相机图像,右侧为随包 ONNX 模型的识别结果。

动图按顺序查看六张验证图像的带框输出。

处理流程
- 读取巡航保存的 PNG/JPEG,或订阅
/town10/image_raw。 - 等比例缩放并补边至 640×640,转换 RGB 浮点张量。
- 使用 OpenCV DNN CPU 后端执行 YOLOv8 ONNX。
- 置信度筛选、按类别进行非极大值抑制,恢复原图像素坐标。
- 保存带框图像、结构化 JSON,或发布对应 ROS 2 话题。
设原图尺寸为 ,补边输入尺寸为 ,缩放比为:
其中 是左、上补边像素。坐标恢复后截断至原图范围。 同类候选框使用交并比抑制:
不同类别分别处理,使玻璃构件与其表面病害可以同时保留。
快速运行
在仓库的 src/air/town10_facade_defect_detection 目录执行:
python -m pip install -r requirements.txt
python main.py --input samples --output output
结果为 output/annotated/*.png 和 output/detections.json。
JSON 每框包含 class_id、class_name、confidence、xyxy、is_defect。
完整六图输出见 识别结果。
原生采集目录接入
在 src/air/town10_facade_cruise_capture 中,连接已起飞悬停且朝向墙面的相机:
python main.py --backend airsim --host 127.0.0.1 --camera front_cam --speed 0.5 --duration 150 --gif --output output/native
进入 src/air/town10_facade_defect_detection,直接识别巡航照片目录:
python main.py --input ../town10_facade_cruise_capture/output/native --output output/native_detection
识别结果保留 capture_000.png 等名称,可与巡航 manifest.json 的实际位姿、相机时间戳对应。
ROS 2 图像接入
source /opt/ros/humble/setup.bash
colcon build --symlink-install --packages-select town10_facade_defect_detection
source install/setup.bash
ros2 launch town10_facade_defect_detection detect.launch.py
默认处理随包图像后退出。巡航采集发布图像时启动持续订阅:
ros2 launch town10_facade_defect_detection detect.launch.py mode:=live input_topic:=/town10/image_raw
| 接口 | 消息类型 | 内容 |
|---|---|---|
/town10/image_raw |
sensor_msgs/Image |
巡航相机图像 |
/town10/defects/image |
sensor_msgs/Image |
带框 BGR 图像 |
/town10/defects/detections |
std_msgs/String |
检测 JSON,含原时间戳和相机坐标系 |
支持 RGB/BGR、RGBA/BGRA、灰度 8 位图像,并正确跳过 step 行补齐字节。
Humble 图像接口验证已通过:640×360 RGB 输入每行含 7 字节补齐,
输出 BGR 图像和 JSON 保留输入时间戳、相机坐标系,样本得到 13 个候选框,病害数量为 9。
接口验证结果
测试与复现
安装测试依赖:
python3 -m pip install --user pytest
# Ubuntu/ROS 2 也可以:sudo apt install python3-pytest
python3 -m pip install -r requirements.txt
运行:
python3 -m pytest -q
colcon build --packages-select town10_facade_defect_detection
colcon test --packages-select town10_facade_defect_detection
colcon test-result --verbose
setup.py 已声明 tests_require 与 extras_require={"test": ["pytest"]},
setup.cfg 已设置 testpaths = tests;colcon test 现在会实际执行
tests/test_boundaries.py 中的 8 个用例,而不是返回 0 tests。当前结果:
8 passed
Summary: 8 tests, 0 errors, 0 failures, 0 skipped
采集包 town10_facade_cruise_capture 的 18 个用例也已注册;对应的
colcon test --packages-select town10_facade_cruise_capture 输出:
18 passed
Summary: 18 tests, 0 errors, 0 failures, 0 skipped
验证数据与结果
四类模型来源于补充的幕墙巡检实现包。完整人工标注有 132 张图像、1976 个框。 其中 106 张用于训练,训练另有 104 张合成增强副本;26 张原始图像用于验证,包含 482 个框。 随包六图来自该验证集,模型、图像与标签的摘要用于确认评价输入一致。
| 类别 | 标注框 | AP50 | Precision | Recall |
|---|---|---|---|---|
| crack 裂缝 | 19 | 0.0050 | 0.0000 | 0.0000 |
| stain 污渍 | 147 | 0.4200 | 0.5268 | 0.4014 |
| peel 剥落 | 124 | 0.1662 | 0.6667 | 0.0806 |
| glass 玻璃 | 192 | 0.9460 | 0.8402 | 0.9583 |
四类 mAP50=0.3843,mAP50–95=0.1728;三类病害微平均 Precision=0.5433、Recall=0.2379。 玻璃构件识别较稳定,裂缝、剥落仍有明显漏检,输出用于辅助定位待复查区域。 此数据是图像级划分,相邻采集帧可能分布于训练与验证,不能据此声称严格跨建筑泛化。
固定工作点的 Precision、Recall 采用置信度 0.25、匹配 IoU=0.5。 AP 使用置信度 0.001 的候选及 101 点插值;AP50–95 对 10 个 IoU 阈值平均。
训练与复现
完整数据目录由外部参数指定,训练入口重新建立可移植的 data.yaml:
python -m pip install -r requirements-training.txt
python train.py --dataset /path/to/dataset_final --output training --epochs 60 --batch 8 --device cpu --export
python evaluate.py --dataset /path/to/dataset_final --output evaluation
训练输出保存在指定目录;随包模型保持原权重。新的数据应按建筑或采集序列划分, 合成增强仅用于训练,并保存模型、数据划分和评价记录之间的对应关系。
模型与许可
随包模型输入 1×3×640×640,输出 1×8×8400。
类别顺序已从 ONNX 元数据核对为 crack/stain/peel/glass。
模型 SHA-256 为 de2fced0c5260ba31af51603f6c884f783572afed6e32fed5a76bdf699a5a97f。
代码及模型采用 AGPL-3.0,许可文本和模型来源随模块提供。
大模型使用声明
本模块代码及文档使用 AI 编程助手(大模型工具)辅助完成方案讨论、代码与文档起草、 问题排查和评审修订。提交者负责检查验证,并对提交内容的正确性和完整性负责。