一、第十七届全国大学生智能汽车竞赛:完全模型组线上资格赛
比赛地址:aistudio.baidu.com/aistudio/co…
1.比赛简介
车辆的普及和人们对出行体验的重视,对地图导航提出了更高的要求。基于车载影像的AR导航系统能够精准快速的识别车道线、行驶区域,不仅能够辅助驾驶系统进行高效的决策,同时结合终端渲染与语音技术,也能够为用户带来更为智能精准的导航体验。
作为『新一代人工智能地图』的百度地图,秉承着『用科技让出行更简单』的使命,借助于图像识别、语音识别、大数据处理等人工智能技术,大幅提升地图数据采集和处理的自动化程度,实现道路覆盖超过1000万公里,已成为业内AI化水平最高、搭载的AI技术最强最丰富的地图数据厂商。本次比赛数据由百度地图提供,要求在统一的计算资源下,能够对车载影像中实车道线、虚车道线和斑马线等区域进行快速精准的识别。
本次竞赛的题目和数据由百度地图数据引擎部提供,模型和基线相关技术支持由深度学习技术平台部提供,一站式AI开发平台AI Studio由百度AI技术生态部提供。期待参赛者们能够以此为契机,共同推进智能交通领域的发展。
2.比赛任务
要求参赛者利用提供的训练数据,在统一的计算资源下,实现一个能够识别虚车道线、实车道线和斑马线具体位置和类别的深度学习模型,不限制深度学习任务。 样例示范:
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模式,让大家好用看得见。具体文档见github.com/PaddlePaddl…
!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, val_dataset)