最近在做一个基于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车道线,实线虚线的检测】附上我使用的图片
文章图片
文章图片
推荐阅读
- 人脸识别|【人脸识别系列】| 实现自动化妆
- 推荐系统论文进阶|CTR预估 论文精读(十一)--Deep Interest Evolution Network(DIEN)
- Python专栏|数据分析的常规流程
- Python|Win10下 Python开发环境搭建(PyCharm + Anaconda) && 环境变量配置 && 常用工具安装配置
- Python绘制小红花
- Pytorch学习|sklearn-SVM 模型保存、交叉验证与网格搜索
- OpenCV|OpenCV-Python实战(18)——深度学习简介与入门示例
- python|8. 文件系统——文件的删除、移动、复制过程以及链接文件
- 爬虫|若想拿下爬虫大单,怎能不会逆向爬虫,价值过万的逆向爬虫教程限时分享
- 分布式|《Python3网络爬虫开发实战(第二版)》内容介绍