基于deeplabv3+|实现遥感建筑物提取

alt

前言

本期将分享「deeplabv3+网络」,论文地址https://arxiv.org/pdf/1905.02423.pdf。源码地址https://github.com/xiaoyufenfei/LEDNet

数据集

本文选取的是WHU-Building-DataSets数据集[1]包含了从新西兰基督城的航空图像中提取的超过220,000个独立建筑,图像被分割成了8189个512×512像素的片,其中包含了训练集(130,500个建筑),验证集(14,500个建筑)和测试集(42,000个建筑)。

Deeplab v3+

此次我们使用的模型为deeplabv3+。Deeplabv3+是深度学习领域的一个语义分割模型,由Google的研究人员提出。它是在Deeplabv3的基础上进行改进和扩展的,通过添加一个简单的解码器模块来特别改善物体边界的分割结果。 Deeplabv3+模型的整体架构包括Encoder和Decoder两个部分。Encoder部分采用了带有空洞卷积的DCNN,并采用了空洞空间金字塔池化模块(ASPP)来引入多尺度信息。相比Deeplabv3,Deeplabv3+还引入了Decoder模块,将底层特征与高层特征进一步融合,提升分割边界准确度。 在具体的技术实现上,Deeplabv3+采用了深度可分离卷积,这是一种更快速和更强大的编码器-解码器网络。深度可分离卷积将卷积操作分为两个独立的步骤:首先是逐个输入通道进行卷积操作,然后再将卷积结果合并。这种技术可以有效地减少计算量和参数数量,提高模型的效率和性能。 alt

网络结构

import math
import os
import torch
import torch.nn as nn
import torch.utils.model_zoo as model_zoo

bn_mom = 0.0003

class SeparableConv2d(nn.Module):
    def __init__(self,in_channels,out_channels,kernel_size=1,stride=1,padding=0,dilation=1,bias=False,activate_first=True,inplace=True):
        super(SeparableConv2d,self).__init__()
        self.relu0 = nn.ReLU(inplace=inplace)
        self.depthwise = nn.Conv2d(in_channels,in_channels,kernel_size,stride,padding,dilation,groups=in_channels,bias=bias)
        self.bn1 = nn.BatchNorm2d(in_channels, momentum=bn_mom)
        self.relu1 = nn.ReLU(inplace=True)
        self.pointwise = nn.Conv2d(in_channels,out_channels,1,1,0,1,1,bias=bias)
        self.bn2 = nn.BatchNorm2d(out_channels, momentum=bn_mom)
        self.relu2 = nn.ReLU(inplace=True)
        self.activate_first = activate_first
    def forward(self,x):
        if self.activate_first:
            x = self.relu0(x)
        x = self.depthwise(x)
        x = self.bn1(x)
        if not self.activate_first:
            x = self.relu1(x)
        x = self.pointwise(x)
        x = self.bn2(x)
        if not self.activate_first:
            x = self.relu2(x)
        return x

class Block(nn.Module):
    def __init__(self,in_filters,out_filters,strides=1,atrous=None,grow_first=True,activate_first=True,inplace=True):
        super(Block, self).__init__()
        if atrous == None:
            atrous = [1]*3
        elif isinstance(atrous, int):
            atrous_list = [atrous]*3
            atrous = atrous_list
        idx = 0
        self.head_relu = True
        if out_filters != in_filters or strides!=1:
            self.skip = nn.Conv2d(in_filters,out_filters,1,stride=strides, bias=False)
            self.skipbn = nn.BatchNorm2d(out_filters, momentum=bn_mom)
            self.head_relu = False
        else:
            self.skip=None
        
        self.hook_layer = None
        if grow_first:
            filters = out_filters
        else:
            filters = in_filters
        self.sepconv1 = SeparableConv2d(in_filters,filters,3,stride=1,padding=1*atrous[0],dilation=atrous[0],bias=False,activate_first=activate_first,inplace=self.head_relu)
        self.sepconv2 = SeparableConv2d(filters,out_filters,3,stride=1,padding=1*atrous[1],dilation=atrous[1],bias=False,activate_first=activate_first)
        self.sepconv3 = SeparableConv2d(out_filters,out_filters,3,stride=strides,padding=1*atrous[2],dilation=atrous[2],bias=False,activate_first=activate_first,inplace=inplace)

    def forward(self,inp):
        
        if self.skip is not None:
            skip = self.skip(inp)
            skip = self.skipbn(skip)
        else:
            skip = inp

        x = self.sepconv1(inp)
        x = self.sepconv2(x)
        self.hook_layer = x
        x = self.sepconv3(x)

        x+=skip
        return x


class Xception(nn.Module):
    """
    Xception optimized for the ImageNet dataset, as specified in
    https://arxiv.org/pdf/1610.02357.pdf
    """

    def __init__(self, downsample_factor):
        """ Constructor
        Args:
            num_classes: number of classes
        """

        super(Xception, self).__init__()

        stride_list = None
        if downsample_factor == 8:
            stride_list = [2,1,1]
        elif downsample_factor == 16:
            stride_list = [2,2,1]
        else:
            raise ValueError('xception.py: output stride=%d is not supported.'%os) 
        self.conv1 = nn.Conv2d(332321, bias=False)
        self.bn1 = nn.BatchNorm2d(32, momentum=bn_mom)
        self.relu = nn.ReLU(inplace=True)
        
        self.conv2 = nn.Conv2d(32,64,3,1,1,bias=False)
        self.bn2 = nn.BatchNorm2d(64, momentum=bn_mom)
        #do relu here

        self.block1=Block(64,128,2)
        self.block2=Block(128,256,stride_list[0],inplace=False)
        self.block3=Block(256,728,stride_list[1])

        rate = 16//downsample_factor
        self.block4=Block(728,728,1,atrous=rate)
        self.block5=Block(728,728,1,atrous=rate)
        self.block6=Block(728,728,1,atrous=rate)
        self.block7=Block(728,728,1,atrous=rate)

        self.block8=Block(728,728,1,atrous=rate)
        self.block9=Block(728,728,1,atrous=rate)
        self.block10=Block(728,728,1,atrous=rate)
        self.block11=Block(728,728,1,atrous=rate)

        self.block12=Block(728,728,1,atrous=rate)
        self.block13=Block(728,728,1,atrous=rate)
        self.block14=Block(728,728,1,atrous=rate)
        self.block15=Block(728,728,1,atrous=rate)

        self.block16=Block(728,728,1,atrous=[1*rate,1*rate,1*rate])
        self.block17=Block(728,728,1,atrous=[1*rate,1*rate,1*rate])
        self.block18=Block(728,728,1,atrous=[1*rate,1*rate,1*rate])
        self.block19=Block(728,728,1,atrous=[1*rate,1*rate,1*rate])
        
        self.block20=Block(728,1024,stride_list[2],atrous=rate,grow_first=False)
        self.conv3 = SeparableConv2d(1024,1536,3,1,1*rate,dilation=rate,activate_first=False)

        self.conv4 = SeparableConv2d(1536,1536,3,1,1*rate,dilation=rate,activate_first=False)

        self.conv5 = SeparableConv2d(1536,2048,3,1,1*rate,dilation=rate,activate_first=False)
        self.layers = []

        #------- init weights --------
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                m.weight.data.normal_(0, math.sqrt(2. / n))
            elif isinstance(m, nn.BatchNorm2d):
                m.weight.data.fill_(1)
                m.bias.data.zero_()
        #-----------------------------

    def forward(self, input):
        self.layers = []
        x = self.conv1(input)
        x = self.bn1(x)
        x = self.relu(x)
        x = self.conv2(x)
        x = self.bn2(x)
        x = self.relu(x)
        
        x = self.block1(x)
        x = self.block2(x)
        low_featrue_layer = self.block2.hook_layer
        x = self.block3(x)
        x = self.block4(x)
        x = self.block5(x)
        x = self.block6(x)
        x = self.block7(x)
        x = self.block8(x)
        x = self.block9(x)
        x = self.block10(x)
        x = self.block11(x)
        x = self.block12(x)
        x = self.block13(x)
        x = self.block14(x)
        x = self.block15(x)
        x = self.block16(x)
        x = self.block17(x)
        x = self.block18(x)
        x = self.block19(x)
        x = self.block20(x)       

        x = self.conv3(x)

        x = self.conv4(x)
        
        x = self.conv5(x)
        return low_featrue_layer,x

def load_url(url, model_dir='./model_data', map_location=None):
    if not os.path.exists(model_dir):
        os.makedirs(model_dir)
    filename = url.split('/')[-1]
    cached_file = os.path.join(model_dir, filename)
    if os.path.exists(cached_file):
        return torch.load(cached_file, map_location=map_location)
    else:
        return model_zoo.load_url(url,model_dir=model_dir)

def xception(pretrained=False, downsample_factor=16):
    model = Xception(downsample_factor=downsample_factor)
    if pretrained:
        model.load_state_dict(load_url('https://github.com/bubbliiiing/deeplabv3-plus-pytorch/releases/download/v1.0/xception_pytorch_imagenet.pth'), strict=False)
    return model


#-----------------------------------------#
#   ASPP特征提取模块
#   利用不同膨胀率的膨胀卷积进行特征提取
#-----------------------------------------#
class ASPP(nn.Module):
 def __init__(self, dim_in, dim_out, rate=1, bn_mom=0.1):
  super(ASPP, self).__init__()
  self.branch1 = nn.Sequential(
    nn.Conv2d(dim_in, dim_out, 11, padding=0, dilation=rate,bias=True),
    nn.BatchNorm2d(dim_out, momentum=bn_mom),
    nn.ReLU(inplace=True),
  )
  self.branch2 = nn.Sequential(
    nn.Conv2d(dim_in, dim_out, 31, padding=6*rate, dilation=6*rate, bias=True),
    nn.BatchNorm2d(dim_out, momentum=bn_mom),
    nn.ReLU(inplace=True), 
  )
  self.branch3 = nn.Sequential(
    nn.Conv2d(dim_in, dim_out, 31, padding=12*rate, dilation=12*rate, bias=True),
    nn.BatchNorm2d(dim_out, momentum=bn_mom),
    nn.ReLU(inplace=True), 
  )
  self.branch4 = nn.Sequential(
    nn.Conv2d(dim_in, dim_out, 31, padding=18*rate, dilation=18*rate, bias=True),
    nn.BatchNorm2d(dim_out, momentum=bn_mom),
    nn.ReLU(inplace=True), 
  )
  self.branch5_conv = nn.Conv2d(dim_in, dim_out, 110,bias=True)
  self.branch5_bn = nn.BatchNorm2d(dim_out, momentum=bn_mom)
  self.branch5_relu = nn.ReLU(inplace=True)

  self.conv_cat = nn.Sequential(
    nn.Conv2d(dim_out*5, dim_out, 11, padding=0,bias=True),
    nn.BatchNorm2d(dim_out, momentum=bn_mom),
    nn.ReLU(inplace=True),  
  )

 def forward(self, x):
  [b, c, row, col] = x.size()
        #-----------------------------------------#
        #   一共五个分支
        #-----------------------------------------#
  conv1x1 = self.branch1(x)
  conv3x3_1 = self.branch2(x)
  conv3x3_2 = self.branch3(x)
  conv3x3_3 = self.branch4(x)
        #-----------------------------------------#
        #   第五个分支,全局平均池化+卷积
        #-----------------------------------------#
  global_feature = torch.mean(x,2,True)
  global_feature = torch.mean(global_feature,3,True)
  global_feature = self.branch5_conv(global_feature)
  global_feature = self.branch5_bn(global_feature)
  global_feature = self.branch5_relu(global_feature)
  global_feature = F.interpolate(global_feature, (row, col), None'bilinear'True)
  
        #-----------------------------------------#
        #   将五个分支的内容堆叠起来
        #   然后1x1卷积整合特征。
        #-----------------------------------------#
  feature_cat = torch.cat([conv1x1, conv3x3_1, conv3x3_2, conv3x3_3, global_feature], dim=1)
  result = self.conv_cat(feature_cat)
  return result

class DeepLab(nn.Module):
    def __init__(self, num_classes, backbone="xception", pretrained=False, downsample_factor=16):
        super(DeepLab, self).__init__()

        #----------------------------------#
        #   获得两个特征层
        #   浅层特征    [128,128,256]
        #   主干部分    [30,30,2048]
        #----------------------------------#
        self.backbone = xception(downsample_factor=downsample_factor, pretrained=pretrained)
        in_channels = 2048
        low_level_channels = 256


        #-----------------------------------------#
        #   ASPP特征提取模块
        #   利用不同膨胀率的膨胀卷积进行特征提取
        #-----------------------------------------#
        self.aspp = ASPP(dim_in=in_channels, dim_out=256, rate=16//downsample_factor)
        
        #----------------------------------#
        #   浅层特征边
        #----------------------------------#
        self.shortcut_conv = nn.Sequential(
            nn.Conv2d(low_level_channels, 481),
            nn.BatchNorm2d(48),
            nn.ReLU(inplace=True)
        )  

        self.cat_conv = nn.Sequential(
            nn.Conv2d(48+2562563, stride=1, padding=1),
            nn.BatchNorm2d(256),
            nn.ReLU(inplace=True),
            nn.Dropout(0.5),

            nn.Conv2d(2562563, stride=1, padding=1),
            nn.BatchNorm2d(256),
            nn.ReLU(inplace=True),

            nn.Dropout(0.1),
        )
        self.cls_conv = nn.Conv2d(256, num_classes, 1, stride=1)

    def forward(self, x):
        H, W = x.size(2), x.size(3)
        #-----------------------------------------#
        #   获得两个特征层
        #   low_level_features: 浅层特征-进行卷积处理
        #   x : 主干部分-利用ASPP结构进行加强特征提取
        #-----------------------------------------#
        low_level_features, x = self.backbone(x)
        x = self.aspp(x)
        low_level_features = self.shortcut_conv(low_level_features)
        
        #-----------------------------------------#
        #   将加强特征边上采样
        #   与浅层特征堆叠后利用卷积进行特征提取
        #-----------------------------------------#
        x = F.interpolate(x, size=(low_level_features.size(2), low_level_features.size(3)), mode='bilinear', align_corners=True)
        x = self.cat_conv(torch.cat((x, low_level_features), dim=1))
        x = self.cls_conv(x)
        x = F.interpolate(x, size=(H, W), mode='bilinear', align_corners=True)
        return x


测试结果

结语

「完整代码与训练结果请加入我们的星球。」

「感兴趣的可以加入我们的星球,获取更多数据集、网络复现源码与训练结果的」

alt 「加入前不要忘了在公众号首页领取优惠券哦!」

往期精彩

SENet实现遥感影像场景分类
SENet实现遥感影像场景分类
DFANet|实现遥感影像道路提取
DFANet|实现遥感影像道路提取
基于topformer实现遥感影像道路提取
基于topformer实现遥感影像道路提取
segformer实现多分类遥感影像语义分割
segformer实现多分类遥感影像语义分割
pyqt5实现语义分割GUI界面工具
pyqt5实现语义分割GUI界面工具
参考资料
[1]

WHU-Building-DataSets: https://study.rsgis.whu.edu.cn/pages/download/building_dataset.html

本文由 mdnice 多平台发布

  • 23
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 我们可以使用下面的代码来实现遥感影像中建筑物的自动提取:# 导入必要的库 from keras.applications.deeplabv3 import Deeplabv3 import numpy as np# 加载你的遥感图像 image = np.array(data)# 创建Deeplabv3模型实例 model = Deeplabv3(input_shape=(224, 224, 3), classes=1)# 运行模型 result = model.predict(image)# 解析结果,提取建筑物 buildings = result > 0.5 ### 回答2: 要使用deeplabv3网络实现遥感影像中建筑物的自动提取,首先需要安装相关的深度学习框架和库,如TensorFlow和Keras。然后按照以下步骤编写代码: 1. 导入所需的库和模块: ```python import numpy as np from PIL import Image import tensorflow as tf from tensorflow.keras.preprocessing import image from tensorflow.keras.applications.deeplab_v3 import preprocess_input ``` 2. 加载预训练的deeplabv3模型: ```python model = tf.keras.applications.DeepLabV3(weights='cityscapes') ``` 3. 加载遥感影像并进行预处理: ```python image_path = 'path_to_remote_sensing_image' remote_sensing_image = Image.open(image_path) remote_sensing_image = remote_sensing_image.resize((512, 512)) # 按需调整图像尺寸 remote_sensing_image_array = image.img_to_array(remote_sensing_image) remote_sensing_image_array = preprocess_input(remote_sensing_image_array) remote_sensing_image_array = np.expand_dims(remote_sensing_image_array, axis=0) ``` 4. 利用模型进行建筑物的自动提取: ```python mask = model.predict(remote_sensing_image_array) predicted_mask = np.argmax(mask, axis=-1) predicted_mask = np.squeeze(predicted_mask) ``` 5. 可选:将预测的掩码转换为二进制图像,便于可视化或后续分析: ```python building_mask = np.zeros_like(predicted_mask) building_mask[predicted_mask == 2] = 255 building_mask = Image.fromarray(building_mask.astype('uint8')) ``` 这样,我们就完成了使用deeplabv3网络实现遥感影像中建筑物的自动提取。您可以根据具体的需求对代码进行进一步的优化和调整。 ### 回答3: 使用DeepLabv3网络实现遥感影像中建筑物的自动提取可以分为以下几个步骤: 1. 数据准备:获取并准备遥感影像的训练集和测试集,需要包含有标注的建筑物区域。训练集应当包括影像及其对应的建筑物掩码。 2. 搭建DeepLabv3网络:使用Python及深度学习框架(如TensorFlow或PyTorch)搭建DeepLabv3网络。DeepLabv3是一个基于卷积神经网络的语义分割模型,可以实现像素级别的分类。通过将影像输入网络,可以得到每个像素点属于建筑物的概率。 3. 训练网络:使用训练集对DeepLabv3网络进行训练。训练过程中,可以使用交叉熵损失函数等评估网络输出的正确性,并使用反向传播算法更新网络参数,使网络逐渐优化。 4. 测试网络:使用测试集对训练好的DeepLabv3网络进行测试。将测试集中的影像输入网络,得到像素级别的建筑物预测结果。可以使用评价指标(如准确率、召回率、F1-Score等)来评估模型的性能。 5. 后处理:对网络输出的建筑物预测结果进行后处理,例如通过阈值化将概率转化为二值(建筑物/非建筑物),去除噪声等。 6. 应用模型:将训练好的DeepLabv3模型应用到新的遥感影像中,即可实现对该影像中建筑物的自动提取。 总结起来,使用DeepLabv3网络实现遥感影像中建筑物的自动提取需要进行数据准备、网络搭建、训练、测试及后处理等步骤。这个过程中,需要注意数据的准备和标注质量,网络的选择和配置,以及评估模型性能的指标选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DataAssassin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值