当前位置: 首页 > article >正文

实时语义分割之FarSeeNet(2020)模型解析代码复现及滑坡检测实战

论文《FarSee-Net: Real-Time Semantic Segmentation by Efficient Multi-scale Context Aggregation and Feature Space Super-resolution》原理解析及代码复现。
用自己的数据训练yolov11目标检测
实时语义分割之BiSeNetv2(2020)结构原理解析及建筑物提取实践
实时语义分割之Deep Dual-resolution Networks(DDRNet2021)原理解析及建筑物提取实践
SegFormer 模型解析:结合 Transformer 的高效分割框架原理及滑坡语义分割实战

文章目录

  • 概要
  • 理论知识
    • 整体架构流程
      • 前端网络(frontend_network):基于ResNet的特征提取
      • 后端网络(backend_network):FASPP(基于空间金字塔池化的特征聚合)
  • 模型实践
    • 训练数据准备
    • 模型训练
    • 影像测试
    • 结果示例

概要

提示: (1)论文地址:https://arxiv.org/abs/2003.03913 (2)本人打包好数据可运行代码:FarSeeNet.zip 链接: https://pan.baidu.com/s/1febtaxNsKVVURu03IIacYA?pwd=1pve 提取码: 1pve
FarSee-Net包括前端、后端两个部分,前端采用ResNet基础的骨干网络确保了鲁棒的特征提取;而后端网络的FASPP模块则通过有效结合高低层特征进行精准分割。网络围绕两个关键思想构建:
1、高效的多尺度上下文聚合:模型整合了多层次的上下文信息,提高了分割精度,尤其是在物体大小差异较大的复杂场景中。
2、特征空间超分辨率:通过使用超分辨率技术,FarSee-Net增强了特征表示,使得在不显著增加计算开销的情况下,能够实现更高像素级别的精度。
精度效率对比

理论知识

整体架构流程

在这里插入图片描述

class FarSeeNet(nn.Module):
    def __init__(self, num_class=1, n_channel=3, backbone_type='resnet18', act_type='relu'):
        super().__init__()
        if 'resnet' in backbone_type:
            self.frontend_network = ResNet(backbone_type)
            high_channels = 512 if backbone_type in ['resnet18', 'resnet34'] else 2048
            low_channels = 256 if backbone_type in ['resnet18', 'resnet34'] else 1024
        else:
            raise NotImplementedError()
        self.backend_network = FASPP(high_channels, low_channels, num_class, act_type)

    def forward(self, x):
        size = x.size()[2:]
        _, _, x_low, x_high = self.frontend_network(x)
        x = self.backend_network(x_high, x_low)
        x = F.interpolate(x, size, mode='bilinear', align_corners=True)
        return x

FarSeeNet 由两部分组成:

  • frontend_network(主干网络):基于ResNet的特征提取。
  • backend_network(解码头):基于FASPP模块通过有效结合高低层特征进行精准分割。

前端网络(frontend_network):基于ResNet的特征提取

self.frontend_network = ResNet(backbone_type)
high_channels = 512 if backbone_type in ['resnet18', 'resnet34'] else 2048
low_channels = 256 if backbone_type in ['resnet18', 'resnet34'] else 1024

FarSee-Net的前端网络采用了ResNet架构。ResNet是一种著名的深度卷积网络,通过残差连接克服了梯度消失问题。前端网络输出低层和高层特征(分别为x_low和x_high),并将其传递给后端网络进一步处理。

  • 高层特征(深层):resnet18和resnet34为512个通道,较深的ResNet变体为2048个通道。
  • 低层特征(浅层):resnet18和resnet34为256个通道,较深的变体为1024个通道。

后端网络(backend_network):FASPP(基于空间金字塔池化的特征聚合)

在这里插入图片描述

代码逻辑(简化示意)

class FASPP(nn.Module):
    def __init__(self, high_channels, low_channels, num_class, act_type, dilations=[6,12,18], hid_channels=256):
        super().__init__()
        
        # 高层特征处理
        self.conv_high = nn.ModuleList([ConvBNAct(high_channels, hid_channels, 1, act_type)])
        for dt in dilations:
            self.conv_high.append(nn.Sequential(ConvBNAct(high_channels, hid_channels, 1, act_type),
                                                 DWConvBNAct(hid_channels, hid_channels, 3, dilation=dt, act_type)))

        self.sub_pixel_high = nn.Sequential(conv1x1(hid_channels*4, hid_channels*2*(2**2)), nn.PixelShuffle(2))

        # 低层特征处理
        self.conv_low_init = ConvBNAct(low_channels, 48, 1, act_type)
        self.conv_low = nn.ModuleList([ConvBNAct(hid_channels*2+48, hid_channels//2, 1, act_type)])
        for dt in dilations[:-1]:
            self.conv_low.append(nn.Sequential(ConvBNAct(hid_channels*2+48, hid_channels//2, 1, act_type),
                                                DWConvBNAct(hid_channels//2, hid_channels//2, 3, dilation=dt, act_type)))

        self.conv_low_last = nn.Sequential(ConvBNAct(hid_channels//2*3, hid_channels*2, 1, act_type),
                                           ConvBNAct(hid_channels*2, hid_channels*2, act_type))

        self.sub_pixel_low = nn.Sequential(conv1x1(hid_channels*2, num_class*(4**2)), nn.PixelShuffle(4))

    def forward(self, x_high, x_low):
        # 处理高层特征
        high_feats = [conv_high(x_high) for conv_high in self.conv_high]
        x = torch.cat(high_feats, dim=1)
        x = self.sub_pixel_high(x)

        # 处理低层特征
        x_low = self.conv_low_init(x_low)
        x = torch.cat([x, x_low], dim=1)

        low_feats = [conv_low(x) for conv_low in self.conv_low]
        x = torch.cat(low_feats, dim=1)
        x = self.conv_low_last(x)
        x = self.sub_pixel_low(x)

        return x

1、高层特征处理(High-level Features):

  • self.conv_high:首先,使用一个 1x1 卷积层提取高层特征。然后,对于每个膨胀率 dilations 中的值,使用一个 1x1 卷积和一个带有不同膨胀率的深度可分离卷积(DWConv)来提取不同尺度的高层特征。
  • self.sub_pixel_high:将所有提取的高层特征合并,并通过一个 1x1 卷积和 PixelShuffle 层进行上采样,提升图像分辨率。

2、低层特征处理(Low-level Features):

  • self.conv_low_init:对低层输入特征图应用一个 1x1 卷积,初始化低层特征。
  • self.conv_low:随后,低层特征与高层特征拼接,并使用多个 1x1 卷积和深度可分离卷积来进一步处理低层特征。
  • self.conv_low_last:经过多个卷积处理后,最终的低层特征通过一个 1x1 卷积和卷积层进一步调整维度。
  • self.sub_pixel_low:类似于高层特征的处理,将低层特征通过一个 1x1 卷积和 PixelShuffle 层进行上采样。

3、前向传播:

  • 高层特征处理:通过 self.conv_high 进行一系列卷积操作,并将结果合并,最终通过 self.sub_pixel_high 层进行上采样。
  • 低层特征处理:低层输入通过 self.conv_low_init 进行初始化,然后与高层特征拼接,经过多层卷积处理后,最终通过 self.sub_pixel_low 层进行上采样,生成最终输出。

模型实践

训练数据准备

提示:云盘代码已内置少量山体滑坡数据集

训练数据分为原始影像和标签(二值化,0和255),均位于Sample文件夹内,数据相对路径为:

Sample\landslide\train\ IMG_T1
------------------\ IMG_LABEL
-------------\val \ IMG_T1
------------------\IMG_LABEL

本示例中影像尺寸不一,在dp0_train.py文件parser参数项,crop_height 、crop_width设置为256、256,训练数据在CDDataset_Seg定义中进行了resize,模型训练中均为256*256。

模型训练

运行dp0_train.py,模型开始训练,核心参数包括:

parser参数说明
num_epochs训练批次
learning_rate初始学习率
batch_size单次样本数量
dataset数据集名字
crop_height训练时影像重采样尺度

数据结构CDDataset_Seg定义在utils文件夹dataset.py中,注意读取后进行了数据增强(随机翻转),灰度化,尺寸调整,标签归一化、 one-hot 编码,以及维度和数据类型的转换,最终得到适用于 PyTorch 模型训练的张量。

        # 读取训练图片和标签图片
        image_t1 = cv2.imread(image_t1_path,-1)
        #image_t2 = cv2.imread(image_t2_path)
        label = cv2.imread(label_path)
       
        # 随机进行数据增强,为2时不做处理
        if self.data_augment:
            flipCode = random.choice([-1, 0, 1, 2])
            if flipCode != 2:
#                image_t1 = normalized(image_t1, 'tif')
                image_t1 = self.augment(image_t1, flipCode)
                #image_t2 = self.augment(image_t2, flipCode)
                label = self.augment(label, flipCode)        
            
        label = cv2.cvtColor(label, cv2.COLOR_BGR2GRAY)
        
        image_t1 = cv2.resize(image_t1, (self.img_h, self.img_w))
        #image_t2 = cv2.resize(image_t2, (Config.img_h, Config.img_w))

        label = cv2.resize(label, (self.img_h, self.img_w))
        label = label/255
        label = label.astype('uint8')
        label = onehot(label, 2)
        label = label.transpose(2, 0, 1)
        label = torch.FloatTensor(label)

训练过程如下图所示,模型保存至checkpoints数据集同名文件夹内。

影像测试

运行dp0_AllPre.py,核心参数包括:

parser参数说明
Checkpointspath预训练模型位置名称
Dataset批量化预测数据文件夹
Outputpath输出数据文件夹

数据加载方式:

    pre_dataset = CDDataset_Pre(data_path=pre_imgpath1,
                            transform=transforms.Compose([
                                transforms.ToTensor()]))

    pre_dataloader = torch.utils.data.DataLoader(dataset=pre_dataset,
                                             batch_size=1,
                                             shuffle=False,
                                             pin_memory=True,
                                             num_workers=0)

需要注意,预测定义的数据结构CDDataset_Pre与训练时CDDataset_Seg有区别,此处将其resize回原始尺寸,后续使用自己的数据训练时注意调整。

结果示例

滑坡检测结果示例
在这里插入图片描述


http://www.kler.cn/a/571078.html

相关文章:

  • Centos7服务器防火墙设置教程
  • Collab-Overcooked:专注于多智能体协作的语言模型基准测试平台
  • ⭐算法OJ⭐矩阵的相关操作【动态规划 + 组合数学】(C++ 实现)Unique Paths 系列
  • ADC采集模块与MCU内置ADC性能对比
  • 【uniapp】子组件和父组件双向绑定,vue3已废除sync写法,v-model代替
  • 计算机毕业设计SpringBoot+Vue.js手机商城 (源码+文档+PPT+讲解)
  • blender学习25.3.3
  • 网络原理--HTTP协议
  • Ubuntu系统上部署Node.js项目的完整流程
  • kafka-关于ISR-概述
  • mapbox基础,使用点类型geojson加载symbol符号图层,用于标注文字
  • C#用加密安全的伪随机数生成器 (CSPRNG) 生成以太坊地址
  • CDefView::_OnFSNotify函数分析
  • 如何在.NET Core中解决缓存穿透、缓存雪崩和缓存击穿问题:多级缓存策略详解
  • 人工智能之数学基础:线性代数中矩阵的初印象
  • 使用MATLAB结合EasySpin进行ESR模拟的详细步骤及示例代码
  • Sqlserver安全篇之_启用TLS即配置SQL Server 数据库引擎以加密连接
  • 【智能机器人开发全流程:硬件选型、软件架构与ROS实战,打造高效机器人系统】
  • 影刀RPA开发拓展--SQL常用语句全攻略
  • AWS Amazon Aurora MySQL 性能监控与安全治理实战指南