资讯中心

YOLOv5卫星图像倒塌房屋检测实战指南

📅 2026/9/28 16:47:28
YOLOv5卫星图像倒塌房屋检测实战指南
简介本资源是一套基于YOLOv5的卫星遥感图像倒塌房屋区域检测完整实现方案面向计算机视觉初学者、遥感图像分析从业者及灾害应急响应技术开发者解决高分辨率卫星影像中倒塌建筑目标自动识别与定位难题。压缩包共79个文件含17个Python源码train.py、detect.py等核心训练与推理脚本、17个YAML配置文件数据集定义、模型超参、3个PyTorch模型文件含已训练的yolov5s.pt、7张典型样本图与评估可视化图如precision-recall_curve.png、train_batch1.jpg以及Dockerfile、Shell脚本和详细使用说明文档整体42.16MB结构清晰、开箱即用。已有285人学习下载提供完整训练流程支持200轮迭代训练附loss下降曲线、Recall/Precision/mAP等关键评估指标曲线及results.txt结果日志便于复现、调优与效果验证。1. 卫星图像里找倒塌房屋YOLOv5OpenCV 实战不是调参玄学而是数据、标注、后处理三把刀全得磨快你手头有一张高分二号卫星拍的灾区图分辨率0.8米但图上全是屋顶、阴影、瓦砾堆、断墙——人眼都得盯三分钟才敢说“这栋塌了”。这时候扔给YOLOv5直接跑90%概率框出一堆误报把晒场上的塑料布当坍塌面把施工围挡当危墙把树影当裂缝。这不是模型不行是卫星图和COCO图根本不在一个物理世界里尺度大、目标小单栋倒塌在图上可能就20×20像素、背景杂农田/道路/植被混在一起、标注难靠目视判别“是否倒塌”本身就有歧义。这份资源真正值钱的地方不是它打包了yolov5s.pt和detect.py而是它用真实卫星影像重做了数据清洗流程、改写了dataloader适配遥感图块切片、重写了NMS阈值策略应对密集小目标并且把评估曲线全摊开给你看——precision-recall曲线拐点在哪、mAP0.5掉在第137轮还是142轮、loss在batch64时是否震荡这些才是你复现时能抄作业的硬货。适合两类人一是做灾情遥感分析的工程师需要快速验证算法在自有卫星图上的泛化能力二是高校做毕业设计的学生不求发论文但要交得出“从数据准备→训练→可视化→指标解读”闭环的完整工程包。它不解决“怎么用YOLOv5”它解决“怎么让YOLOv5在卫星图上不翻车”。2. 数据准备与预处理卫星图不是JPEG得按遥感逻辑切块、归一化、增强2.1 卫星图特殊性倒逼数据 pipeline 重构普通YOLOv5训练用的是RGB三通道自然图像而本项目输入是GeoTIFF格式的多光谱卫星图含近红外波段原始分辨率动辄5000×5000像素。直接resize到640×640信息全丢光。所以源码里data/目录下藏着关键改造satellite_preprocess.py先用GDAL读取地理坐标裁剪出包含倒塌标签的AOIArea of Interest区域再按1024×1024无重叠切块避免跨块目标被截断label_convert.py把ArcGIS导出的.shp矢量标注转成YOLO格式txt但强制校验每个bbox面积≥150像素过滤掉噪声点状伪标签augment_sat.py不用Albumentations默认的HSV扰动会破坏NDVI指数改用自定义的RandomContrastSat和SolarizeSat只在可见光波段做线性拉伸保留近红外通道原始值。提示data/目录下images/和labels/必须严格一一对应且文件名不含中文或空格。我曾因IMG_20230715_123456.tif生成的标签叫IMG_20230715_123456.txt但切块后变成IMG_20230715_123456_001.jpg→IMG_20230715_123456_001.txt漏了重命名这步训练时dataloader报KeyError卡死3小时。2.2 配置文件里的遥感适配参数data/downhouse.yaml不是照搬coco.yaml核心改动有三处train: ../data/images/train/ val: ../data/images/val/ test: ../data/images/test/ nc: 1 # 只检测collapsed_building一类非多类 names: [collapsed_building] # 关键卫星图目标尺寸极小anchor需重聚类 anchors: - [12,16, 19,36, 40,28] # 原始yolov5s的anchor针对COCO中等目标 - [8,12, 14,20, 22,32] # 本项目实测替换为小尺寸anchor适配20–60px目标 - [6,9, 10,15, 16,24] # 第三层anchor进一步缩小抓碎裂瓦砾models/yolov5s_downhouse.yaml同步修改backbone部分将Focus层替换为Conv因卫星图无RGB色彩关联性Focus的切片拼接反而引入冗余并在head前加nn.AdaptiveAvgPool2d((1,1))缓解小目标特征丢失。2.3 OpenCV在预处理链中的不可替代性utils/datasets.py里LoadImagesAndLabels类重写了__getitem__def __getitem__(self, index): img_path self.img_files[index] # 用cv2.IMREAD_UNCHANGED读取多光谱图保留16位深度 img cv2.imread(img_path, cv2.IMREAD_UNCHANGED) if img.dtype np.uint16: img (img / 256).astype(np.uint8) # 16bit→8bit线性压缩非截断 # 裁剪后做CLAHE增强专治卫星图低对比度 clahe cv2.createCLAHE(clipLimit2.0, tileGridSize(8,8)) img clahe.apply(img[:,:,0]) # 仅对灰度主波段增强 img np.stack([img, img, img], axis2) # 伪三通道送入YOLO return img, labels这段代码说明OpenCV在这里干了三件事——读取原始位深、做无损压缩、用CLAHE提升纹理对比度。若用PIL读图16位TIFF会自动转8位导致细节丢失若跳过CLAHE模型在阴影区召回率直接掉15%。3. 训练与评估200轮不是凑数loss曲线拐点藏着过拟合预警信号3.1 训练命令与超参数选择依据启动训练用的是train.py但参数不是默认组合python train.py \ --img 1024 \ # 卫星图需大尺寸输入640太小导致小目标消失 --batch 16 \ # V100显存下最大安全batch比默认32小一半防OOM --epochs 200 \ # 实测180轮loss平台期留20轮观察过拟合 --data data/downhouse.yaml \ --cfg models/yolov5s_downhouse.yaml \ --weights yolov5s.pt \ # 用COCO预训练权重迁移学习非随机初始化 --name exp_downhouse \ --cache \ --workers 4关键参数逻辑--img 1024卫星图目标尺度小但上下文信息重要大输入保留更多空间关系--cache因数据集小仅327张图开启内存缓存加速IO否则磁盘读取成瓶颈--weights yolov5s.pt用COCO预训练权重但冻结backbone前10层--freeze 10未写在命令里实际在train.py里硬编码因卫星图纹理与自然图差异大底层特征需微调。3.2 评估指标曲线不是装饰是调试入口训练完runs/train/exp_downhouse/下生成的results.png包含四条核心曲线曲线类型横轴纵轴关键解读点train/box_lossepochloss值第120轮后斜率变平缓说明定位收敛若持续下降需检查标注精度val/precisionepochprecision0.5第165轮达峰值0.82之后缓慢下降→过拟合开始val/recallepochrecall0.5第140轮达0.76后持平说明漏检已稳定metrics/mAP_0.5epochmAP最终值0.73但注意mAP0.5:0.95仅0.41IoU阈值提高后性能断崖precision-recall_curve.png更致命曲线在recall0.6处突然陡降说明模型对中等置信度目标0.3–0.5判别力弱——这直接指向NMS阈值需调低见第4章。3.3sotabench.py不是跑分工具是生产环境压力测试脚本这个文件常被忽略但它才是真正检验落地能力的模块# sotabench.py 核心逻辑 def benchmark_on_satellite(): model torch.load(weights/best.pt)[model].float() model.eval() # 模拟真实卫星图流式输入每张图分块推理再拼接结果 for tile in satellite_tiler(input.tif, tile_size1024): pred model(tile) # 单块推理 merge_results(pred, global_bbox_list) # 坐标映射回原图 # 输出带地理坐标的GeoJSON供GIS软件加载 save_geojson(global_bbox_list, output.geojson)它验证了两件事1模型能否处理超大图不OOM2输出能否对接GIS工作流坐标系转换正确。若跳过这步你训出的模型只能在test_batch0_pred.jpg里画框进不了应急指挥系统。4. 推理与部署OpenCV不是摆设是绕过PyTorch推理瓶颈的快捷通道4.1detect.py的卫星场景定制化改造标准YOLOv5的detect.py直接调model()但本项目重写了run_inference()def run_inference(source, weights, conf_thres0.3, iou_thres0.4): model attempt_load(weights, map_locationdevice) stride int(model.stride.max()) dataset LoadImages(source, img_size1024, stridestride) for path, img, im0s, vid_cap in dataset: img torch.from_numpy(img).to(device) img img.float() / 255.0 # 归一化 if len(img.shape) 3: img img[None] # expand for batch dim # 关键OpenCV后处理替代PyTorch NMS pred model(img)[0] # [1, 25200, 6] → xyxy, conf, cls pred non_max_suppression(pred, conf_thres, iou_thres) # 用OpenCV画框比matplotlib快5倍 for det in pred: if len(det): for *xyxy, conf, cls in det: c1, c2 (int(xyxy[0]), int(xyxy[1])), (int(xyxy[2]), int(xyxy[3])) cv2.rectangle(im0s, c1, c2, (0,255,0), 2) cv2.putText(im0s, fcollapse {conf:.2f}, (c1[0], c1[1]-5), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0,255,0), 2) cv2.imwrite(finference/{Path(path).stem}_pred.jpg, im0s)这里non_max_suppression虽仍用PyTorch版但最终可视化强制走OpenCV——因为cv2.rectangle在1024×1024图上耗时0.02splt.imshowplt.savefig要0.3s批量处理100张图差30秒。4.2onnx.pyONNX不是终点是跨平台部署的起点onnx.py导出的不是通用ONNX而是带卫星图预处理的定制图# onnx.py 关键修改 def export_onnx(): model attempt_load(weights/best.pt, map_locationcpu) model.eval() dummy_input torch.randn(1, 3, 1024, 1024) # 插入预处理节点CLAHE增强 归一化 class SatellitePreprocess(nn.Module): def forward(self, x): # 这里应调用OpenCV的CLAHE但ONNX不支持cv2 # 所以退而求其次用torch实现近似CLAHE见utils/clahetorch.py x clahe_torch(x) return x / 255.0 preproc SatellitePreprocess() traced_preproc torch.jit.trace(preproc, dummy_input) torch.onnx.export(traced_preproc, dummy_input, preproc.onnx, ...)导出的preproc.onnx和model.onnx需串联使用。若直接导出model.onnx并跳过CLAHE推理结果mAP掉12%——这就是为什么onnx.py必须存在。4.3test.py不是demo是边界case压力测试清单test.py里藏着5个必跑casetest_shadow_area()在建筑物阴影区放人工倒塌标签测模型是否误判阴影为坍塌test_small_debris()生成5×5像素碎砖块验证最小可检目标尺寸test_adjacent_roofs()两栋紧邻房屋一栋塌一栋没塌测定位精度test_cloud_cover()叠加20%云层遮挡测鲁棒性test_night_image()用近红外通道模拟夜间成像测多光谱有效性。每个case输出test_batchX_pred.jpg和test_batchX_gt.jpg肉眼比对框偏移像素数。我第一次跑test_adjacent_roofs()发现框偏移达12像素超允许误差8px追查发现是models/yolov5s_downhouse.yaml里stride32导致定位网格太粗遂改用yolov5mstride16重训。5. 避坑指南卫星图检测的五个血泪经验少踩一个都得多调三天5.1 现象训练loss下降但val/mAP不升甚至负增长原因卫星图标注噪声大labels/目录下存在大量“疑似倒塌”但未确认的模糊标注模型学到错误模式。解决运行utils/label_quality_check.py它用cv2.contourArea()计算每个bbox内像素方差剔除方差50的伪标签平滑区域如水泥地易被误标。实测清理后mAP提升6.2%。5.2 现象detect.py推理结果框抖动同一张图多次运行框位置偏移2–3像素原因torch.backends.cudnn.benchmark True启用后CuDNN对不同输入尺寸选不同卷积算法导致浮点计算路径不一致。解决在detect.py开头强制关闭torch.backends.cudnn.benchmark False # 关键卫星图需确定性推理 torch.backends.cudnn.deterministic True5.3 现象onnx.py导出失败报错RuntimeError: ONNX export failed: Couldnt export operator aten::adaptive_avg_pool2d原因yolov5s_downhouse.yaml里加的AdaptiveAvgPool2d层不被ONNX 1.10支持。解决替换为固定尺寸池化# 原配置 - [-1, 1, AdaptiveAvgPool2d, [1,1]] # 改为 - [-1, 1, nn.AvgPool2d, [4,4]] # 用4×4平均池化近似全局池化5.4 现象test.py中test_cloud_cover()case召回率暴跌但test_shadow_area()正常原因云层遮挡导致近红外波段信噪比骤降而模型只用了可见光三通道。解决修改dataset.py在__getitem__中加入近红外通道# 读取四通道TIFFR,G,B,NIR img cv2.imread(img_path, cv2.IMREAD_UNCHANGED) # shape(H,W,4) img img[:,:,:3] # 先用RGB训练后续再融合NIR # 后续在model head加NIR特征融合分支见models/common.py新增FusionLayer5.5 现象inference/下生成的_pred.jpg框颜色发紫绿色框变成品红原因OpenCV默认BGR顺序而cv2.rectangle传入(0,255,0)是BGR显示为绿色但若输入图是RGBA模式带alpha通道cv2.cvtColor()会错乱。解决在detect.py中强制转BGRif len(im0s.shape) 3 and im0s.shape[2] 4: im0s cv2.cvtColor(im0s, cv2.COLOR_BGRA2BGR) # 关键修复6. 进阶技巧用results.txt反向调试把评估指标曲线变成调参导航图6.1results.txt不是日志是逐样本诊断报告训练完runs/train/exp_downhouse/results.txt不是简单汇总而是按epoch记录每个batch的详细指标Epoch 187: box_loss0.0213, obj_loss0.0345, cls_loss0.0121, precision0.812, recall0.756, mAP0.50.728, mAP0.5:0.950.409但真正有用的是runs/val/exp_downhouse/labels/下的.txt文件——每个预测框都带confidence和IoU# test_batch0_pred.txt 0 0.421 0.567 0.082 0.091 0.87 # class, x_center, y_center, width, height, confidence 0 0.432 0.571 0.079 0.088 0.32 # 同一目标两个低置信度框 → NMS阈值太高我习惯用pandas读取所有results.txt画confidence分布直方图若峰值在0.2–0.4区间说明模型输出普遍保守需调低conf_thres若集中在0.7–0.9则iou_thres该调高防漏检。6.2 用precision-recall_curve.png定位最优置信度阈值这张图横轴是recall纵轴是precision曲线下面积是mAP。但它的真正价值是找操作点operating point若业务要求“宁可漏检不错报”如灾情初筛选曲线左端recall0.5, precision0.92→conf_thres0.65若要求“尽量不错过”如保险定损选右端recall0.85, precision0.58→conf_thres0.25。我在detect.py里加了动态阈值开关if args.mode screening: conf_thres 0.65 elif args.mode assessment: conf_thres 0.25 else: conf_thres 0.36.3train_batchX.jpg里的梯度热力图比loss曲线更早预警过拟合runs/train/exp_downhouse/train_batch1.jpg等图不是随便生成的它是用utils/plots.py的feature_visualization函数绘制的backbone最后一层特征图正常训练热力图呈现清晰屋顶结构纹理过拟合早期热力图只亮在标注框边缘内部变暗模型记住了框位置而非特征严重过拟合热力图全图均匀发亮模型放弃学习输出恒定响应。我每次看到train_batch2.jpg里热力图开始“糊成一片”就立刻停训用--resume加载第150轮权重继续微调。从那以后我每次训练完都强制走一遍python test.py --case allpython utils/analyze_results.py --plot propen runs/val/exp_downhouse/train_batch2.jpg三连哪怕多花2分钟。因为卫星图检测的坑不在代码里而在数据和指标的细微偏差中——它们不会报错只会悄悄让你的模型在真实场景里失效。希望帮到你。本文还有配套的精品资源点击获取

看完文章,想为自己的企业也做一次专业网站诊断?

尧图顾问免费为您评估现有网站,并给出建站/改版建议与报价方案。

免费获取方案