数字图像处理课综合实验
实验题目 跑道识别
1.实验目标
1.1要求:识别出跑道线并绘制在原图上
1.2提示:
①全局或局部二值化处理
②识别直线
③进行直线过滤,并绘制跑道线
2.实验环境
VS2013+OpenCV3.0
3.实验原理
Hough检测原理:
霍夫变换(Hough)是1972年提出来的,最开始就是用来在图像中过检测直线,后来扩展能检测圆、曲线等
霍夫变换就是通过图形的一种表示模式,加上一种转换方法,把图形的点集投射到一个点上以便检测。
标准直线Hough变换采用如下参数化直线方程:
式中,θ表示直线的法线方向,0≤θ<180,ρ表示原点至直线的距离(本实验中θ的单位均为“度”,ρ的单位均为“像素”)。通常在图像直线检测中不直接使用图像坐标系,而是使用原点在图像中心处、y轴方向与图像的y方向相反的正交坐标系,如图1所示的Oxy坐标系。
图1直线Hough变换的坐标系与参数定义
为了进行直线检测,首先需要按一定的量化间隔将可能的θ与ρ取值范围离散化为若干区间,其中θ的取值范围规定在[0,180)的区间内,而ρ的取值范围则由图像矩形的顶点至原点即图像中心的距离确定;整个可能的θ-ρ 参数空间被离散化为一个二维的网格,对每一个可能的离散化参数对(θi,ρj)即每个网格单元设置一个计数器。然后对图像中的每个特征点(x0,y0),遍历所有的离散θ值,根据式(1)计算出每个θi值下对应的ρ 值及相应的离散区间ρi,并对计数器(θi,ρi)的值加1,这一过程称为特征点对参数空间投票。当所有的特征点均完成了投票后,寻找出参数空间中计数器值大于某一给定阈值T 的局部极大点,这些局部极大点对应的直线参数对(θ,ρ)即代表了检测得到的图像中的直线。
以图1为例,对于每一个在直线l0上的均有点。
所以对于计数器(θ0,ρ0) 而言它极有可能为最大值。得到和后直线也就检测出来了。
其核心思想是把图像中属于某种图形的点集(二维)映射到一个点(可以是高维)上,这个点记录了点集中点的数目,使得程序通过搜索峰值找到该点,这个点就是后面要说到的图形的参数,而该参数的范围就叫做参数空间。霍夫变换不仅能够识别出图像中有无需要检测的图形,而且能够定位到该图像的位置、角度等。
4.实验步骤
4.1简要步骤如下:
①.将输入图像滤波
②.将滤波后的图像灰度化
③.采用边缘检测算子转换成二值化边缘图像
④.对二值化图像进行霍夫变换
⑤.将检测出的直线进行过滤
⑥.绘制跑道线
4.2流程图如图2所示:
图2流程图
5.算法实现
5.1 canny和中值滤波的参数确定:
中值滤波的最佳ksize为3,canny算子的最佳参数(threshold1,threshold12,aperture_size)为( 20, 30, 3),这样检测出来的直线更加贴合跑道。
5.2 直线斜率的检测实现:
k = (double)(lines[i][3] - lines[i][1]) / (double)(lines[i][2] - lines[i][0]);
取出直线的起始点,计算直线的斜率,通过直线斜率初步筛选直线,实验得跑道线的斜率在(-1.8,-0.3)∪(0.25,3)这个区间内,通过这个斜率的筛选能达到初步的好效果。
5.3 通过直线端点筛选,调整:
输出直线的起始点及斜率,大概可以确定跑道线在图片中的区域。原图片的大小为1080*1604.
若直线斜率为正:只留下直线长度大于150的,若该直线起点横坐标小于500,则根据直线的斜率沿着直线方向调整起点的横坐标变为500;若该直线起点纵坐标小于500,则更具直线的斜率沿着直线方向调整起点的纵坐标到500;
若直线斜率为负:只留下直线长度大于220的,若该直线终点横坐标大于600,则根据直线的斜率沿着直线方向调整终点的横坐标变为600;若该直线终点纵坐标小于500,则根据直线的斜率沿着直线方向调整终点的纵坐标到500;
因为有些直线它既是跑道线的一部分,有包含了其他的线段(不属于跑道线),所以通过这个操作可以避免这个问题。
部分调整代码:
double p = (500 - point1[0]) *x1;
point1[0] = 500;
point1[1] += p;
所以计算差值,根据差值和斜率就可以调整点的位置同时使的直线不会偏移。
6.实验效果图
效果图如图3所示,可以看出,跑道线都已经检测出来,还有部分比较杂乱的短线,弯道部分暂无法检测。
图3跑道检测效果图
7.遇到的问题及解决过程
1.hough检测直线代码其实是很简单的,但如果就单纯只检测直线,就会得到图4
图4 hough检测效果图
只是霍夫检测的话会存在很多杂线,因为图片中要素过多。
观察图4,发现有很多水平线,都是不需要的,还有一些垂直线也不需要。
初步想法是滤去水平直线,但是图片中还存在树之类的干扰,所以尽管滤去了水平直线,还是有很多多余的直线,比如说树枝,草,山,很影响检测效果。
再观察一下跑道,其实跑道线不多,斜率也相近,比较好过滤其他杂线,所以我想到了计算出直线的斜率,根据斜率在过滤一部分直线。
2.所以我定义了一个函数求直线的斜率,又针对了直线的斜率进行了过滤,可以得到图。可以看出, 基础霍夫变换只是寻找图像中边缘像素的对齐区域。因为有些像素只是碰巧拍成了直线,这种方式可能产生错误的检测结果,也可能因为多条直线穿过了同一个像素对齐区域,而检测出重复的结果。又因为斜率和跑道线相近,所以检测的效果已经接近,但还是不理想。
图5 斜率过滤效果图
3.在前面的基础上再对直线的长度进行过滤,就会得到这图6,多余的线是减少了,但是根本问题还未解决。
图6 长度过滤效果图
所以我又想到了可能还根据截距也能过滤一部分直线,测试很多不同的参数,发现不行。
4.于是我对直线检测规定了区域:
Mat imageROI = dst(Range(0, 800), Range(0, 1000));效果图如图7:
图7 规定区域效果图
5.最后因为实在没有办法处理那些过长的跑道线,于是打印出了绘制的直线的起点和终点。再来看一下原图(图8),跑道这张图片还是很端正的,也不太需要矫正,跑道线基本都在同一水平位置结束,所以我们可以调整直线的起始点和终点的位置使直线只绘制在红色区域,通过不断地调参和调试,确定最佳的调整位置,就可以绘制出拟合较好的直线了。
图8 跑道原图
结果图(图9)如下,还有一些短线,应该是根据斜率该端点时引起的,问题不大,跑道识别基本完成。:
图9 最终识别图
8.实验体会
尝试了很多方法过滤直线,都效果很差,这个综合实验的关键点就在于过滤其他直线留下跑道线,刚开始觉得反正图片中直线数量少,至少能得到完整的跑道线,于是我直接用hough检测未做任何处理,检测的直线非常的乱,因为图片中存在建筑物和风景,建筑物上的直线是最密集的,很影响跑道识别。最开始我的想法是截掉图片上半部分,只在下半部分做直线检测,然后过滤水平线,也可以得到比较好的效果,但是这样实现还是不太好。我觉得还可以通过截取跑道部分检测直线,然后通过偏移量在原图上绘制图像,这样效果也是不错的。其实一旦弄清这个道理,代码还是不难的,主要是要看可不可以想到方法去解决存在的问题。每一步下来都会有问题,我们需要思考怎么利用已学得知识去优化。
这次实验让我充分了解了opencv中中值滤波,canny算子边缘检测,hough变换检测直线的原理,是很宝贵的实践财富,半个学期的教学时间中,上机的机会也很少,如果上课只是听老师简单讲一下理论知识是很难应用起来的。因为很少接触到图像处理的知识,吸收起来也非常困难,这次的综合实验让我收获很多,很有意义。
这次实验只接触到了hough变换的直线检测,希望以后可以有机会做曲线检测的实验,能更加完整的识别整个操场的跑道线。