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

实时语义分割之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回原始尺寸,后续使用自己的数据训练时注意调整。

结果示例

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

相关文章:

  • Linux----网络通信
  • WPS AI+office-ai的安装、使用
  • Linux查看TP6 command定时任务并重启
  • 一、Prometheus架构
  • table 拖拽移动
  • 广域互联网关键技术详解(GRE/LSTP/IPsec/NAT/SAC/SPR)
  • 文件上传复现
  • Office 2021 Mac Office办公
  • 【银河麒麟高级服务器操作系统实际案例分享】数据库资源重启现象分析及处理全过程
  • HTML5+CSS3+JS小实例:带缩略图的焦点图
  • vue组合式API中prop
  • 深入 Vue.js 组件开发:从基础到实践
  • 《张一鸣,创业心路与算法思维》
  • 准确--Centos最小化安装通过命令去修改ip和dns
  • 本地部署Dify及避坑指南
  • 【powerjob】 powerjobserver注册服务IP错误
  • uniapp+vue3搭建项目
  • ESP32-P4 支持哪些 RISC-V 汇编指令?
  • 前缀和矩阵
  • 人工智能技术的广阔前景
  • 宿州做网站/自动优化句子的软件
  • 如果制作个人网站/国内免费推广产品的网站
  • 安装wordpress 空白/长沙网站优化推广方案
  • 境外网站 备案/优化大师官网入口
  • 济南哪家公司做网站好/企业邮箱入口
  • 广西建设厅查询网站/百度客户服务电话