1024,带你搭建第一个车道线检测网络LaneNet

喜欢而已 提交于 2020-10-26 11:01:17


在这里插入图片描述


资源汇总:

论文下载地址:https://arxiv.org/abs/1802.05591
github项目地址:https://github.com/MaybeShewill-CV/lanenet-lane-detection
LanNet资料合集:https://pan.baidu.com/s/17dy1oaYKj5XruxAL38ggRw 提取码:1024
LanNet论文翻译:车道线检测网络之LaneNet



一、LaneNet 算法详解

1.1 LaneNet 简介

传统的车道线检测方法依赖于手工提取的特征来识别,如颜色的特征、结构张量、轮廓等,这些特征还可能与霍夫变换、各种算子或卡尔曼滤波器相结合。在识别车道线之后,采用后处理技术来过滤错误检测并将其分组在一起以形成最终车道。然而,由于道路场景的变化,这些传统的方法容易出现鲁棒性问题!

更新的方法利用深度学习模型,这些模型被训练用于像素级车道分割。但这些方法仅限于检测预定义的固定数量的车道,例如当前车道,并且不能应对车道改变。

基于此,2018年Davy Neven等人提出一种新的车道线检测网络LaneNet,LaneNet主要做出了如下两个贡献

  • 将车道检测问题归结为一个实例分割问题,其中每条车道都形成了自己的实例,可以端到端地进行训练。
  • 构建了一个新的网络H-Net,用于学习给定输入图像的透视变换参数,该透视变换能够对坡度道路上的车道线进行良好地拟合,克服了鲁棒性不好的问题。

1.2 整体结构分析

作者提出了一个多分支的网络结构,包含一个二值化分割网络(lane segmentation)和一个实例分割网络(lane embedding),从而实现端到端、任意数量的车道线检测。具体来说,二值分割网络输出所有的车道线像素,而实例分割网络将输出的车道线像素分配到不同的车道线实例中。整体的网络结构图如下:
在这里插入图片描述
另一方面,数据集输入到H-Net网络中,学习到透视变换参数H矩阵。用于不同车道线实例的像素,进行车道线拟合,从而得到上图所示连续点状的车道线。

1.3 LaneNet 网络结构

LaneNet的整体网络结构如下:
在这里插入图片描述
二值化分割网络

Lanenet的一个分支为二值化分割网络,该网络将车道线像素与背景区分开。由于目标类别是2类(车道/背景),并且高度不平衡,因此参考了ENet,损失函数使用的是标准的交叉熵损失函数

实例分割网络

该分支网络参考了《Semantic Instance Segmentation with a Discriminative Loss Function》,使用基于one-shot的方法做距离度量学习,将该方法集成在标准的前馈神经网络中,可用于实时处理。该分支网络训练后输出一个车道线像素点距离,基于归属同一车道的像素点距离近,不同车道线像素点距离远的基本思想,利用聚类损失函数聚类得到各条车道线。

聚类损失函数

损失函数如下:
在这里插入图片描述
     [ x ] + = m a x ( 0 , x ) [x]_+=max(0, x) [x]+=max(0,x)

     L t o t a l = L v a r + L d i s t L_{total}=L_{var}+L_{dist} Ltotal=Lvar+Ldist

其中,各个参数表示如下:

  • C——表示车道线实例个数;
  • N c N_c Nc——每个车道线实例中像素的个数;
  • u c u_c uc——每个车道线实例的像素中心;
  • L v a r L_{var} Lvar是方差损失,他的目的是为了降低类内距离
  • L d i s t L_{dist} Ldist是距离损失,它的目的是增大类间距离 (不同车道线之间的距离);

网络结构图

LaneNet的架构基于编码器-解码器网络ENet,该网络是由5个阶段组成。前3个阶段是编码器网络,进行了两次下采样;后两个阶段是解码器网络,进行了两次上采样。
在这里插入图片描述
LaneNet在该网络的基础上修改成了双分支网络。由于ENet的编码器比解码器包含更多的参数,完全在两个任务之间共享完整的编码器将导致不令人满意的结果。因此,LaneNet只在两个分支之间共享前两个阶段(1和2),留下ENet编码器的阶段3和完整的ENet解码器作为每个单独分支的主干。分割分支的最后一层输出单通道图像,用于二值化分割;而实例分割分支的最后一层输出N通道图像,其中N是实例维度。每个分支的损失项都是相等加权的,并通过网络反向传播。

1.4 H-Net 网络结构

LaneNet网络输出的是每条车道线的像素集合,常规的处理是将图像转为鸟瞰图,然后用二次或三次多项式拟合出弯曲的车道线。然而,目前所使用的透视变换矩阵的参数通常是预先设定、不会改变的,在面对水平线波动的影响(如上下坡)等情况下的车道线拟合并不准确,鲁棒性不强。因此,作者提出了H-net模型,用来学习透视变换矩阵的参数H。

在这里插入图片描述
H有6个自由度,放置零是为了强制约束,即在变换下水平线保持水平。

H-NET的网络体系结构较小,由3x3卷积、BN层 和 Relu 的连续块构成。使用最大池化层来降低维度,并在最后添加2个全连接层。完整的网络结构如下图所示:
在这里插入图片描述
最后一个全连接层的结点数是6,对应的就是H矩阵中的6个参数。

1.5 LaneNet 性能优点

检测速度。在英伟达1080Ti显卡上进行测试,检测一帧大小为512x512的彩色图片,耗时19ms,因此每秒可处理50帧左右。
在这里插入图片描述
检测精度。 通过使用LaneNet结合三阶多项式拟合和H-Net的变换矩阵,在tuSimple挑战中检测精度达到96.4%,获得了第四名,与第一名相比只有0.5%的差异。结果可以在下表中看到。
在这里插入图片描述


二、手把手带你实现 LaneNet

2.1 项目介绍

该项目在github上已经开源,获得了1.3k的星标,想试试的同学可克隆下来:https://github.com/MaybeShewill-CV/lanenet-lane-detection,如果打不开,也可以从我的百度云网盘下载:LaneNet资料合集 ,提取码:1024

代码结构和各部分功能如下:

lanenet-lane-detection
├── config //配置文件
├── data //一些样例图片和曲线拟合参数文件
├── data_provider // 用于加载数据以及制作 tfrecords
├── lanenet_model 
│   ├── lanenet.py //网络布局 inference/compute_loss/compute_acc
│   ├── lanenet_front_end.py // backbone 布局
│   ├── lanenet_back_end.py // 网络任务和Loss计算 inference/compute_loss
│   ├── lanenet_discriminative_loss.py //discriminative_loss实现
│   ├── lanenet_postprocess.py // 后处理操作,包括聚类和曲线拟合
├── model //保存模型的目录semantic_segmentation_zoo
├── semantic_segmentation_zoo // backbone 网络定义
│   ├── __init__.py
│   ├── vgg16_based_fcn.py //VGG backbone
│   └─+ mobilenet_v2_based_fcn.py //mobilenet_v2 backbone
│   └── cnn_basenet.py // 基础 block
├── tools //训练、测试主函数
│   ├── train_lanenet.py //训练
│   ├── test_lanenet.py //测试
│   └──+ evaluate_dataset.py // 数据集评测 accuracy
│   └── evaluate_lanenet_on_tusimple.py // 数据集检测结果保存
│   └── evaluate_model_utils.py // 评测相关函数 calculate_model_precision/calculate_model_fp/calculate_model_fn
│   └── generate_tusimple_dataset.py // 原始数据转换格式
├─+ showname.py //模型变量名查看
├─+ change_name.py //模型变量名修改
├─+ freeze_graph.py//生成pb文件
├─+ convert_weights.py//对权重进行转换,为了模型的预训练
└─+ convert_pb.py //生成pb文

2.2 环境搭建

根据开源作者描述,其测试的环境为:

  • ubuntu 16.04
  • python3.5
  • cuda-9.0
  • cudnn-7.0
  • GTX-1070 GPU
  • tensorflow 1.12.0

我使用的环境与配置为:

  • ubuntu16.04系统
  • PyCharm 2020
  • python3.6
  • tensorflow1.13.1-gpu
  • cuda-10.0
  • cudnn7.6.4
  • opencv4.0.0
  • RTX 2070 GPU

想尝试的朋友,可以参考上面两种配置,也可以自行尝试其他的版本。

2.3 准备工作

如果想要自行训练的同学,可以下载TuSimple数据集,进行训练。同样,我们也可以直接使用官方训练好的模型,来输入图片,看看测试效果。为了方便,下面我们直接加载已经训练好的模型,进行本地测试。

(1) 下载TuSimple数据集,如果不训练可以跳过这一步。

(2) 下载训练好的模型,下载链接:LaneNet资料合集 ,提取码:1024

下载完后,我们将模型文件tusimple_lanenet放在工程目录下的model文件中,如下图所示:

在这里插入图片描述

2.4 模型测试

完成环境配置和模型部署后,我们就可以进行测试了!

(1) 先对TusSample数据集中的图片进行测试

  • 第一步,在原工程目录下的data文件中新建一个Mytest文件夹,然后任意选取TusSample数据集中的一张图片放入其中,例如1.jpg,如下图所示:

在这里插入图片描述

  • 第二步,使用PyCharm打开下载好的项目工程,配置好环境后,打开终端,如下图所示:

在这里插入图片描述

  • 第三步,在终端输入以下命令,执行程序:
python tools/test_lanenet.py --weights_path model/tusimple_lanenet/tusimple_lanenet.ckpt --image_path data/Mytest/1.jpg

最后车道线检测效果如下:
在这里插入图片描述

(2)对自己的图片进行测试

  • 第一步,选择自己拍摄的一张车道线图片2.jpg,放入刚才新建好的Mytest文件夹下,如下图所示:

在这里插入图片描述
第二步,打开终端,输入命令,执行程序:

python tools/test_lanenet.py --weights_path model/tusimple_lanenet/tusimple_lanenet.ckpt --image_path data/Mytest/2.jpg

对自己的拍摄的图片检测效果如下:

在这里插入图片描述
测试分析:

从图中可以看出,对自己的图片进行检测时,最终的检测结果虽然能够完美地与实际车道线重合,但是延伸至了空中。

产生这种情况最主要的原因是:没有自己制作数据集进行训练,从而得到更有针对性的模型造成的。由于这里我使用的测试模型是在TuSimple数据集下训练得到的,所以我们对TuSimple中的图片测试效果会很好,比如前面的1.jpg。

如果我们想要对自己的图片进行测试,得到更好的效果,那么就需要自己的数据集。比较好的办法是:

  • 首先在TuSimple数据集下进行训练,得到的训练模型作为预训练模型,这一部分工作其实已经做好了,大家直接下载预训练模型即可
  • 然后,在预训练模型的基础上,加载自己制作的数据集,再进行训练,直到达到预期的效果。

采用这种迁移学习的思想,往往能够事半功倍!

1024,祝大家节日快乐!喜欢就给我点个赞吧,您的支持是我创作的最大动力!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!