使用U-Net模型训练 自然灾害类洪水、飓风等灾后救援高分辨率无人机图像语义分割数据集 灾后救援场景的语义分割任务 基于深度学习的自然灾害救援语义分割系统
以下文字及代码仅供参考。
自然灾害救援高分辨率无人机图像语义分割数据集训练方案
文章目录
- 使用U-Net模型训练 自然灾害类洪水、飓风等灾后救援高分辨率无人机图像语义分割数据集 灾后救援场景的语义分割任务 基于深度学习的自然灾害救援语义分割系统
- 自然灾害救援高分辨率无人机图像语义分割数据集训练方案
-
- 一、数据集概述
- 二、模型可选择 语义分割常用模型
-
- 1. DeepLabv3+
- 2. U-Net++
- 3. PSPNet (Pyramid Scene Parsing Network)
- 4. HRNet (High-Resolution Network)
- 三、环境配置
- 四、数据预处理
- 五、模型训练
- 六、模型改进与优化建议
-
- 1. 多任务学习架构
- 2. 数据增强策略
- 3. 损失函数改进
- 七、评估指标
- 八、推理与可视化
- 九、同学训练注意事项

如何训练这套数据集?

文章目录
- 使用U-Net模型训练 自然灾害类洪水、飓风等灾后救援高分辨率无人机图像语义分割数据集 灾后救援场景的语义分割任务 基于深度学习的自然灾害救援语义分割系统
- 自然灾害救援高分辨率无人机图像语义分割数据集训练方案
-
- 一、数据集概述
- 二、模型可选择 语义分割常用模型
-
- 1. DeepLabv3+
- 2. U-Net++
- 3. PSPNet (Pyramid Scene Parsing Network)
- 4. HRNet (High-Resolution Network)
- 三、环境配置
- 四、数据预处理
- 五、模型训练
- 六、模型改进与优化建议
-
- 1. 多任务学习架构
- 2. 数据增强策略
- 3. 损失函数改进
- 七、评估指标
- 八、推理与可视化
- 九、同学训练注意事项
自然灾害类洪水、飓风等灾后救援高分辨率无人机图像语义分割数据集
1.高分辨率图像:22GB数据量,数据集中的图像具有高清晰度(4000*3000分辨率),能够捕捉更多细节,有利于识别小尺度目标。
2.丰富的语义标注:包含多种灾害场景下的像素级标注,涵盖水、建筑物、车辆、道路、树木和池塘等10个类别。
3.多样的灾害场景:数据集包含多种灾害类型(如飓风、洪水等)的场景,覆盖不同的光照和天气条件。
4.损坏程度分类:除了语义分割标注外,还提供了建筑物和道路的损坏程度分类(如轻微损坏、中度损坏、严重损坏等)。
5.图像数量:共4494张图像。
6.语义分割类别:包括水、无损坏建筑、轻微损坏建筑、严重损坏建筑、完全损毁建筑、车辆、畅通道路、阻塞道路、树木和池塘。

一、数据集概述
4494张高分辨率(4000×3000)无人机图像,数据量22GB,适用于灾后救援场景的语义分割任务。标注类别包括:
二、模型可选择 语义分割常用模型
针对高分辨率图像和复杂灾害场景,推荐以下语义分割模型:
1. DeepLabv3+
- 优势:多尺度特征融合,空洞卷积保持分辨率
- 适合处理高分辨率图像中的小目标识别
- 支持分类与分割联合训练
2. U-Net++
- 优势:嵌套跳跃连接,提升边界精度
- 适合像素级精确标注的灾害损坏程度识别
- 可扩展为3D版本处理多光谱数据
3. PSPNet (Pyramid Scene Parsing Network)
- 优势:金字塔池化模块捕捉多尺度信息
- 适合多样化的灾害场景理解
- 对光照和天气变化具有鲁棒性
4. HRNet (High-Resolution Network)
- 优势:保持高分辨率表示贯穿整个网络
- 特别适合本数据集的4000×3000高分辨率图像
- 多分辨率并行处理增强细节识别能力
三、环境配置
# 创建虚拟环境
conda create -n disaster_seg python=3.8
conda activate disaster_seg
# 安装依赖
pip install torch torchvision torchaudio
pip install matplotlib numpy opencv-python
pip install scikit-learn scikit-image
pip install tensorboard
四、数据预处理
import os
import cv2
import numpy as np
import xml.etree.ElementTree as ET
from sklearn.model_selection import train_test_split
def resize_image(image, target_size=(1024, 1024)):
"""高分辨率图像分块或缩放"""
# 方式1: 直接缩放
resized_image = cv2.resize(image, target_size, interpolation=cv2.INTER_LINEAR)
# 方式2: 分块处理(保留原始分辨率)
# patches = [image[i:i+target_size[0], j:j+target_size[1]]
# for i in range(0, image.shape[0], target_size[0])
# for j in range(0, image.shape[1], target_size[1])]
return resized_image
def preprocess_dataset(data_dir, output_dir, test_size=0.2):
"""数据集划分和预处理"""
image_dir = os.path.join(data_dir, "images")
label_dir = os.path.join(data_dir, "annotations")
# 创建输出目录
os.makedirs(os.path.join(output_dir, "images", "train"), exist_ok=True)
os.makedirs(os.path.join(output_dir, "images", "val"), exist_ok=True)
os.makedirs(os.path.join(output_dir, "masks", "train"), exist_ok=True)
os.makedirs(os.path.join(output_dir, "masks", "val"), exist_ok=True)
# 获取所有文件
image_files = [f for f in os.listdir(image_dir) if f.endswith(".jpg") or f.endswith(".png")]
train_files, val_files = train_test_split(image_files, test_size=test_size, random_state=42)
# 处理训练集
for filename in train_files:
# 处理图像
img = cv2.imread(os.path.join(image_dir, filename))
resized_img = resize_image(img)
cv2.imwrite(os.path.join(output_dir, "images", "train", filename), resized_img)
# 处理标签
label_file = os.path.splitext(filename)[0] + ".png"
mask = cv2.imread(os.path.join(label_dir, label_file), 0)
resized_mask = resize_image(mask, target_size=(1024, 1024))
cv2.imwrite(os.path.join(output_dir, "masks", "train", label_file), resized_mask)
# 处理验证集
for filename in val_files:
# 处理图像
img = cv2.imread(os.path.join(image_dir, filename))
resized_img = resize_image(img)
cv2.imwrite(os.path.join(output_dir, "images", "val", filename), resized_img)
# 处理标签
label_file = os.path.splitext(filename)[0] + ".png"
mask = cv2.imread(os.path.join(label_dir, label_file), 0)
resized_mask = resize_image(mask, target_size=(1024, 1024))
cv2.imwrite(os.path.join(output_dir, "masks", "val", label_file), resized_mask)
print(f"Total images: {len(image_files)}")
print(f"Train set size: {len(train_files)}")
print(f"Validation set size: {len(val_files)}")
# 使用示例
data_directory = "path/to/your/dataset"
output_directory = "path/to/preprocessed/dataset"
preprocess_dataset(data_directory, output_directory)
五、模型训练
以DeepLabv3+为例:
import torch
import torch.nn as nn
from torchvision import models, transforms
from torch.utils.data import Dataset, DataLoader
from PIL import Image
import os
import numpy as np
# 自定义数据集类
class DisasterDataset(Dataset):
def __init__(self, image_dir, mask_dir, transform=None, mask_transform=None):
self.image_dir = image_dir
self.mask_dir = mask_dir
self.transform = transform
self.mask_transform = mask_transform
self.image_files = os.listdir(image_dir)
def __len__(self):
return len(self.image_files)
def __getitem__(self, idx):
img_name = self.image_files[idx]
mask_name = os.path.splitext(img_name)[0] + ".png"
image = Image.open(os.path.join(self.image_dir, img_name)).convert("RGB")
mask = Image.open(os.path.join(self.mask_dir, mask_name))
if self.transform:
image = self.transform(image)
# 将mask转换为类别标签(0-9)
mask = np.array(mask)
mask[mask == 255] = 0 # 处理无效标签值
mask = torch.from_numpy(mask).long()
return image, mask
# 数据预处理
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
# 创建数据加载器
train_dataset = DisasterDataset(
image_dir="path/to/preprocessed/images/train",
mask_dir="path/to/preprocessed/masks/train",
transform=transform
)
val_dataset = DisasterDataset(
image_dir="path/to/preprocessed/images/val",
mask_dir="path/to/preprocessed/masks/val",
transform=transform
)
train_loader = DataLoader(train_dataset, batch_size=4, shuffle=True, num_workers=4)
val_loader = DataLoader(val_dataset, batch_size=4, shuffle=False, num_workers=4)
# 加载预训练的DeepLabv3+模型
model = models.segmentation.deeplabv3_resnet50(pretrained=True)
model.classifier[4] = nn.Conv2d(256, 10, kernel_size=(1, 1)) # 修改输出通道数为10类
# 移动到GPU(如果可用)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = model.to(device)
# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss(ignore_index=255) # 忽略无效标签
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 训练循环
num_epochs = 50
for epoch in range(num_epochs):
model.train()
running_loss = 0.0
for images, masks in train_loader:
images = images.to(device)
masks = masks.to(device)
optimizer.zero_grad()
outputs = model(images)['out']
loss = criterion(outputs, masks)
loss.backward()
optimizer.step()
running_loss += loss.item() * images.size(0)
epoch_loss = running_loss / len(train_dataset)
print(f"Epoch {epoch+1}/{num_epochs}, Loss: {epoch_loss:.4f}")
# 验证
model.eval()
val_loss = 0.0
with torch.no_grad():
for images, masks in val_loader:
images = images.to(device)
masks = masks.to(device)
outputs = model(images)['out']
loss = criterion(outputs, masks)
val_loss += loss.item() * images.size(0)
val_epoch_loss = val_loss / len(val_dataset)
print(f"Validation Loss: {val_epoch_loss:.4f}")
print("Training complete")
六、模型改进与优化建议
1. 多任务学习架构
class MultiTaskModel(nn.Module):
def __init__(self, backbone, num_classes, num_damage_levels=3):
super(MultiTaskModel, self).__init__()
self.backbone = backbone
self.semantic_head = nn.Conv2d(256, num_classes, kernel_size=1)
self.damage_head = nn.Conv2d(256, num_damage_levels, kernel_size=1)
def forward(self, x):
features = self.backbone(x)['out']
semantic = self.semantic_head(features)
damage = self.damage_head(features)
return {'semantic': semantic, 'damage': damage}
2. 数据增强策略
transform = transforms.Compose([
transforms.ColorJitter(brightness=0.3, contrast=0.3, saturation=0.3),
transforms.RandomApply([transforms.GaussianBlur(kernel_size=5)], p=0.2),
transforms.RandomHorizontalFlip(p=0.5),
transforms.RandomVerticalFlip(p=0.5),
transforms.RandomRotation(30),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
3. 损失函数改进
class CombinedLoss(nn.Module):
def __init__(self, weight_semantic=1.0, weight_damage=0.5):
super(CombinedLoss, self).__init__()
self.semantic_criterion = nn.CrossEntropyLoss(ignore_index=255)
self.damage_criterion = nn.CrossEntropyLoss(ignore_index=255)
self.weight_semantic = weight_semantic
self.weight_damage = weight_damage
def forward(self, outputs, targets):
semantic_loss = self.semantic_criterion(outputs['semantic'], targets['semantic'])
damage_loss = self.damage_criterion(outputs['damage'], targets['damage'])
total_loss = self.weight_semantic * semantic_loss + self.weight_damage * damage_loss
return total_loss
七、评估指标
def calculate_metrics(preds, labels, num_classes=10):
preds = preds.cpu().numpy().flatten()
labels = labels.cpu().numpy().flatten()
# 过滤掉忽略的标签
valid_indices = labels != 255
preds = preds[valid_indices]
labels = labels[valid_indices]
# 计算准确率
accuracy = np.mean(preds == labels)
# 计算IoU
iou_per_class = []
for class_id in range(num_classes):
true_positive = np.sum((preds == class_id) & (labels == class_id))
false_positive = np.sum((preds == class_id) & (labels != class_id))
false_negative = np.sum((preds != class_id) & (labels == class_id))
denominator = true_positive + false_positive + false_negative
if denominator == 0:
iou_per_class.append(np.nan)
else:
iou_per_class.append(true_positive / denominator)
mean_iou = np.nanmean(iou_per_class)
return {
"accuracy": accuracy,
"iou_per_class": iou_per_class,
"mean_iou": mean_iou
}
八、推理与可视化
def visualize_segmentation(image, prediction, class_colors):
# 将预测结果转换为彩色图像
color_pred = np.zeros((prediction.shape[0], prediction.shape[1], 3), dtype=np.uint8)
for class_id, color in enumerate(class_colors):
color_pred[prediction == class_id] = color
# 显示图像
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.imshow(image)
plt.title("Input Image")
plt.axis("off")
plt.subplot(1, 2, 2)
plt.imshow(color_pred)
plt.title("Segmentation Result")
plt.axis("off")
plt.tight_layout()
plt.show()
# 使用示例
class_colors = [
(0, 0, 0), # 背景
(0, 0, 255), # 水
(0, 255, 0), # 无损坏建筑
(255, 255, 0), # 轻微损坏建筑
(255, 0, 0), # 严重损坏建筑
(255, 0, 255), # 完全损毁建筑
(0, 255, 255), # 车辆
(128, 128, 128), # 畅通道路
(128, 0, 0), # 阻塞道路
(0, 128, 0) # 树木
]
# 推理
model.eval()
with torch.no_grad():
image, _ = val_dataset[0]
image_tensor = image.unsqueeze(0).to(device)
output = model(image_tensor)['out']
pred = torch.argmax(output, dim=1).squeeze().cpu().numpy()
# 可视化
image = image.permute(1, 2, 0).cpu().numpy()
visualize_segmentation(image, pred, class_colors)
九、同学训练注意事项
显存管理:
- 对于4000×3000的高分辨率图像,建议使用滑动窗口或图像分块方法
- 可采用混合精度训练(AMP)减少内存占用
- 使用分布式训练加速收敛
类别不平衡处理:
- 在损失函数中添加类别权重
- 对罕见类别(如完全损毁建筑)进行过采样
- 使用Focal Loss缓解类别不平衡问题
迁移学习:
- 初始阶段使用在Cityscapes等大规模语义分割数据集上预训练的模型
- 冻结底层特征提取层,先微调顶层
- 逐步解冻更多层进行精细化调整
模型优化:
- 使用余弦退火学习率调度
- 添加辅助损失(auxiliary loss)提升性能
- 使用空洞空间金字塔池化(ASPP)模块增强多尺度特征提取
基于深度学习的自然灾害救援语义分割系统能够有效识别灾后场景中的关键要素,为应急响应和灾情评估提供重要支持。
仅供参考学习






