一、第十七届全国大学生智能汽车竞赛:完全模型组线上资格赛
比赛地址:https://aistudio.baidu.com/aistudio/competition/detail/131/0/task-definition
1.比赛简介
车辆的普及和人们对出行体验的重视,对地图导航提出了更高的要求。基于车载影像的AR导航系统能够精准快速的识别车道线、行驶区域,不仅能够辅助驾驶系统进行高效的决策,同时结合终端渲染与语音技术,也能够为用户带来更为智能精准的导航体验。
作为『新一代人工智能地图』的百度地图,秉承着『用科技让出行更简单』的使命,借助于图像识别、语音识别、大数据处理等人工智能技术,大幅提升地图数据采集和处理的自动化程度,实现道路覆盖超过1000万公里,已成为业内AI化水平最高、搭载的AI技术最强最丰富的地图数据厂商。本次比赛数据由百度地图提供,要求在统一的计算资源下,能够对车载影像中实车道线、虚车道线和斑马线等区域进行快速精准的识别。
本次竞赛的题目和数据由百度地图数据引擎部提供,模型和基线相关技术支持由深度学习技术平台部提供,一站式AI开发平台AI Studio由百度AI技术生态部提供。期待参赛者们能够以此为契机,共同推进智能交通领域的发展。
2.比赛任务
要求参赛者利用提供的训练数据,在统一的计算资源下,实现一个能够识别虚车道线、实车道线和斑马线具体位置和类别的深度学习模型,不限制深度学习任务。 样例示范:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LiuLLf53-1642855745311)(http://bj.bcebos.com/v1/ai-studio-match/file/21b27164efa64b3bb2f5efed6d956730fc61e11be86849f1ae35ab44c4ba580d?authorization=bce-auth-v1%2F0ef6765c1e494918bc0d4c3ca3e5c6d1%2F2022-01-14T08%3A09%3A49Z%2F-1%2F%2F8b281f827158c1dcf0873706ca47286209ceee2e9c3935906876a9a226c9d68c)]
3.比赛数据
数据集描述
本届赛题数据集包括16000张可以直接用于训练的车载影像数据,官方采用分割连通域标注方法,对这些图片数据标注了虚车道线、实车道线和斑马线的区域和类别,其中标注数据以灰度图的方式存储。 标注数据是与原图尺寸相同的单通道灰度图,其中背景像素的灰度值为0,不同类别的目标像素分别为不同的灰度值。实车道线、虚车道线和斑马线类别编号分别为1、2和3。选手报名之后,可在「数据集介绍」tab中下载数据集。
图像与标注数据依文件名编号对应,组织结构如下:
| -- train
| | -- image
| | |-- 00001.jpg
| | |-- …
| | |-- 08000.jpg
| | -- label
| | |-- 00001.png
| | |-- …
| | | -- 08000.png
需注意的是,灰度值较低仅影响肉眼可见性,并不影响深度学习训练。如需要观测标注图像,可以将其拉伸至0~255的RGB图像。
4.提交要求
本次比赛要求选手使用飞桨PaddlePaddle2.1及以上版本生成端到端深度学习模型。
选手需上传训练模型、预测代码及环境库(可选)的zip形式压缩包到AI Studio平台进行自动评测。其中,预测代码需命名为predict.py,model目录不超过200M(不压缩),整体压缩包不超过1G,目录结构约定如下:
| -- model
| | -- xxx.pb
| | …
| -- env
| | -- xxx.lib
| |…
| -- predict.py
| -- …
二、环境准备
此次计划用PaddleSeg动态图API模式,让大家好用看得见。具体文档见https://github.com/PaddlePaddle/PaddleSeg/tree/develop/docs/apis
!pip install -U pip
!pip install -U paddleseg
三、数据准备
1.数据解压缩
!unzip -qoa data/data125511/软件杯_data_2022.zip -d data
2.数据查看
!ls data/软件杯_data_2022/ -l
!head data/软件杯_data_2022/train_list.txt
!head data/软件杯_data_2022/val_list.txt
from PIL import Image
img=Image.open('data/软件杯_data_2022/JPEGImages/07535.jpg')
print(img.size)
img=img.resize((600,400))
img
from PIL import Image
import numpy as np
img=Image.open('data/软件杯_data_2022/Annotations/07535.png')
print(img.size)
img=np.array(img)
img=Image.fromarray(img.astype('uint8'))
img=img.resize((600,400))
img
!wc -l data/软件杯_data_2022/train_list.txt data/软件杯_data_2022/val_list.txt
可见训练集12800,测试集3200,总计16000
import cv2, os
import numpy as np
#amount of classer
CLASSES_NUM = 15
#find imagee in folder dir
def findImages(dir,topdown=True):
im_list = []
if not os.path.exists(dir):
print("Path for {} not exist!".format(dir))
raise
else:
for root, dirs, files in os.walk(dir, topdown):
for fl in files:
im_list.append(fl)
return im_list
# amount of images corresponding to each classes
images_count = [0]*CLASSES_NUM
# amount of pixels corresponding to each class
class_pixels_count = [0]*CLASSES_NUM
# amount of pixels corresponding to the images of each class
image_pixels_count = [0]*CLASSES_NUM
image_folder = './data/软件杯_data_2022/Annotations'
im_list = findImages(image_folder)
for im in im_list:
print(im)
cv_img = cv2.imread(os.path.join(image_folder, im), cv2.IMREAD_UNCHANGED)
size_img = cv_img.shape
colors = set([])
for i in range(size_img[0]):
for j in range(size_img[1]):
p_value = cv_img.item(i,j)
if not p_value < CLASSES_NUM: # check
print(p_value)
else:
class_pixels_count[p_value] = class_pixels_count[p_value] + 1
colors.add(p_value)
im_size = size_img[0]*size_img[1]
for n in range(CLASSES_NUM):
if n in colors:
images_count[n] = images_count[n] + 1
image_pixels_count[n] = image_pixels_count[n] + im_size
print(images_count)
print(class_pixels_count)
print(image_pixels_count)
3.构建训练集
import paddleseg.transforms as T
from paddleseg.datasets import Dataset
dir(T)
['Compose',
'Image',
'LimitLong',
'Normalize',
'Padding',
'PaddingByAspectRatio',
'RandomAffine',
'RandomBlur',
'RandomDistort',
'RandomHorizontalFlip',
'RandomNoise',
'RandomPaddingCrop',
'RandomRotation',
'RandomScaleAspect',
'RandomVerticalFlip',
'Resize',
'ResizeByLong',
'ResizeByShort',
'ResizeRangeScaling',
'ResizeStepScaling',
'ScalePadding',
'__builtins__',
'__cached__',
'__doc__',
'__file__',
'__loader__',
'__name__',
'__package__',
'__path__',
'__spec__',
'cv2',
'functional',
'manager',
'math',
'np',
'random',
'transforms']
help(Dataset)
# 构建训练用的transforms
transforms = [
T.Resize(target_size=(512, 512)),
T.RandomHorizontalFlip(),
T.RandomNoise(),
T.RandomBlur(),
T.Normalize()
]
# 构建训练集
train_dataset = Dataset(
dataset_root='data/软件杯_data_2022/',
train_path='data/软件杯_data_2022/train_list.txt',
transforms=transforms,
num_classes=4,
mode='train'
)
4.构建验证集
# 构建训练用的transforms
transforms = [
T.Resize(target_size=(512, 512)),
T.Normalize()
]
# 构建训练集
val_dataset = Dataset(
dataset_root='data/软件杯_data_2022/',
val_path='data/软件杯_data_2022/val_list.txt',
transforms=transforms,
num_classes=4,
mode='val'
)
四、模型训练
import paddleseg.models as M
dir(M)
1.模型配置
基于 PaddlePaddle 实现的 BiSeNet V2。 BiSeNetV2
原文请参考:
Yu, Changqian, et al. “BiSeNet V2: Bilateral Network with Guided Aggregation for Real-time Semantic Segmentation”
参数
- num_classes (int): 相互独立的目标类别的数量。
- lambd (float, optional): 控制语义分支通道大小的因素。默认:
0.25
- pretrained (str, optional): 预训练模型的url或path。 默认:
None
help(M.BiSeNetV2)
model = M.BiSeNetV2(num_classes=4,
lambd=0.25,
align_corners=False,
pretrained=None)
2.构建优化器
import paddle
# 设置学习率
base_lr = 0.01
lr = paddle.optimizer.lr.PolynomialDecay(base_lr, power=0.9, decay_steps=1000, end_lr=0)
optimizer = paddle.optimizer.Momentum(lr, parameters=model.parameters(), momentum=0.9, weight_decay=4.0e-5)
3. 构建损失函数
为了适应多路损失,损失函数应构建成包含’types’和’coef’的dict,如下所示。 其中losses[‘type’]表示损失函数类型, losses[‘coef’]为对应的系数。需注意len(losses[‘types’])应等于len(losses[‘coef’])。
from paddleseg.models.losses import CrossEntropyLoss
losses = {}
losses['types'] = [CrossEntropyLoss()] * 5
losses['coef'] = [1]* 5
4…训练
from paddleseg.core import train
help(train)
train(
model=model,
train_dataset=train_dataset,
val_dataset=val_dataset,
optimizer=optimizer,
save_dir='output',
iters=2000,
batch_size=86,
save_interval=200,
log_iters=10,
num_workers=0,
losses=losses,
use_vdl=True)
五、模型评估
# 加载模型
model_path = 'output/best_model/model.pdparams'
if model_path:
para_state_dict = paddle.load(model_path)
model.set_dict(para_state_dict)
print('Loaded trained params of model successfully')
else:
raise ValueError('The model_path is wrong: {}'.format(model_path))
from paddleseg.core import evaluate
help(evaluate)
evaluate(
model,
eg.core import evaluate
help(evaluate)
evaluate(
model,
val_dataset)