利用PaddleSeg框架进行图像分割


文章创作部分参见 飞桨深度学习平台

一、基础理论

1.神经网络

对于线性回归,大家并不陌生,假设样本与输出关系如下:
在这里插入图片描述
模型的求解就是通过数据拟合出 w j w_{j} wj b b b。我们可以将这种线性关系等价于一系列线性神经元(神经网络的标准结构中每个神经元由加权和与非线性变换构成,然后将多个神经元分层排列并连接形成神经网络。线性回归模型可以认为是神经网络模型的一种极简特例,是一个只有加权和、没有非线性变换的神经元)
在这里插入图片描述
每个神经元的加权系数就是线性回归模型中的 w j w_{j} wj
人工神经网络不在是简单地单层结构,而应包括多个神经网络层,如卷积层、全连接层、LSTM等,每一层又包括很多神经元,超过三层的非线性神经网络都可以被称为深度神经网络。通俗的讲,深度学习的模型可以视为是输入到输出的映射函数,如图像到高级语义(美女)的映射,足够深的神经网络理论上可以拟合任何复杂的函数。因此神经网络非常适合学习样本数据的内在规律和表示层次,对文字、图像和语音任务有很好的适用性。

在这里插入图片描述
类比于人的大脑,神经网络主要包括两部分:
(1)神经元:即神经网络中的节点,具有相应的权重
(2)信号的传输:通俗来说就是某种激活介质,让数据到达此神经元之后能够向后传播,激活函数来承担此功能。

2.卷积神经网络

对于计算机视觉这样一门学科来说,我们的样本不再是单一数据,而是许许多多图片或视频信号,如果图片中的每一个像素值作为一个样本观测值的话,加上一张图片具有多个输入通道,我们自然不能对每个像素点都设置相应的神经元。卷积神经网络便是在这样的背景之下提出的一种新式深度神经网络。
卷积神经网络(Convolutional Neural Networks, CNN)是计算机视觉技术最经典的模型结构。利用卷积神经网络,我们得以完成以下复杂任务:
(a) 图像分类:用于识别图像中物体的类别(如:bottle、cup、cube)
(b) 目标检测:用于检测图像中每个物体的类别,并准确标出它们的位置。
© 图像语义分割:用于标出图像中每个像素点所属的类别,属于同一类别的像素点用一个颜色标识。

在这里插入图片描述
完整的卷积神经网络应该包括以下方面:
(1)卷积:利用图像卷积对图像像素点进行特征提取
在这里插入图片描述

(2)池化:用总体特征代替局部特征,能有效的减小神经元的个数,节省存储空间并提高计算效率
在这里插入图片描述
(2)激活函数:增加非线性

在这里插入图片描述
卷积神经网络的关键在于搭建网络,即如何设置卷积层、池化层以及相应的激活函数,目前较为主流的网络主要如下:
DeepLabv3+,U-Net,PSPNet,HRNet,Fast-SCNN,BiSeNetv2,OCRNet等等

在这里插入图片描述

二、利用PaddleSeg进行图像分割

1.搭建paddlepadlle环境

在这里插入图片描述

(1)我们需要进入paddle实训平台AI Studio进行项目创建,并进行相应数据集的挂载。
(平台提供种类繁多的数据集,我们可以挂载任意自己喜欢的数据集,注意需要是图像分割数据集)
(2)下载PaddleSeg源码文件

git clone https://github.com/PaddlePaddle/PaddleSeg

网速不好也可进行如下下载:

git clone https://gitee.com/paddlepaddle/PaddleSeg.git

如果是需要API操作,需要下载相应的依赖库,这里我们采用Linnux操作方式就没有下载相应的依赖库。

pip install paddleseg

2.数据配置

首先先解压数据集:

!unzip -oq /home/aistudio/data/data95249/train_image.zip -d data/
!unzip -oq /home/aistudio/data/data95249/val.zip -d data/

推荐将我们的数据配置成以下格式:
在这里插入图片描述
即:将我们的图片和标签以及带有对应关系的txt文本放在同一路径下(并不是强制,这是为了我们后续在配置文件的过程中方便填写路径)
还有就是小伙伴在进行images和labels创建的时候发现copy文件之后这里面并不是按顺序images1、images2、images3…的顺序排列,有可能是images3、images5、images1…相应的labels文件夹也不是这样依次排列,这是由于多进程运行方式导致字节小的图片先复制到指定文件夹中,而字节大的慢一些。
这里我们可以巧妙利用一些判断,让images和labels能够对应的排列。


import numpy as np
import os
import shutil
from utils import get_path
from utils import get_test_data
eval_num=1000
image_size=(224,224)
train_images_path="data/train_image"
label_images_path="data/train_50k_mask"
images=np.array(get_path(train_images_path))
labels=np.array(get_path(label_images_path))
images=np.expand_dims(np.array(get_path(train_images_path)),axis=1)
labels=np.expand_dims(np.array(get_path(label_images_path)),axis=1)
data=np.array(np.concatenate((images,labels),axis=1))
np.random.shuffle(data)
images=data[:,0]
labels=data[:,1]

以上操作获取的解压之后图片和标签的源路径,并且数据合并之后进行打乱并不会丢失图像和标签的对应关系。

接下来便是构造我们需要的数据格式:
我们先创建相应的文件夹

!mkdir data/custom_dataset/
!mkdir data/custom_dataset/labels/
!mkdir data/custom_dataset/images/

接下来很关键的一步,移动拷贝原图片和标签到指定的文件夹,注意:这里同时对images和labels同时操作,发现images大小较大于是将其先移动拷贝,采用if判断保证每次只移动一次(即每次仅仅移动一张image和一张label,模拟了单进程数据传输方式。

a=0
for i in range(len(images)):
     shutil.copyfile(images[i],'data/custom_dataset/images/'+str(i)+'.png')
     shutil.copyfile(labels[i],'data/custom_dataset/labels/'+str(i)+'.png') 
     if len(os.listdir('data/custom_dataset/images'))>a:
         a=len(os.listdir('data/custom_dataset/images'))
         continue

接下来对放置好的文件夹下创建包含对应关系的txt文件(由于上一步骤保证了新文件夹下images和labels的对应关系,这一步仅仅需要按照路径下文件名依次写入txt文件。

def write_file(mode, images, labels):
    with open('data/custom_dataset/{}.txt'.format(mode), 'w') as f:
        for i in range(len(images)):
            f.write('{} {}\n'.format(images[i], labels[i]))
def get_path_labels(image_path):
    files=[]
    for image_name in os.listdir(image_path):
            if image_name.endswith('.png') and not image_name.startswith('.'):
                files.append(os.path.join('/home/aistudio/data/custom_dataset/labels/',image_name))
    return sorted(files)
def get_path_images(image_path):  
    files=[]
    for image_name in os.listdir(image_path):
            if image_name.endswith('.png') and not image_name.startswith('.'):
                files.append(os.path.join('/home/aistudio/data/custom_dataset/images/',image_name))
    return sorted(files)

images_path_new='data/custom_dataset/images/'
#标签路径
label_path_new='data/custom_dataset/labels/'
images_new=np.array(get_path_images(images_path_new))
labels_new=np.array(get_path_labels(label_path_new))
write_file('train1', images_new[:-eval_num], labels_new[:-eval_num])
write_file('val1', images_new[-eval_num:], labels_new[-eval_num:])

到此,以上操作完成后custom_dataset文件夹下结构应如下:
在这里插入图片描述
到此,数据配置结束。

3.模型配置

配置模型前,需要参阅paddle官方各模型配置情况:
在这里插入图片描述
打勾的模型即需要配置相应的骨干网络。有关更详细的模型配置,可以参阅Model Zoo
为配置我们的模型文件,需要进入以下目录:(如果未出现PaddleSeg文件夹,则重复步骤一下载PaddleSeg源码文件)

在这里插入图片描述
为方便起见,我们可以直接对以下路径下的文件进行修改PaddleSeg/configs/quick_start/bisenet_optic_disc_512x512_1k.yml
下面给出一个实例:

batch_size: 16
iters: 50000  #模型迭代的次数

train_dataset:
  type: Dataset
  dataset_root: /home/aistudio/data/custom_dataset
  train_path: /home/aistudio/data/custom_dataset/train1.txt
  num_classes: 2
  transforms:
    - type: Resize
      target_size: [224, 224]
    - type: RandomHorizontalFlip
    - type: RandomVerticalFlip
    - type: RandomBlur
    - type: RandomDistort
      brightness_range: 0.4
      contrast_range: 0.4
      saturation_range: 0.4
    - type: Normalize
  
  mode: train

val_dataset:
  type: Dataset
  dataset_root: /home/aistudio/data/custom_dataset
  val_path: /home/aistudio/data/custom_dataset/val1.txt
  num_classes: 2
  transforms:
    - type: Resize  
      target_size: [224, 224]  
    - type: Normalize
  mode: val

optimizer: #设定优化器的类型
  type: sgd #采用SGD(Stochastic Gradient Descent)随机梯度下降方法为优化器
  momentum: 0.9 #动量
  weight_decay: 4.0e-5 #权值衰减,使用的目的是防止过拟合

learning_rate: #设定学习率
  value: 0.01  #初始学习率
  decay:
    type: poly  #采用poly作为学习率衰减方式。
    power: 0.9  #衰减率
    end_lr: 0   #最终学习率

loss: #设定损失函数的类型
  types:
    - type: CrossEntropyLoss #损失函数类型
  coef: [1]
  #BiseNetV2有4个辅助loss,加上主loss共五个,1表示权重 all_loss = coef_1 * loss_1 + .... + coef_n * loss_n

model:
  type: DeepLabV3P
  backbone:
    type: ResNet101_vd
    output_stride: 8
    multi_grid: [1, 2, 4]
    pretrained:  https://bj.bcebos.com/paddleseg/dygraph/resnet101_vd_ssld.tar.gz
  num_classes: 2
  backbone_indices: [0, 3]
  aspp_ratios: [1, 12, 24, 36]
  aspp_out_channels: 256
  align_corners: True
  pretrained: null

可以发现我这里用到了DeepLabV3P模型,需要的骨干网络为ResNet101_vd
如果需要采用其他模型也可设置如下:

batch_size: 16
iters: 10000

train_dataset:
  type: Dataset
  dataset_root: /home/aistudio/data/custom_dataset
  train_path: /home/aistudio/data/custom_dataset/train1.txt
  num_classes: 2
  transforms:
    - type: Resize
      target_size: [224, 224]
    - type: RandomHorizontalFlip
    - type: RandomVerticalFlip
    - type: RandomDistort
      brightness_range: 0.1
      contrast_range: 0.1
      saturation_range: 0.1
    - type: Normalize
  mode: train

val_dataset:
  type: Dataset
  dataset_root: /home/aistudio/data/custom_dataset
  val_path: /home/aistudio/data/custom_dataset/val1.txt
  transforms:
    - type: Resize
      target_size: [224, 224]
    - type: Normalize
  mode: val
  num_classes: 2

test_dataset:
  type: Dataset
  dataset_root: /home/aistudio/data/test_image
  val_path: home/aistudio/data/custom_dataset/test1.txt
  transforms:
    - type: Normalize
  mode: test
  num_classes: 2

optimizer:
  type: sgd
  momentum: 0.9
  weight_decay: 4.0e-5

learning_rate:
  value: 0.01
  decay:
    type: poly
    power: 0.9
    end_lr: 0.0

loss:
  types:
    - type: CrossEntropyLoss
  coef: [1]

model:
  type: UNet_3Plus
  num_classes: 2
  use_deconv: False
  pretrained: Null

这里用到了UNet_3Plus模型,无须骨干网络。

以上为配置文件的整体框架,若需查看详细配置属性,可参见配置项
如需完整运行代码,我参照我上述给出的两个配置示例,修改dataset_root(文件根目录)
train_path(训练集txt路径)
val_path(验证集路径)

在此,简单介绍一下配置文件的一些主要模块:
1.transforms为数据增强配置,包含图像归一化、尺寸调整、随机翻转等类,可根据PaddleSeg/paddleseg/transforms/transforms.py路径下文件类属性输入参数格式配置自己的数据增强模块。
2.optimizer为优化器选项,目前只支持’sgd’和’adam’
3.learning_rate为学习率,这里采用PolynomialDecay
4.loss是一个关键环节,这里选择交叉熵

4.文件修改

由于目前的标签大多数为三个通道,但我们进行前向计算与反向梯度传播的过程中仅仅只需要一个通道
即我们实际的标签维度(N,3,H,W)需要为(N,1,H,W),并且由于PaddleSeg源代码在进行计算的过程中将通道变成了(N,H,W,C),于是我们可以在源代码上进行修改,否则运行过程中可能出现维度不同一而报错。我们需要对源码进行一些修改:
(1)定位到PaddleSeg/paddleseg/models/losses/cross_entropy_loss.py,修改部分代码如下:
在这里插入图片描述
(2)定位到PaddleSeg/paddleseg/core/val.py,修改部分代码如下:
在这里插入图片描述

5.模型训练

!python PaddleSeg/train.py --config PaddleSeg/configs/quick_start/bisenet_optic_disc_512x512_1k.yml --save_interval 5000 --use_vdl

对于这里不同配置项的含义也可参阅帮助文档

6.模型评估

!python PaddleSeg/val.py --config PaddleSeg/configs/quick_start/bisenet_optic_disc_512x512_1k.yml --model_path output/iter_20000/model.pdparams 

由于没有设置测试集,可以自行划分测试集进行测试。

  • 6
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值