matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第1张图片

写在前面:

前几天写的第一篇文章收获了35个赞(目前)确实给了我挺大的鼓舞的哈哈哈,感觉写文章也挺锻炼自己能力的,也算是把它当笔记写吧

最近笔者开始着手开发一个新的项目,其中第一步就用了很多数字图像的知识,包括灰度图变换、canny边缘检测、霍夫变换等,想起来前几天的数字图像处理文章,索性在写一篇关于霍夫变换的吧,也好借这个机会用代码和效果图来帮大家感受霍夫变换算法的强大

关于环境:

笔者所使用的开发环境是Ubuntu16.04 + Pycharm + opencv4,前面两个应该大家都知道是什么吧,Ubuntu为一款较为流行的linux操作系统,Pycharm则是一款较为先进的python开发编译器,其中opencv是计算机视觉领域必备的一个计算机视觉库,全程为Open Source Computer Vision Library,强烈推荐对于计算机视觉感兴趣的同学可以开始了解一下 (ps:今天发现了一个pycharm暗黑系主题插件:Material Theme UI,简直好看哭了,这里安利一波,贴一下效果图)

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第2张图片

一.前言

在我们开始深入学习霍夫变换算法之前,我们先简单了解一下什么是霍夫变换以及霍夫变换的应用举例

1.霍夫变换到底是个什么啥呀

霍夫变换是一种特征检测(feature),被广泛应用在图像分析(image analysis)计算机视觉(computer vision)以及数位影像处理 (digital image processing)。 经典的霍夫变换是侦测图片中的直线,之后,霍夫变换不仅能识别直线,也能够识别任何形状,常见的有圆形椭圆形

让我们想象一下,现在叫大家在一副图片中找出一条直线或者圆,相信对于大家应该都是一件相当容易的事,但是对于计算机来说,一副图像所呈现的只是灰度值从0-255的庞大矩阵而已,它可不容易知道复制的矩阵中哪些是直线哪些不是,霍夫变换便是帮助计算机'看到'图像中的直线或圆的一种算法

其基本思想为:

将传统的图像从x y轴坐标体系变换到参数空间(m, b)或者霍夫空间(Hough space)中,通过在参数空间(parameter space)或可称为累加空间(accumulator space)中计算局部最大值从而确定原始图像直线或圆所在位置

(下面用一个具体应用来让大家有个直观的理解)

2.霍夫变换的具体应用实例

霍夫变换最初较为成功的应用体现在机场跑道检测,如图 1-1 、图 1-2所示,图中为基于霍夫变换的对机场的机场跑到检测

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第3张图片
图 1-1 潮汕机场跑道线检测图

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第4张图片
图 2-2 英国紐瓦克机场跑道线检测图

二.霍夫变换

常见的霍夫变换可归为以下两种:

1).基于笛卡尔坐标空间的霍夫变换

2).基于极坐标空间(二维直线霍夫空间)的霍夫变换

下面让我们来一一介绍这两种霍夫变换算法,以下文章仅包括霍夫变换中直线检测部分,如对圆检测或椭圆检测有兴趣的同学可自行去查阅资料哈

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第5张图片

(贴张很酷炫的霍夫变换可视图)

1.基于笛卡尔坐标空间的霍夫变换

在我们从初中就开始使用的平面直角坐标中,一条直线的表示通常用

表示,其中
表示的是直线的
斜率
表示的是直线的
截距,一条直线上的点所使用的是同一个
,因此我们可以设想一下,如果有一个坐标轴体系是以
为横轴,
为竖轴,形成以
为参数的
参数空间,是不是在平面坐标中同一条直线上的点在参数空间表示为一个点呢, 霍夫变换即是基于这种思想而诞生的,如图 2-1所示

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第6张图片
图 2-1

让我们换一种思维来更深层次理解一下霍夫变换,在xy笛卡尔坐标轴上的任意一点(x,y)随着x斜率

和截距
的改变,在参数空间各种
的组合将会呈现为一条
直线,如图 2-2所示,为点A(2, 12)在 参数空间的投影

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第7张图片
图 2-2

现在我们在xy笛卡尔坐标轴做另一点B(1, 8)的参数空间投影,如图 2-3所示

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第8张图片
图 2-3

可以发现,在参数空间中两直线交于紫色点位(4, 4),这里所体现的信息为:点A、B两点连接的直线斜率为

,截距为
,因此,现在我们可以理解霍夫变换其实就是
计算参数空间累加点的值大小,值越大越说明这个点的参数
所代表的直线
置信度越高,可是我们还要讨论一个问题,当直线为垂直x轴时,斜率
将会变为
无穷大,在计算机数值运算时会造成无法进行,如图 2-4所示

因此DudaHart提出使用极坐标空间进行霍夫变换,以此来解决这一问题,即我们接下来要介绍的真正意义上的基于极坐标空间(二维直线霍夫空间)的霍夫变换

2.基于极坐标空间(二维直线霍夫空间)的霍夫变换

首先我们先回顾一下什么是极坐标,极坐标是指在平面内由极点极轴极径组成的坐标系,其中假设有一点

,其中参数
表示极径,即极点O到P点的距离,参数
表示极角,即OX到OP的角度,极坐标方程举个例子,如图 2-4所示,假设有一极坐标方程:
,当
时,
计算得4.9

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第9张图片
图 2-4

相信到现在大家对极坐标有个大致的了解,我们回过头看霍夫变换,以直线检测为例,假设有一条直线,原点到该直线的垂直距离为

,垂线与x轴的夹角为
,那么这条直线是
唯一的,且直线方程为:

如图 2-5绿线所示,其中直线上的每个点,在参数空间都可表示为一条正弦曲线(sinusoidal curve),如图右三条蓝线所对应的便是xy坐标系中直线上三点p1p2p3,在参数空间中这三条正弦曲线会交于一点,即图中点(0.92, 9.66),其反映的信息为三点所在直线与原点距离

为9.66,垂线与x轴夹角
为0.92

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第10张图片

至此,我们可以发现其实极坐标参数空间与笛卡尔坐标参数空间类似,都可看成在累加空间(accumulator space)计算局部最大值,进行直线的预测,可是大家忽略了一个问题,在现实的应用场景中,许多直线并不是非常精细,或多或少存在偏差,导致参数空间各曲线不能交于精确的一点,因此我们需要将参数空间分块,分块的步长则为单位长度的

,如图 2-6所示,其次计算单位区域内
累加的交点数量,将大于 阈值(threshold)的区域值认定为直线存在, 存储其参数

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第11张图片

但是还存在一个问题,分块的步长对检测的精准度也有影响,分的太细,计算代价就会上升,分的太大,计算的准确率就会下降,因此现在通用的常用做法是:

步长设为单像素单位,
步长设为
,并且现实场景中的应用也会使用一种
Mask掩模的做法,提取我们感兴趣的图像区域,以此来大大减少计算量

好了,笔者对于霍夫变换的介绍大致就到这里(在细讲怕又写的太长了哈哈哈),接下来我们要讲的是基于霍夫变换实现的无人驾驶中的车道线检测

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第12张图片

(贴个gif帮助大家直观理解霍夫变换,其中右侧即参数空间,方块颜色越亮则说明该点所携带参数更有可能为一条直线)

三.车道线检测

最近笔者在学习辅助自动驾驶这一块的知识,对这方面多少有点了解,算是给大家科普一下吧,自动驾驶系统主要由三部分组成:算法端Client端云端,其中算法端包括面向传感感知决策等关键部分的算法,传感可以理解为使用各种设备如摄像头、传感器、雷达等进行外界信息的传入,而感知即将这些信息处理为让机器可以理解的信息,如我们接下来要实现的车道线检测,利用霍夫变换来使汽车知道车道线的具体位置,为后续决策等操作提供支持,好了科普就大概讲这么多,接下来讲一下车道线检测大致的流程吧

  1. 彩色图像(Color Image)转换为灰度图(Gray Scale Image)
  2. 高斯(Gaussian)滤波
  3. Canny边缘检测
  4. 生成Mask掩模
  5. 基于霍夫变换的直线检测
  6. 绘制车道线
  7. 图像融合

1.灰度图转换

第一步我们需要将彩色图像(Color Image)转换为灰度图(Gray Scale Image),即从三通道图像RGB转为单通道图像,可以将这一步视为一个信息提取操作或简化操作,我们在这一步需要用到Opencv库cv.cvtColor函数,这一函数作用为颜色空间转换,这里我们只需要用到两个参数:src输入图像,code颜色转换代码,其中RGB图像转灰度图的转换代码为cv.COLOR_RGB2GRAY,效果如图 3-1所示,具体代码如下:

# 灰度图转换

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第13张图片
图 3-1 灰度图

2.高斯滤波

高斯滤波算法是一种去除高频噪声的常用方式,其在Opencv中的函数为cv.GaussianBlur,其参数大致有src输入图像,Size为高斯核大小,即高斯滤波器的尺寸,第三个参数即高斯标准差

,一般默认为0即可,具体代码如下:
# 高斯滤波

3.Canny边缘检测

Canny边缘检测算法具体来说是一种信息提取算法,将原本复制的灰度图最大限度保留信息的情况下转换为二值图像,进而进行其它的操作,这里不再多说,如有兴趣了解边缘检测算法的可以参考笔者的上一篇文章数字图像图像处理:边缘检测(Edge detection),效果如图 3-2所示,具体的实现代码如下:

# Canny边缘检测

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第14张图片
图 3-2 边缘图像

4.生成Mask掩模

Mask掩模的作用为降低计算代价,即只在我们感兴趣部分进行算法的计算,如霍夫变换检测车道线,这里笔者设计的Mask区域如图 3-3所示,其中height与width为图片的高与宽,具体实现代码如下:

# 生成感兴趣区域即Mask掩模

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第15张图片
图 3-3 Mask区域可视化

5.基于霍夫变换的直线检测

霍夫变换这里也不在多讲了,前面讨论的已经足够详细,如还不明白的同学可以往前翻翻看哈,这里我们用到的是Opencv封装好的函数cv.HoughLinesP函数,其参数有点多,我们一个一个来介绍

  • image:输入图像,通常为canny边缘检测处理后的图像
  • rho:线段以像素为单位的距离精度
  • theta:像素以弧度为单位的角度精度(np.pi/180较为合适)
  • threshold:霍夫平面累加的阈值
  • minLineLength:线段最小长度(像素级)
  • maxLineGap:最大允许断裂长度

具体代码如下:

def hough_lines(img, rho, theta, threshold, min_line_len, max_line_gap):

    # rho:线段以像素为单位的距离精度
    # theta : 像素以弧度为单位的角度精度(np.pi/180较为合适)
    # threshold : 霍夫平面累加的阈值
    # minLineLength : 线段最小长度(像素级)
    # maxLineGap : 最大允许断裂长度
    lines = cv.HoughLinesP(img, rho, theta, threshold, np.array([]), minLineLength=min_line_len, maxLineGap=max_line_gap)
    return lines

6.绘制车道线

这一步是将上一步检测到的直线绘制出来,但是远远没有听起来那么简单,为什么呢?首先我们来看一张图,这是上一步霍夫变换后直接绘制的直线,如图 3-4所示

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第16张图片
图 3-4 霍夫变换检测直线

我们可以看到,出现了多条线段相互相邻这一情况,而我们所期望的是单车道线检测,便于直观体验与后续处理,因此我们在这一步还需对上一步检测到的直线进行进一步的预处理,处理的方法具体为:

  1. 对每条直线求取斜率,分别归为左右列表中
  2. 对得到的列表进行斜率平均值
    的计算和最高点A的计算
  3. 根据平均斜率m_{0}与最高点计算线段与图像下方的交点B坐标
  4. 连接最高点A与交点B

以上为大致流程,更为深层的理解需要大家看一下代码才会懂哈,图 3-5是处理完的车道线效果图,具体代码如下:

line_image 

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第17张图片
图 3-5 车道线绘制

7.图像融合

这一步是将原始彩色图像与我们刚绘制的车道线图像进行比例的融合,这里需要介绍一个函数cv.addWeighted,参数src1和alpha表示图像或矩阵和它对应的权重(Weight),src2和beta表示的则是第二副图像或矩阵和它对应的权重,第五个参数gamma表示整体添加到数值,默认为0即可

这里我们将原图权重设为0.8,车道线图像设为1,则最后呈现的效果为车道线较为明显,可视化程度提高,效果如图 3-6 图3-7所示,具体代码如下:

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第18张图片
图 3-6 车道检测效果图1

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第19张图片
图 3-7 车道检测效果图2
# 原图像与车道线图像按照a:b比例融合
def weighted_img(img, initial_img, a=0.8, b=1., c=0.):
    return cv.addWeighted(initial_img, a, img, b, c)

看了上面的图有没有觉得很炫酷呢,笔者教大家一个更炫酷的,就是在视频流中检测车道线,即使用cv.VideoCapture,就可以实现车道的实时检测,具体代码如下:

cap = cv.VideoCapture("./test_videos/solidYellowLeft.mp4")
while(cap.isOpened()):
    _, frame = cap.read()
    processed = process_image(frame)
    cv.imshow("image", processed)
    cv.waitKey(1)

视频如下:

matlab车道线检测_数字图像处理:基于霍夫变换的车道线检测_第20张图片
实时车道线检测https://www.zhihu.com/video/1093202755635785728

四.总结

写着写着回头发现好像又写的有点长,各位看官请见谅哈

霍夫变换是一个数字图像处理经常使用的算法,其算法思想笔者一直认为很值得我们学习,即转换思想,将问题转换为另一个维度空间上,可能实现起来并没有那么难(刚学霍夫变换的时候真的惊叹人好聪明啊)

接下来笔者可能会开始写机器学习比较经典的一些算法或者深度学习中的卷积神经网络(CNN),喜欢的同学帮忙点个赞加个关注哦,最后贴一下完整的代码:

import 

你可能感兴趣的:(matlab车道线检测)