opencv|python+opencv车道线,实线虚线的检测

最近在做一个基于opencv的无人小车,行车过程中遇到障碍时需要变道,由于实线不能变道,所以要判断车道线。但是找了很多地方却找不到关于车道线的实线虚线检测,于是通过自己的奇思妙想,想到了解决的办法,于是写下此博客,希望能帮到更多的人。
入门版的车道线检测 参考的资料
在此参考代码基础上完成的实线,虚线检测
代码

import cv2 as cv import numpy as np import utils#读取图片 src = https://www.it610.com/article/cv.imread('test_images/test3.jpg') #高斯降噪 src1 = cv.GaussianBlur(src,(5,5),0,0) # cv.imshow('gaosi',src1) #灰度处理 src2 = cv.cvtColor(src1,cv.COLOR_BGR2GRAY) # cv.imshow('huidu',src2) #边缘检测 lthrehlod = 50 hthrehlod =150 src3 = cv.Canny(src2,lthrehlod,hthrehlod) # cv.imshow('bianyuan',src3) #ROI划定区间,并将非此区间变成黑色 regin = np.array([[(0,660),(690,440), (1200,700),(src.shape[1],660)]]) #为啥要两中括号? mask = np.zeros_like(src3) mask_color = 255#src3图像的通道数是1,且是灰度图像,所以颜色值在0-255 cv.fillPoly(mask,regin,mask_color) src4 = cv.bitwise_and(src3,mask) # cv.imshow('bianyuan2',src4)#利用霍夫变换原理找出上图中的像素点组成的直线,然后画出来 rho = 1 theta = np.pi/180 threhold =15 minlength = 40 maxlengthgap = 20 lines = cv.HoughLinesP(src4,rho,theta,threhold,np.array([]),minlength,maxlengthgap) #画线 linecolor =[0,255,255] linewidth = 4 src5 = cv.cvtColor(src4,cv.COLOR_GRAY2BGR) #转化为三通道的图像# 优化处理 def choose_lines(lines, threhold):# 过滤斜率差别较大的点 slope = [(y2 - y1) / (x2 - x1) for line in lines for x1, x2, y1, y2 in line] while len(lines) > 0: mean = np.mean(slope)# 平均斜率 diff = [abs(s - mean) for s in slope] idx = np.argmax(diff) if diff[idx] > threhold: slope.pop(idx) lines.pop(idx) else: break return lineslefts =[] rights =[] leftlength=[] rightlength=[] for linein lines: for x1,y1,x2,y2 in line: #cv.line(src5,(x1,y1),(x2,y2),linecolor,linewidth) #分左右车道 k = (y2-y1)/(x2-x1) length= ((y2-y1)**2+(x2-x1)**2)**0.5#计算线段长度 if k<0: lefts.append(line) leftlength.append(length) else: rights.append(line) rightlength.append(length)# print(max(leftlength)) # print(max(rightlength))if max(leftlength)>max(rightlength): text="The left-hand side is the solid line" else: text="The right-hand side is the solid line"def clac_edgepoints(points, ymin, ymax):# 可以理解成找一条线的端点 x = [p[0] for p in points] y = [p[1] for p in points]k = np.polyfit(y, x, 1) func = np.poly1d(k)# 方程是y关于x的函数,因为输入的ymin ymax。要求xmin,xmaxxmin = int(func(ymin)) xmax = int(func(ymax))return [(xmin, ymin), (xmax, ymax)]good_leftlines = choose_lines(lefts, 0.1)# 处理后的点 good_rightlines = choose_lines(rights, 0.1)leftpoints = [(x1, y1) for left in good_leftlines for x1, y1, x2, y2 in left] leftpoints = leftpoints + [(x2, y2) for left in good_leftlines for x1, y1, x2, y2 in left] rightpoints = [(x1, y1) for right in good_rightlines for x1, y1, x2, y2 in right] rightpoints = rightpoints + [(x2, y2) for right in good_rightlines for x1, y1, x2, y2 in right]lefttop = clac_edgepoints(leftpoints, 500, src.shape[0])# 要画左右车道线的端点 righttop = clac_edgepoints(rightpoints, 500, src.shape[0])src6 = np.zeros_like(src5)cv.line(src6, lefttop[0], lefttop[1], linecolor, linewidth) cv.line(src6, righttop[0], righttop[1], linecolor, linewidth)# cv.imshow('onlylane',src6)#图像叠加 src7 = cv.addWeighted(src1,0.8,src6,1,0) font = cv.FONT_HERSHEY_SIMPLEX cv.putText(src7,text,(100,100), font, 1,(255,255,255),2) cv.imshow('Finally Image',src7)cv.waitKey(0) cv.destroyAllWindows() ~


代码中有几个需要注意到的地方,是车道线检测关键的所在
1、感兴趣区域的划定,会直接影响车道线检测的结果
#ROI划定区间,并将非此区间变成黑色 regin = np.array([[(0,660),(690,440), (1200,700),(src.shape[1],660)]]) ~

大概意思就是取到的四个点形成的矩形区域,矩形区域需要框定图中的车道线,我所用到的图片大小是1280x720的,如果使用其他大小的图片可能会报错,以及车道线检测结果出现错误。需要根据自己用的实际图片更改自己的区域。
2、实线,虚线检测部分
#利用霍夫变换原理找出上图中的像素点组成的直线,然后画出来 rho = 1 theta = np.pi/180 threhold =15 minlength = 40 maxlengthgap = 20 lines = cv.HoughLinesP(src4,rho,theta,threhold,np.array([]),minlength,maxlengthgap)~lefts =[] rights =[] leftlength=[] rightlength=[] for linein lines: for x1,y1,x2,y2 in line: #cv.line(src5,(x1,y1),(x2,y2),linecolor,linewidth) #分左右车道 k = (y2-y1)/(x2-x1) length= ((y2-y1)**2+(x2-x1)**2)**0.5#计算线段长度 if k<0: lefts.append(line) leftlength.append(length) else: rights.append(line) rightlength.append(length)if max(leftlength)>max(rightlength): text="The left-hand side is the solid line" else: text="The right-hand side is the solid line"~

这里就是实线,虚线检测关键所在,本人自己想到的一个解决办法,思路就是根据直线的长度,长的为实线,短的为虚线。首先通过霍夫变换找到所有的直线,再根据找到的直线算出每个直线的长度,取出左右两边最长的直线进行比较,更长的一边就是实线了。代码实现起来非常简单。
【opencv|python+opencv车道线,实线虚线的检测】附上我使用的图片
opencv|python+opencv车道线,实线虚线的检测
文章图片
opencv|python+opencv车道线,实线虚线的检测
文章图片

    推荐阅读