unet算法学习入门以及基于pytorch实现的unet图像语义分割算法(数据集天池地表建筑物识别)

基本概念

卷积:计算权重矩阵和扫描所得的数据矩阵的乘积,然后把结果汇总成一个输出像素。
在这里插入图片描述

池化:池化过程在一般卷积过程后。池化(pooling) 的本质,其实就是采样。Pooling 对于输入的 Feature Map,选择某种方式对其进行降维压缩,以加快运算速度。采用较多的一种池化过程叫最大池化(Max Pooling)。
在这里插入图片描述
卷积相关计算公式
在这里插入图片描述

填充:前面可以发现,输入图像与卷积核进行卷积后的结果中损失了部分值,输入图像的边缘被“修剪”掉了(边缘处只检测了部分像素点,丢失了图片边界处的众多信息)。这是因为边缘上的像素永远不会位于卷积核中心,而卷积核也没法扩展到边缘区域以外。通过填充的方法,当卷积核扫描输入数据时,它能延伸到边缘以外的伪像素,从而使输出和输入size相同。
在这里插入图片描述

步长(Stride):滑动卷积核时,我们会先从输入的左上角开始,每次往左滑动一列或者往下滑动一行逐一计算输出,我们将每次滑动的行数和列数称为Stride。
上采样和下采样
缩小图像(或称为下采样(subsampled)或降采样(downsampled))的主要目的有两个:1、使得图像符合显示区域的大小;2、生成对应图像的缩略图。
放大图像(或称为上采样(upsampling)或图像插值(interpolating))的主要目的是放大原图像,从而可以显示在更高分辨率的显示设备上。

Unet

概述:图像处理语义分割算法,语义分割需要判断图像每个像素点的类别,进行精确分割。语义分割目前在自动驾驶、自动抠图、医疗影像等领域有着比较广泛的应用。
网络结构:前半部分就是特征提取,后半部分是上采样(编码器-解码器结构)
Encoder:左半部分,由两个3x3的卷积层(RELU)再加上一个2x2的maxpooling层组成一个下采样的模块(后面代码可以看出);
Decoder:有半部分,由一个上采样的卷积层(去卷积层)+特征拼接concat+两个3x3的卷积层(ReLU)反复构成;
在这里插入图片描述

代码实现

  • 框架:pytorch
  • 网络接口:UNET
  • 数据集:天池地表建筑物识别
  • 数据集地址以及项目简介:https://tianchi.aliyun.com/competition/entrance/531872/information

天池数据MASK是CSV格式的,需要转换后才能使用。

def create_sample():
    # 训练标签数据csv转图片
    train_mask = pd.read_csv("./build_data/source/train_mask.csv", sep='\t', names=['name', 'mask'])
    for name,mask in train_mask.values:
        if(pd.isnull(mask)):
            r_dir =TRAIN_IMG_DIR+ '/' +name
            if(os.path.exists(r_dir)):
                os.remove(r_dir)
                print("删除"+r_dir)
            continue;
        mask = rle_decode(mask)
        cv2.imwrite(TRAIN_MASK_DIR+'/'+name.rsplit(".",maxsplit=1)[0]+"_mask.jpg", mask*255)

转换后的MSKE图片
在这里插入图片描述

UNet网络结构如下代码定义

#定义UNet网络
class UNet(nn.Module):
    def __init__(self):
        super(UNet, self).__init__()
        self.max_pool_2x2 = nn.MaxPool2d(kernel_size=2, stride=2)
        self.down_conv_1 = double_conv(3, 64)
        self.down_conv_2 = double_conv(64, 128)
        self.down_conv_3 = double_conv(128, 256)
        self.down_conv_4 = double_conv(256, 512)
        self.down_conv_5 = double_conv(512, 1024)

        self.up_trans_1 = nn.ConvTranspose2d(
            in_channels=1024,
            out_channels=512,
            kernel_size=2,
            stride=2
        )
        self.up_conv_1 = double_conv(1024, 512)

        self.up_trans_2 = nn.ConvTranspose2d(
            in_channels=512,
            out_channels=256,
            kernel_size=2,
            stride=2
        )
        self.up_conv_2 = double_conv(512, 256)

        self.up_trans_3 = nn.ConvTranspose2d(
            in_channels=256,
            out_channels=128,
            kernel_size=2,
            stride=2
        )
        self.up_conv_3 = double_conv(256, 128)

        self.up_trans_4 = nn.ConvTranspose2d(
            in_channels=128,
            out_channels=64,
            kernel_size=2,
            stride=2
        )
        self.up_conv_4 = double_conv(128, 64)

        self.out = nn.Conv2d(
            in_channels=64,
            out_channels=1,
            kernel_size=1
        )

    def forward(self, image):
        # expected size
        # encoder (Normal convolutions decrease the size)
        x1 = self.down_conv_1(image)
        # print("x1 "+str(x1.shape))
        x2 = self.max_pool_2x2(x1)
        # print("x2 "+str(x2.shape))
        x3 = self.down_conv_2(x2)
        # print("x3 "+str(x3.shape))
        x4 = self.max_pool_2x2(x3)
        # print("x4 "+str(x4.shape))
        x5 = self.down_conv_3(x4)
        # print("x5 "+str(x5.shape))
        x6 = self.max_pool_2x2(x5)
        # print("x6 "+str(x6.shape))
        x7 = self.down_conv_4(x6)
        # print("x7 "+str(x7.shape))
        x8 = self.max_pool_2x2(x7)
        # print("x8 "+str(x8.shape))
        x9 = self.down_conv_5(x8)
        # print("x9 "+str(x9.shape))

        # decoder (transposed convolutions increase the size)
        x = self.up_trans_1(x9)
        x = addPadding(x7, x)
        x = self.up_conv_1(torch.cat([x7, x], 1))

        x = self.up_trans_2(x)
        x = addPadding(x5, x)
        x = self.up_conv_2(torch.cat([x5, x], 1))

        x = self.up_trans_3(x)
        x = addPadding(x3, x)
        x = self.up_conv_3(torch.cat([x3, x], 1))

        x = self.up_trans_4(x)
        x = addPadding(x1, x)
        x = self.up_conv_4(torch.cat([x1, x], 1))

        x = self.out(x)
        # print(x.shape)
        return x.to(DEVICE)

一些其他代码就不贴了,目前模型还在训练ing,因为显卡问题,所以epoch和batch_size设置都比较小。
在这里插入图片描述
需要获取全部源码可以关注微信公众号<是云开源>,回复《unet》获取。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/m0_47220500/article/details/121487582
今日推荐