动手学无人驾驶(7):车道线检测

在这里插入图片描述
最近在研究视觉语义地图,需要进行车道线检测,发现这篇车道线检测论文效果蛮好的 (Ultra Fast Structure-aware Deep Lane Detection)。论文作者在知乎上已经介绍过了:https://zhuanlan.zhihu.com/p/157530787,本文中我简单介绍下论文原理,重点介绍如何使用原作者开源的模型检测自己采集的数据。


1.Method介绍

目前大多数车道线检测算法中都是将车道线检测看作是像素分割问题。但是这会存在两个问题,一是计算速度慢,二是在一些有挑战的场景中(遮挡、夜晚、极端光照条件)由于没有视觉线索很难进行检测。因此在本文中,作者提出了一个按行检测车道线的方法

作者首先将原始图像按照一定像素间隔划分成 hhh 个anchors,同时又将每一个anchor划分为 www 个网格。若图像全局特征用 XXX 表示,车道线数量用 CCC 表示,车道线分类器为 fijf^{ij}fij,则车道线预测概率为:
Pi,j,:=fij(X),s.t. i∈[1,C],j∈[1,h]P_{i, j,:}=f^{i j}(X), \text { s.t. } i \in[1, C], j \in[1, h] Pi,j,:=fij(X), s.t. i[1,C],j[1,h]

概率 Pi,j,:P_{i, j,:}Pi,j,:(w+1)(w+1)(w+1) 维的向量。

为什么本文提出的方法可以快速检测车道线呢?如下图所示,基于像素分割的车道线检测要进行 H×W×(C+1)H \times W \times (C+1)H×W×(C+1) 次分类,而本文提出的方法只需要进行 C×h×(w+1)C \times h \times (w+1)C×h×(w+1) 次分类,由于 h<<H,w<<Wh<<H,w<<Wh<<Hw<<W,因此整体计算量大幅减小。
在这里插入图片描述
同时在本文中作者又提出了两个新的结构损失函数。

  • 由于车道线一般是连续的,所有同一车道线在相邻anchor的预测概率应该是接近的,作者提出了车道线相似损失函数
    Lsim=∑i=1C∑j=1h−1∥Pi,j,:−Pi,j+1,:∥1L_{s i m}=\sum_{i=1}^{C} \sum_{j=1}^{h-1}\left\|P_{i, j,:}-P_{i, j+1,:}\right\|_{1} Lsim=i=1Cj=1h1Pi,j,:Pi,j+1,:1
  • 另一个是车道线形状损失函数,作者使用softmax函数得到车道线的概率:Prob⁡i,j,:=softmax⁡(Pi,j,1:w)\operatorname{Prob}_{i, j,:}=\operatorname{softmax}\left(P_{i, j, 1: w}\right)Probi,j,:=softmax(Pi,j,1:w),同时使用期望来表示车道线所处位置Loci,j=∑k=1wk⋅Prob⁡i,j,kL o c_{i, j}=\sum_{k=1}^{w} k \cdot \operatorname{Prob}_{i, j, k}Loci,j=k=1wkProbi,j,k。最后作者使用二阶微分方程来约束车道线位置:
    Lshp=∑i=1C∑j=1h−2∥(Loci,j−Loci,j+1)−(Loci,j+1−Loci,j+2)∥1\begin{aligned} L_{s h p}=\sum_{i=1}^{C} \sum_{j=1}^{h-2} \| &\left(L o c_{i, j}-L o c_{i, j+1}\right) -\left(L o c_{i, j+1}-L o c_{i, j+2}\right) \|_{1} \end{aligned} Lshp=i=1Cj=1h2(Loci,jLoci,j+1)(Loci,j+1Loci,j+2)1

2.自采数据集车道线检测

下面使用作者训练好的模型来检测车道线,代码链接为:https://github.com/cfzd/Ultra-Fast-Lane-Detection。

下载完源码后,创建一个lane_detection.py,首先导入需要的库:

import torch
import scipy.special
import os, cv2
from PIL import Image
from model.model import parsingNet
import numpy as np
import torchvision.transforms as transforms
from data.constant import tusimple_row_anchor

然后加载预训练模型,作者在两个车道线数据集上进行了训练,我这里选择是的在TuSimple数据集训练的模型,代码如下:

 net = parsingNet(pretrained = False, backbone='18',cls_dim = (101,56,4),use_aux=False) # we dont need auxiliary segmentation in testingtest_model = 'tusimple_18.pth'
state_dict = torch.load(test_model, map_location='cpu')['model']compatible_state_dict = {}
for k, v in state_dict.items():if 'module.' in k:compatible_state_dict[k[7:]] = velse:compatible_state_dict[k] = vnet.load_state_dict(compatible_state_dict, strict=False)
net.eval()

然后是一些参数设置,如图片大小尺寸(我这里图片大小为 1280×5601280\times5601280×560),row anchor 尺寸(这里使用的是作者设置的anchor尺寸),图片预处理等(将图片大小resize为 800×288800\times288800×288):

img_w, img_h = 1280, 560
size = (img_w,img_h)
cls_num_per_lane = 56
row_anchor = tusimple_row_anchorimg_transforms = transforms.Compose([transforms.Resize((288, 800)),transforms.ToTensor(),transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225)),
])

下一步就是车道线检测与可视化:

 with torch.no_grad():out = net(img)col_sample = np.linspace(0, 800-1, 100)
col_sample_w = col_sample[1] - col_sample[0]out_j = out[0].data.cpu().numpy()
out_j = out_j[:, ::-1, :]                               
prob = scipy.special.softmax(out_j[:-1, :, :], axis=0)  
idx = np.arange(100) + 1
idx = idx.reshape(-1, 1, 1)
loc = np.sum(prob * idx, axis=0)
out_j = np.argmax(out_j, axis=0)
loc[out_j == 100] = 0
out_j = loc                                             for i in range(out_j.shape[1]):if np.sum(out_j[:, i] != 0) > 2:for k in range(out_j.shape[0]):if out_j[k, i] > 0:ppp = (int(out_j[k,i] * col_sample_w * img_w / 800) - 1, int(img_h *   (row_anchor[cls_num_per_lane-1-k]/288))-1)cv2.circle(vis,ppp,4,(0,0,255),-1)
Image.fromarray(vis).show()

最后检测结果如下:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/439560.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Coursera自动驾驶课程第16讲:LIDAR Sensing

在第15讲《Coursera自动驾驶课程第15讲&#xff1a;GNSS and INS Sensing for Pose Estimation》 我们学习了自动驾驶定位中常用的两种传感器&#xff1a;IMU&#xff08;惯性测量单元&#xff09; 和GNSS&#xff08;全球导航卫星系统&#xff09;。 本讲我们将学习自动驾驶汽…

DB、ETL、DW、OLAP、DM、BI关系结构图

在此大概用口水话简单叙述一下他们几个概念&#xff1a; &#xff08;1&#xff09;DB/Database/数据库——这里一般指的就是OLTP数据库&#xff0c;在线事物数据库&#xff0c;用来支持生产的&#xff0c;比如超市的买卖系统。DB保留的是数据信息的最新状态&#xff0c;只有一…

Tarjan 算法 常用模板

可以求每个点属于第几个强连通分量&#xff1a;https://blog.csdn.net/dellaserss/article/details/8267192 int Tarjan(int u){int v;dfn[u]low[u]Index;stack[Top]u;Instack[u]1;for(int i0;i<G[u].size();i){vG[u][i];if(!dfn[v]){Tarjan(v);low[u]min(low[u],low[v]);}…

【HDU - 5012】Dice(模拟,bfs)

题干&#xff1a; There are 2 special dices on the table. On each face of the dice, a distinct number was written. Consider a 1.a 2,a 3,a 4,a 5,a 6 to be numbers written on top face, bottom face, left face, right face, front face and back face of dice A. S…

重读经典:《Generative Adversarial Nets》

GAN论文逐段精读【论文精读】这是李沐博士论文精读的第五篇论文&#xff0c;这次精读的论文是 GAN。目前谷歌学术显示其被引用数已经达到了37000。GAN 应该是机器学习过去五年上头条次数最多的工作&#xff0c;例如抖音里面生成人物卡通头像&#xff0c;人脸互换以及自动驾驶中…

一步步编写操作系统 62 函数调用约定

由于我们要将c语言和汇编语言结合编程啦&#xff0c;所以一定会存在汇编代码和c代码相互调用的问题&#xff0c;有些事情还是要提前交待给大家的&#xff0c;本节就是要给大家说下函数调用规约中的那些事儿。 函数调用约定是什么&#xff1f; 调用约定&#xff0c;calling co…

重读经典:《An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale》

ViT论文逐段精读【论文精读】这次李沐博士邀请了亚马逊计算机视觉专家朱毅博士来精读 Vision Transformer&#xff08;ViT&#xff09;&#xff0c;强烈推荐大家去看本次的论文精读视频。朱毅博士讲解的很详细&#xff0c;几乎是逐词逐句地讲解&#xff0c;在讲解时把 ViT 相关…

给不会调用C++STL库中二分函数lower_bound,upper_bound,binary_search同学的一些话!

lower_bound算法返回第一个大于等于给定值所在的位置。设置两个指针start和last&#xff0c;其中start指向数组的起始位置&#xff0c;last指向数组末尾位置之后的位置。当start和last指向相同位置时循环结束。mid指向[start,last)区间的中间位置&#xff0c;当中间位置元素值大…

详解IMU标定经典论文:A Robust and Easy to Implement Method for IMU Calibration without External Equipments

本文介绍一篇 关于IMU 标定的经典论文&#xff0c;论文收录于 ICRA14&#xff0c;在论文中作者介绍了如何不适用外部设备标定 IMU 加速度和角速度偏差、尺度系数、轴偏移参数。 论文链接&#xff1a;https://readpaper.com/paper/2021503353、https://readpaper.com/paper/221…

重读经典:《Momentum Contrast for Unsupervised Visual Representation Learning》

MoCo 论文逐段精读【论文精读】这次论文精读李沐博士继续邀请了亚马逊计算机视觉专家朱毅博士来精读 Momentum Contrast&#xff08;MoCo)&#xff0c;强烈推荐大家去看本次的论文精读视频。朱毅博士和上次一样讲解地非常详细&#xff0c;几乎是逐词逐句地讲解&#xff0c;在讲…

【HRBUST - 1623】Relation(思维模拟,拆解字符串)

题干&#xff1a; 一天&#xff0c;ikki在看书的时候发现书上有个类似于家谱状的插图&#xff0c;突然ikki想到了一个有趣的现象&#xff1a;有时候用某个人一连串 的关系描述另一个人的时候&#xff0c;最后可能还是他本身。例如&#xff1a;小明的爸爸的爸爸和小明的爷爷是同…

一步步编写操作系统 67 系统调用的实现1-2 68

接上文&#xff1a; 系统调用的子功能要用eax寄存器来指定&#xff0c;所以咱们要看看有哪些系统调用啦&#xff0c;在linux系统中&#xff0c;系统调用是定义在/usr/include/asm/unistd.h文件中&#xff0c;该文件只是个统一的入口&#xff0c;指向了32位和64位两种版本。在a…

【HDU - 6662】Acesrc and Travel(树形dp,博弈dp)

题干&#xff1a; Acesrc is a famous tourist at Nanjing University second to none. During this summer holiday, he, along with Zhang and Liu, is going to travel to Hong Kong. There are nnspots in Hong Kong, and n−1n−1 bidirectional sightseeing bus routes …

一步步编写操作系统 69 汇编语言和c语言共同协作 70

由于有了上一节的铺垫&#xff0c;本节的内容相对较少&#xff0c;这里给大家准备了两个小文件来实例演示汇编语言和c语言相互调用。 会两种不同语言的人&#xff0c;只是掌握了同一件事物的两种表达方式。人在学习一种新语言时&#xff0c;潜意识里是建立了语言符号与事物形象…

一步步编写操作系统 71 直接操作显卡,编写自己的打印函数71-74

一直以来&#xff0c;我们在往屏幕上输出文本时&#xff0c;要么利用bios中断&#xff0c;要么利用系统调用&#xff0c;这些都是依赖别人的方法。咱们还用过一个稍微有点独立的方法&#xff0c;就是直接写显存&#xff0c;但这貌似又没什么含量。如今我们要写一个打印函数了&a…

【CodeForces - 208C 】Police Station(单源最短路条数,起点终点建图,枚举顶点)

题干&#xff1a; The Berland road network consists of n cities and of m bidirectional roads. The cities are numbered from 1 to n, where the main capital city has number n, and the culture capital — number 1. The road network is set up so that it is possi…

【Chrome浏览器】常用快捷键整理

标签页和窗口快捷键 1. Ctrl n 打开新窗口 2. Ctrl t 打开新的标签页&#xff0c;并跳转到该标签页 3. Ctrl Shift t 重新打开最后关闭的标签页&#xff0c;并跳转到该标签页 4. Ctrl Tab 跳转到下一个打开的标签页 5. Ctrl Shift Tab 跳转到上一个打开的标签页 6.…

【人工智能课程实验】 - 利用贝叶斯分类器实现手写数字 的识别

读入数据与预处理 因为老师给的文件无法直接读取&#xff0c;故从官网导入数据&#xff1a; 官网链接&#xff1a;http://www.cs.nyu.edu/~roweis/data.html 导入数据之后要对MATLAB文件进行读入&#xff1a; datasio.loadmat(trainfile) 对文件type一下&#xff1a; ty…

一步步编写操作系统 77 内联汇编与ATT语法简介

内联汇编 之前和大家介绍过了一种汇编方法&#xff0c;就是C代码和汇编代码分别编译&#xff0c;最后通过链接的方式结合在一起形成可执行文件。 另一种方式就是在C代码中直接嵌入汇编语言&#xff0c;强大的GCC无所不能&#xff0c;咱们本节要学习的就是这一种&#xff0c;它…