点击上方“小白学视觉”,选择加"星标"或“置顶”
重磅干货,第一时间送达
主要介绍基于Hough变换与深度学习的直线检测。其中介绍并使用了各种算子(尤其Canny)进行图像的边缘检测,并在Hough变换后使用几何特征与空间特征等筛选与确定目标直线。(内附数据与python代码)
0.尝试
最初本人使用实验一中提到的均值滤波(3x3为例)与中值滤波(卷积核为5为例)对实验图像进行处理,样例如图2所示:
图2 图像进行均值、中值滤波前后(上为均值滤波)
分析:由图2可见,使用均值及中值滤波降噪效果均较差,且滤波后图像模糊,丢失较多信息,不能为后续的边缘检测与路沿识别提供优化,故在本实验中使用其他方法。
1.图像处理->边缘检测(原理)
在图像中边缘即为亮度变化明显的点,边缘检测本质上就是检测并绘制出边缘点的集合,实现了简化图像信息,使用边缘线代表图像所携带信息。
经典边缘检测方法在使用中或多或少存在一定问题,求得的边缘图存在很多问题,如噪声污染没有被排除、边缘线太过粗宽等,对于本任务均不是最优选择。故在本实验中选择Canny算子进行边缘检测。不同算子进行边缘检测效果对比样如图7所示:
2.Canny算子边缘检测(原理)
经过对比,较适合本实验的边缘检测方法为Canny算子。Canny算子是一种非微分边缘检测算子,目标是找到一个最优的边缘检测解或找寻一幅图像中灰度强度变化最强的位置。最优边缘检测主要通过低错误率、高定位性和最小响应三个标准进行评价。相关标准定义如表4,使用Canny算子进行边缘检测流程及相关原理如表5所示:
3.Canny算子边缘检测(实现)
在正式开始边缘检测前,有以下四个重要特征需要了解,后续设计中帮助提高识别率:
Ⅰ、颜色:车道线(路沿)通常为浅色(白色/黄色),而道路则为深色(深灰色)。因此,黑白图像效果更好,因为车道可以很容易地从背景中分离出来。
Ⅱ、形状:车道线(路沿)通常是实线或虚线,所以可以将它们与图像中的其他对象分开。可以用Canny等边缘检测算法找到图像中的所有边缘/线条。然后我们可以使用进一步的信息来决定哪些边可以被限定为车道线。
Ⅲ、方向:公路车道线(路沿)更接近于垂直方向,而不是水平方向。因此,在图像中检测到的直线的斜率可以用来检查它是否可能是车道。
Ⅳ、在图像中的位置:在一个由行车记录仪拍摄的常规公路图像中,车道线(路沿)通常出现在图像的下半部分。因此,可以将搜索区域缩小到感兴趣的区域,以减少噪声。
根据(2)中的原理与流程设计代码,核心实现的设计与解析如下:
3.1 图像转化(彩->灰)
图像转化原因:边缘检测最关键的部分是计算梯度,颜色难以提供关键信息,并且颜色本身非常容易受到光照等因素的影响,所以只需要灰度图像中的信息就足够了。并且灰度化后,简化了矩阵,提高了运算速度。
原理:将彩色图像(Color Image)转换为灰度图(Gray Scale Image),即从三通道RGB图像转为单通道图像。
实现:我们实现彩图转化为灰度图需要用到opencv库中的cv.cvtColor函数,需要用到两个参数:src——输入图片,code——颜色转换代码,具体代码如下:
3.2 高斯滤波
高斯滤波选择原因:因为现实中的噪声分布多是随机,故在图5(0)中使用均值滤波与中值滤波效果不好,而Canny算子一般搭配高斯滤波。
简介、原理及操作:高斯滤波是一种线性平滑滤波,适用于消除高斯噪声。高斯滤波每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值,其中卷积操作原理样例如图9所示:
Ⅱ、库函数(本实验方法)
Opencv库中内置高斯滤波函数,用法为cv2.GaussianBlur(src, ksize, sigmaX, sigmaY, borderType)-> dst。经对比后,发现库函数实现与使用较方便,且效果较好,故本实验选择库函数实现高斯滤波,前后对比样例(以高斯矩阵的长与宽为5,标准差取0为例)如图11所示:
3.3 Canny边缘检测
在进行完图像转化与高斯滤波等图像处理后,正式进入Canny边缘检测,按表4中步骤设计边缘检测代码,如高斯滤波实现,可自定义函数实现,也可直接使用库函数实现。
手写实现可见:Python实现Canny算子边缘检测
https://yueyue200830.github.io/2020/04/04/Python%E5%AE%9E%E7%8E%B0Canny%E7%AE%97%E5%AD%90%E8%BE%B9%E7%BC%98%E6%A3%80%E6%B5%8B/
本实验使用库函数进行Canny边缘检测。其中每一步生成图像样例及结果对比如图12所示:
图12 Canny边缘检测每一步生成的图像及不同实现方法效果对比
本实验直接使用opencv库中的cv.Canny函数,其中使用到的参数为:src——输入图像,low_threshold ——低阈值,high_threshold——高阈值,边缘检测样例(低阈值=75,高阈值=225为例)如图13所示:
3.4 生成Mask掩膜,提取 ROI
通过观察我们不难发现,本实验中路沿在图像中的位置基本处于中间偏右,这意味着我们可以对图像进行区域选取,排除其他边缘与线的影响,使识别效果更好,详解如下:
简介:Mask掩模的作用为降低计算代价,核心为遮挡非感兴趣区,只在我们感兴趣部分(ROI)进行算法的计算(mask最终需要与要作用到的输入图像的尺寸与类型保持一致)。本实验中我们感兴趣的部分为路沿,故可设计Mask掩模如图14所示:
1.传统图像方法综述
如前文所述,传统图像方法通过边缘检测滤波等方式分割出车道线区域,然后结合Hough变换、RANSAC等算法进行车道线检测。这类算法需要人工手动去调滤波算子,根据算法所针对的街道场景特点手动调节参数曲线,工作量大且鲁棒性较差,当行车环境出现明显变化时,车道线的检测效果不佳。主流方式如表13:
缺点:应用场景受限;Hough变换检测方法准确但很难做弯道检测,拟合方法可以检测弯道但不稳定,仿射变换可以做多车道检测但在遮挡等情况下干扰严重。透视变换操作会对相机有一些具体的要求,在变换前需要调正图像,而且摄像机的安装和道路本身的倾斜都会影响变换效果。其次,这些方法都无法满足实时性要求。
2.深度学习方法综述
近年来,随着深度学习在计算机视觉领域的快速发展,对应方法由于其鲁棒性和实时性迅速获得了关注,大致分为四类:基于分割的方法、基于检测的方法、基于参数曲线的方法、基于关键点的方法。下面对四类方法进行简介:
2.1 基于分割的方法
基于分割的方法将车道线检测建模为逐像素分类问题,每个像素分为车道线区域或背景。这类模型通常是在语义分割模型的基础上,增加一个车道线实例判别头,来对车道线是否存在进行监督学习。经典算法有:SCNN、RESA、LaneNet等。
其中以SCNN为例,为了区分不同的车道线,SCNN将不同的车道线作为不同的类别,从而将车道检测转化为多类分割任务。提出一个切片CNN结构(RESA对结构进行改进,加入切片间的不同步幅大小的信息传递,同时解耦相邻层之间的时序上的依赖,增加并行处理能力),以使消息跨行和列传递,原理如图30所示:
总结:分割模型大,处理速度慢。在严重遮挡情况下表现差,未充分利用车道先验知识。
2.2 基于检测的方法
基于检测的方法通常采用自顶向下的方法来预测车道线,这类方法利用车道线在驾驶视角自近处向远处延伸的先验知识,构建车道线实例。基于Anchor的方法设计线型Anchor,并对采样点与预定义Anchor的偏移量进行回归。应用非极大值抑制(NMS)选择置信度最高的车道线。经典算法有:LineCNN、LaneATT等。
其中以lineCNN为例,其使用从图像边界以特定方向发出的直线射线作为一组Anchor,原理如图31所示:
总结:自顶向下的设计能够更好的利用车道线的先验知识,提高检测实时性,同时在处理严重遮挡等情况下能够获得连续的车道线检测实例。但预设Anchor形状会影响检测的灵活性。
2.3 基于参数曲线的方法
基于参数曲线的方法使用预先设定的参数曲线,对车道线形状进行检测,经典算法有:PolyLaneNet、B´ezierLaneNet等。
以PolyLaneNet为例,其通过多项式曲线回归,输出表示图像中每个车道线的多项式。并维持高效性(115FPS),原理如图32所示:
总结:基于曲线的方法可以自然地学习整体车道表示,具有较高的推理速度,但在准确度上不高。
2.4 基于关键点的方法
基于关键点的方法直接对车道线的实例进行检测,使用后处理对实例进行划分。经典算法有:FOLOLane、GANet等。
以FOLOLane为例,其对局部模式进行建模,并以自下而上的方式实现对全局结构的预测,原理如图33所示:
总结:此类方法兼具灵活性和实时性,在处理遮挡问题时如何构建全局信息是需要考虑的问题。
六、深度学习方法实践
本部分以LaneNet为例,对深度学习方法在车道线检测方面进行简单实践,具体如下:
Towards End-to-End Lane Detection: an Instance Segmentation Approach论文(2018):Towards End-to-End Lane Detection: an Instance Segmentation Approach
代码(tensorflow):https://github.com/MaybeShewill-CV/lanenet-lane-detection
数据集(tuSimple):https://github.com/TuSimple/tusimple-benchmark/issues/3
1.数据集介绍
LaneNet官方使用数据集为tuSimple数据集,是车道线识别中常用数据集(网络最早公开的数据集),基本为高速公路车道线检测,相关信息如表14:
2.算法介绍
LaneNet是一种端到端(输入原数据,无需特征提取)的车道线检测方法,包含 LanNet + H-Net 两个网络模型。是将语义分割和对像素进行向量表示结合起来的多任务模型,最后利用聚类完成对车道线的实例分割。
H-Net 是个小的网络结构,负责预测变换矩阵 H,使用转换矩阵 H 对同属一条车道线的所有像素点进行重新建模(即:学习给定输入图像的透视变换参数,该透视变换能够对坡度道路上的车道线进行良好地拟合)。
整体网络架构与核心流程如图34所示,LaneNet网络架构与实现如图35所示:
优点:通过embedding vector与cluster配合使用,能检测不限条数的车道线。通过HNet学得的perspective transformation,使得lane fitting能够更鲁棒。
缺陷:cluster很耗时,实际工程应用上很难满足实时性的要求。
总结
1.路沿检测步骤
本次实验的核心任务为路沿检测,对实验步骤进行总结,基于Hough变换的路演检测步骤如图39所示:
图39 基于Hough变换的直线(路沿)检测步骤
2.路沿检测问题与解决
本次实验在实现路沿检测的过程中,在各部分均出现了一定问题,几个典型问题及解决方案总结如下:
2.1 图像处理方式的选择
本实验最初尝试使用实验一的均值与中值滤波对图像进行预处理,效果不佳。在后续选择与Canny算子相适配的高斯滤波,在Hough变换前加入对比度增强,解决了此问题。故在实际问题中应该根据算法与数据选择相应的图像处理方式。
2.2 参数设置问题
无论是Canny算子的高低阈值,还是Hough变换中的七个参数,在本实验中的选择均对结果有较大影响。故在本实验中需人工调参,经过不断迭代与优化参数确定较优参数,同时需兼顾参数的准确性与泛化能力。
2.3 目标直线的筛选与确定
在Hough变换后检测出多条直线,如何筛选与确定目标直线(路沿)也是一个问题。本实验中首先使用直线的几何特征(斜率)与空间的结构特征(mask掩模)判断,再利用直线位置、斜率聚类、x轴差值等特点确定目标直线,并使用上一帧直线+位置修正或卡尔曼滤波修正过度判断的情况。对于本实验中出现的视频模糊与过弯情况,使用上述方法也可以较好解决。
3.基于Hough变换直线检测的分析与补充
在利用Hough变换及相关判断完成本实验路沿识别后,对实验效果进行分析如下:
3.1 优点
基于Hough变换进行直线检测的优点在于实现方便、代码复杂度低(高效),对于简单数据处理情况较好。
3.2 缺陷
基于Hough变换进行直线检测的缺陷在于参数调整过程麻烦,最优参数确定困难,模型对环境因素依赖性过强,在变化过大等情况下表现不佳,且泛化能力较差,代码迁移性低。
3.3 补充
在传统图像方法上,除了基于Hough变换的直线检测,还有基于LSD直线、基于俯视图变换、基于拟合、基于平行透视灭点的车道线检测等。
在深度学习方法上,由于其在直线检测任务上表现出的高实时性与鲁棒性,多数方法涌现。大致分为如下四类:基于分割的方法、基于检测的方法、基于参数曲线的方法、基于关键点的方法。
原文地址
https://blog.csdn.net/weixin_51426083/article/details/127812799
下载1:OpenCV-Contrib扩展模块中文版教程
在「小白学视觉」公众号后台回复:扩展模块中文教程,即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。
下载2:Python视觉实战项目52讲
在「小白学视觉」公众号后台回复:Python视觉实战项目,即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。
下载3:OpenCV实战项目20讲
在「小白学视觉」公众号后台回复:OpenCV实战项目20讲,即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。
交流群
欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~