PaddleSeg实现自动驾驶语义分割
PaddleSeg使用PP-LiteSeg完成自动驾驶语义分割
PaddleSeg实现自动驾驶语义分割
本示例的主要流程如下:
- 准备环境:使用PaddleSeg的软件环境
- 准备数据:用户如何准备、整理自定义数据集
- 模型训练:训练配置和启动训练命令
- 可视化训练过程:使用VDL展示训练过程
- 模型评估:评估模型效果
- 模型预测与可视化:使用训练好的模型进行预测,同时对结果进行可视化
- 模型导出:如何导出可进行部署的模型
- 模型部署:快速使用Python实现高效部署
1 环境安装
# 克隆PaddleSeg仓库,国内可以直接使用gitee的库
!git clone https://gitee.com/paddlepaddle/PaddleSeg.git
# 安装其他依赖
%cd PaddleSeg
!pip install -r requirements.txt
2 数据准备
2.1 数据介绍
Semantic Segmentation for Self Driving Cars数据地址
该数据集提供通过CARLA自动驾驶汽车模拟器捕获的数据图像和标记语义分割。这些数据是作为Lyft Udacity Challenge的一部分生成的。此数据集可用于训练 ML 算法,以识别图像中汽车、道路等的语义分割。
该数据有5组1000张图像和相应的标签。本项目合并了AB两组数据作为训练集和验证集。
# 解压数据到PaddleSeg/dataset/文件夹
%cd ~
!mkdir PaddleSeg/dataset/
!unzip -d PaddleSeg/dataset/dataA_B data/data151864/dataA_B.zip
2.2 数据可视化
本数据集是三通道的,只取mask[:,:,0]即第一个通道的值作为label。
%cd ~/PaddleSeg
import pandas as pd
import numpy as np
import random
import os
import matplotlib.pyplot as plt
img_path = 'dataset/dataA_B/images'
mask_path = 'dataset/dataA_B/annotations'
image_list = os.listdir(img_path)
img_name = random.choice(image_list)
img = plt.imread(os.path.join(img_path,img_name))
mask = plt.imread(os.path.join(mask_path,img_name))
fig, axs = plt.subplots(1,2,figsize=(10,5))
axs[0].imshow(img)
axs[1].imshow(mask[:,:,0])
for a in axs:
a.axis('off')
plt.show()
/home/aistudio/PaddleSeg
# 输出mask三个通道的值
print(mask.shape)
print("==============================")
print(mask[:,:,0])
print("==============================")
print(mask[:,:,1])
print("==============================")
print(mask[:,:,2])
(600, 800, 3)
==============================
[[0. 0. 0. ... 0. 0. 0. ]
[0. 0. 0. ... 0. 0. 0. ]
[0. 0. 0. ... 0. 0. 0. ]
...
[0.03921569 0.03921569 0.03921569 ... 0.03921569 0.03921569 0.03921569]
[0.03921569 0.03921569 0.03921569 ... 0.03921569 0.03921569 0.03921569]
[0.03921569 0.03921569 0.03921569 ... 0.03921569 0.03921569 0.03921569]]
==============================
[[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
...
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]]
==============================
[[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
...
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]
[0. 0. 0. ... 0. 0. 0.]]
#找出掩码中唯一的值,即标签种类数量
np.unique(mask * 255)
array([ 0., 1., 2., 3., 5., 6., 7., 8., 9., 10., 11., 12.],
dtype=float32)
# 标签
labels = ['Unlabeled','Building','Fence','Other',
'Pedestrian', 'Pole', 'Roadline', 'Road',
'Sidewalk', 'Vegetation', 'Car','Wall',
'Traffic sign']
for i in range(13):
mask = plt.imread('dataset/dataA_B/annotations/02_00_000.png')*255
#如果等一i就为255其他为0
mask = np.where(mask == i, 255, 0)
#取mask
mask1 = mask[:,:,0]
plt.title(f'class: {i} {labels[i]}')
plt.imshow(mask1)
plt.show()
2.3 数据处理
PaddleSeg采用单通道的标注图片,每一种像素值代表一种类别,像素标注类别需要从0开始递增,例如0,1,2,3表示有4种类别。
注: 标注图像请使用PNG无损压缩格式的图片。标注类别最多为256类。
以上是PaddleSeg的标注协议,即我们的数据需要满足是单通道的标注图片,所以要将数据变为单通道的灰度图。但针对灰度图不仅只能看见全黑的效果,还存在相应的弊端:
- 对图像标注后,无法直接观察标注是否正确。
- 模型测试过程无法直接判断分割的实际效果。
PaddleSeg支持伪彩色图作为标注图片,在原来的单通道图片基础上,注入调色板。在基本不增加图片大小的基础上,却可以显示出彩色的效果。
同时PaddleSeg也兼容灰度图标注,用户原来的灰度数据集可以不做修改,直接使用。
本项目是将图像转换为灰度图再转换为伪彩色标注图来做处理。
# 将三通道变成单通道。
import os
import os.path as osp
import sys
import numpy as np
from PIL import Image
input = 'dataset/dataA_B/annotations'
# os.walk()方法用于通过在目录树中游走输出在目录中的文件名
for fpath, dirs, fs in os.walk(input):
print(fpath)
for f in fs:
try:
path = osp.join(fpath, f)
# _output_dir = fpath.replace(input, '')
# _output_dir = _output_dir.lstrip(os.path.sep)
image = Image.open(path)
image,_,_ = image.split()
image.save(path)
except:
continue
print("已变为单通道!")
dataset/dataA_B/annotations
已变为单通道!
# 转换为单通道灰度图可视化
img_path = 'dataset/dataA_B/images'
mask_path = 'dataset/dataA_B/annotations'
image_list = os.listdir(img_path)
img_name = random.choice(image_list)
img = plt.imread(os.path.join(img_path,img_name))
mask = plt.imread(os.path.join(mask_path,img_name))
fig, axs = plt.subplots(1,2,figsize=(10,5))
axs[0].imshow(img)
axs[1].imshow(mask)
for a in axs:
a.axis('off')
plt.show()
灰度标注转换为伪彩色标注
可以直接使用PaddleSeg提供的转换工具。
%cd ~/PaddleSeg
!python tools/gray2pseudo_color.py dataset/dataA_B/annotations/ dataset/dataA_B/annotations/
img_path = 'dataset/dataA_B/images'
mask_path = 'dataset/dataA_B/annotations'
image_list = os.listdir(img_path)
img_name = random.choice(image_list)
img = plt.imread(os.path.join(img_path,img_name))
mask = plt.imread(os.path.join(mask_path,img_name))
fig, axs = plt.subplots(1,2,figsize=(10,5))
axs[0].imshow(img)
axs[1].imshow(mask)
for a in axs:
a.axis('off')
plt.show()
2.4 数据集划分
以下为数据的种类标签,即生成labels.txt的值。
Unlabeled
Building
Fence
Other
Pedestrian
Pole
Roadline
Road
Sidewalk
Vegetation
Car
Wall
Traffic sign
# 使用PaddleSeg提供的划分数据集的工具
%cd ~/PaddleSeg
!python tools/split_dataset_list.py dataset/dataA_B images annotations --split 0.7 0.3 0 --format png png --label_class 'Unlabeled' 'Building' 'Fence' 'Other' 'Pedestrian' 'Pole' 'Roadline' 'Road' 'Sidewalk' 'Vegetation' 'Car' 'Wall' 'Traffic sign'
3 模型训练
3.1 PP-LiteSeg模型介绍
本示例选择PP-LiteSeg模型进行训练。
PP-LiteSeg是PaddleSeg团队自研的轻量化模型,在Cityscapes数据集上超越其他模型,实现最优的精度和速度平衡。 具体而言,PP-LiteSeg模型沿用编解码架构,设计灵活的Decoder模块(FLD)、统一注意力融合模块(UAFM)和简易PPM上下文模块(SPPM),实现高精度和高效率的实时语义分割。
PP-LiteSeg模型的结构如下图。更多详细介绍,请参考链接。
3.2 配置文件详解
PaddleSeg提供配置化驱动进行模型训练、测试和预测等,配置文件是其中的关键。
PaddleSeg的配置文件包括超参、训练数据集、验证数据集、优化器、损失函数、模型等信息。所有的配置文件在PaddleSeg/configs文件夹下面。大家可以灵活修改配置文件的内容,如自定义模型使用的骨干网络、模型使用的损失函数以及关于网络结构等配置,自定义配置数据处理的策略,如改变尺寸、归一化和翻转等数据增强的策略。
重点参数说明:
- 在PaddleSeg的配置文件给出的学习率中,除了"pp_liteseg_optic_disc_512x512_1k.yml"中为单卡学习率外,其余配置文件中均为4卡的学习率,如果用户是单卡训练,则学习率设置应变成原来的1/4。
- 在PaddleSeg中的配置文件,给出了多种损失函数:CrossEntropy Loss、BootstrappedCrossEntropy Loss、Dice Loss、BCE Loss、OhemCrossEntropyLoss、RelaxBoundaryLoss、OhemEdgeAttentionLoss、Lovasz Hinge Loss、Lovasz Softmax Loss,用户可根据自身需求进行更改。
- 配置文件解读如下。
batch_size: 4 #设定batch_size的值即为迭代一次送入网络的图片数量,一般显卡显存越大,batch_size的值可以越大
iters: 1000 #模型迭代的次数
train_dataset: #训练数据设置
type: Dataset #数据集名字
dataset_root: data/optic_disc_seg #数据集路径
train_path: data/optic_disc_seg/train_list.txt #数据集中用于训练的标识文件
num_classes: 2 #指定目标的类别个数(背景也算为一类)
mode: train #表示用于训练
transforms: #数据预处理/增强的方式
- type: ResizeStepScaling #将原始图像和标注图像随机缩放为0.5~2.0倍
min_scale_factor: 0.5
max_scale_factor: 2.0
scale_step_size: 0.25
- type: RandomPaddingCrop #从原始图像和标注图像中随机裁剪512x512大小
crop_size: [512, 512]
- type: RandomHorizontalFlip #采用水平反转的方式进行数据增强
- type: RandomDistort #亮度、对比度、饱和度随机变动
brightness_range: 0.5
contrast_range: 0.5
saturation_range: 0.5
- type: Normalize #将图像归一化
val_dataset: #验证数据设置
type: Dataset #数据集名字
dataset_root: data/optic_disc_seg #数据集路径
val_path: data/optic_disc_seg/val_list.txt #数据集中用于验证的标识文件
num_classes: 2 #指定目标的类别个数(背景也算为一类)
mode: val #表示用于验证
transforms: #数据预处理/增强的方式
- type: Normalize #图像进行归一化
optimizer: #设定优化器的类型
type: sgd #采用SGD(Stochastic Gradient Descent)随机梯度下降方法为优化器
momentum: 0.9 #动量
weight_decay: 4.0e-5 #权值衰减,使用的目的是防止过拟合
lr_scheduler: # 学习率的相关设置
type: PolynomialDecay # 一种学习率类型。共支持12种策略
learning_rate: 0.01
power: 0.9
end_lr: 0
loss: #设定损失函数的类型
types:
- type: CrossEntropyLoss #损失函数类型
coef: [1, 1, 1] # PP-LiteSeg有一个主loss和两个辅助loss,coef表示权重: total_loss = coef_1 * loss_1 + .... + coef_n * loss_n
model: #模型说明
type: PPLiteSeg #设定模型类别
backbone: # 设定模型的backbone,包括名字和预训练权重
type: STDC2
pretrained: https://bj.bcebos.com/paddleseg/dygraph/PP_STDCNet2.tar.gz
训练前要修改下方配置文件才能运行 !!!!
我们的配置,使用的configs/pp_liteseg/pp_liteseg_stdc1_camvid_960x720_10k.yml
文件,并修改了数据配置(替换文件的相应部分即可)。
train_dataset:
type: Dataset
dataset_root: dataset/dataA_B
num_classes: 13
mode: train
train_path: dataset/dataA_B/train.txt
transforms:
- type: ResizeStepScaling
min_scale_factor: 0.5
max_scale_factor: 2.5
scale_step_size: 0.25
- type: RandomPaddingCrop
crop_size: [960, 720]
- type: RandomHorizontalFlip
- type: RandomDistort
brightness_range: 0.5
contrast_range: 0.5
saturation_range: 0.5
- type: Normalize
val_dataset:
type: Dataset
dataset_root: dataset/dataA_B
num_classes: 13
mode: val
val_path: dataset/dataA_B/val.txt
transforms:
- type: Normalize
主要关注的参数:
- type的参数是Dataset,代表的是建议的数据格式;
- dataset_root路径为包含label和image所在的路径;在示例中为:- - dataset_root: dataset/optic_disc_seg
- train_path为txt的路径;在示例中为:train_path: dataset/optic_disc_seg/train_list.txt
- num_classes为类别(背景也算为一类);
- transform是对数据的预处理的策略,用户可根据自己的实际需要改动
3.3 训练
训练参数解析:
参数名 | 用途 | 是否必选项 | 默认值 |
---|---|---|---|
iters | 训练迭代次数 | 否 | 配置文件中指定值 |
batch_size | 单卡batch size | 否 | 配置文件中指定值 |
learning_rate | 初始学习率 | 否 | 配置文件中指定值 |
config | 配置文件 | 是 | - |
save_dir | 模型和visualdl日志文件的保存根路径 | 否 | output |
num_workers | 用于异步读取数据的进程数量, 大于等于1时开启子进程读取数据 | 否 | 0 |
use_vdl | 是否开启visualdl记录训练数据 | 否 | 否 |
save_interval | 模型保存的间隔步数 | 否 | 1000 |
do_eval | 是否在保存模型时启动评估, 启动时将会根据mIoU保存最佳模型至best_model | 否 | 否 |
log_iters | 打印日志的间隔步数 | 否 | 10 |
resume_model | 恢复训练模型路径,如:output/iter_1000 |
否 | None |
keep_checkpoint_max | 最新模型保存个数 | 否 | 5 |
训练后的模型参数在 /work 文件夹下
# 修改好配置文件后才能运行。
%cd ~/PaddleSeg
!export CUDA_VISIBLE_DEVICES=0
!python train.py \
--config configs/pp_liteseg/pp_liteseg_stdc1_camvid_960x720_10k.yml \
--do_eval \
--use_vdl \
--save_interval 500 \
--save_dir output
4 可视化
5 模型评估
!python val.py \
--config configs/pp_liteseg/pp_liteseg_stdc1_camvid_960x720_10k.yml \
--model_path output/best_model/model.pdparams
在图像分割领域中,评估模型质量主要是通过三个指标进行判断,准确率
(acc)、平均交并比
(Mean Intersection over Union,简称mIoU)、Kappa系数
。
- 准确率:指类别预测正确的像素占总像素的比例,准确率越高模型质量越好。
- 平均交并比:对每个类别数据集单独进行推理计算,计算出的预测区域和实际区域交集除以预测区域和实际区域的并集,然后将所有类别得到的结果取平均。在本例中,正常情况下模型在验证集上的mIoU指标值会达到0.80以上,显示信息示例如下所示,第3行的mIoU=0.8526即为mIoU。
- Kappa系数:一个用于一致性检验的指标,可以用于衡量分类的效果。kappa系数的计算是基于混淆矩阵的,取值为-1到1之间,通常大于0。其公式如下所示,P0P_0P0为分类器的准确率,PeP_eP**e为随机分类器的准确率。Kappa系数越高模型质量越好。
随着评估脚本的运行,最终打印的评估日志如下。
2022-06-29 10:53:04 [INFO] [EVAL] #Images: 600 mIoU: 0.7103 Acc: 0.9566 Kappa: 0.9463 Dice: 0.8022
2022-06-29 10:53:04 [INFO] [EVAL] Class IoU:
[0.9473 0.9162 0.4943 0.6247 0.1106 0.5114 0.6477 0.9585 0.8975 0.8421
0.969 0.7128 0.6018]
2022-06-29 10:53:04 [INFO] [EVAL] Class Precision:
[0.9755 0.9618 0.7631 0.7762 0.8018 0.8356 0.8263 0.9765 0.9447 0.9007
0.9738 0.8861 0.8673]
2022-06-29 10:53:04 [INFO] [EVAL] Class Recall:
[0.9703 0.9507 0.5839 0.7619 0.1137 0.5687 0.7499 0.9811 0.9473 0.9283
0.9949 0.7848 0.6628]
6 模型预测与可视化
除了分析模型的IOU、ACC和Kappa指标之外,我们还可以查阅一些具体样本的切割样本效果,从Bad Case启发进一步优化的思路。
predict.py脚本是专门用来可视化预测案例的,命令格式如下所示
!python predict.py \
--config configs/pp_liteseg/pp_liteseg_stdc1_camvid_960x720_10k.yml \
--model_path output/best_model/model.pdparams \
--image_path dataset/dataA_B/images/02_00_063.png\
--save_dir output/result
可视化:
7 个人介绍
CSDN地址:https://blog.csdn.net/weixin_43267897?spm=1001.2101.3001.5343
Github地址:https://github.com/KHB1698
AI Studio地址:https://aistudio.baidu.com/aistudio/personalcenter/thirdview/791590
此文仅为搬运,原作链接:https://aistudio.baidu.com/aistudio/projectdetail/4203976
更多推荐
所有评论(0)