基于opencv的车道检测(附源码&注释)

代码

import cv2 as cv
import numpy as np
def calulate_slope(line):
    x_1, y_1, x_2, y_2 = line[0]
    return(y_2-y_1)/(x_2-x_1)

road = cv2.imread('road_lr.jpg',cv.IMREAD_GRAYSCALE)  #霍夫变化只能读灰度图,'road2.jfif'是filename
color_road = cv2.imread('road_lr.jpg')
# mask = np.zeros_like(color_road)   #获取一个与图像相同大小的数组
mask = np.zeros_like(road)   #获取一个与图像相同大小的数组
# mask = cv2.fillPoly(mask,
#                     np.array([[[2,134],[1,116],[197,44],[368,112],[371,134]]]),
#                     (0,255,255))  # 写上掩码区域,彩色图
mask = cv2.fillPoly(mask,
                    np.array([[[2,134],[1,116],[197,44],[368,112],[371,134]]]),
                    255)  # 写上掩码,灰度图,我就写255白色
#masked = cv2.bitwise_and(color_road, mask)  #布尔运算,第一个是原图,第二个是掩码(彩色图)
masked = cv2.bitwise_and(road, mask)  #布尔运算,第一个是原图,第二个是掩码(灰度图)
cv2.imshow('masked',mask) # 展示掩码
cv2.imshow('masked',masked) # 展示布尔运算后的图
edge_img = cv2.Canny(masked,752,318)   #canny边沿化  cv2.Canny(road,151,756)
cv2.imshow('cannyed',edge_img)
lines = cv2.HoughLinesP(edge_img,5,np.pi/180,15,minLineLength=20,maxLineGap=10)  #霍夫变化参数意义自行查阅
print(lines)    #lines的值,长度
length = len(lines)
print(length)   #所以一共有407个直线
# cv2.imshow('huofued',lines)
cv2.imshow('name',edge_img)
left_lines = [line for line in lines if calulate_slope(line)  > 0]
right_lines = [line for line in lines if calulate_slope(line) < 0]  # [line for line in file (file name)]的格式是列表推导式,这个等式是将for循环的结果存储到列表lines中。
def reject_abnormal_lines(lines, thershold):
    slopes = [calulate_slope(line) for line in lines]
    while len(lines) >0:
        mean = np.mean(slopes)  #平均值
        diff = [abs(s-mean) for s in slopes]
        idx = np.argmax(diff)
        if diff[idx] > thershold :   # 如果我们现有的差值
            slopes.pop(idx)
            lines.pop(idx)
        else:
            break
    return lines
print( 'before filter')
print(len(left_lines))
print(len(right_lines))

reject_abnormal_lines(left_lines, thershold=0.3)  #去除哪些不正常的线段
reject_abnormal_lines(right_lines, thershold=0.3)

print( 'after filter')
print(len(left_lines))
print(len(right_lines))
def least_fit(lines):
  x_coords = np.ravel([[line[0][0], line[0][2]] for line in lines])
  y_coords = np.ravel([[line[0][1], line[0][3]] for line in lines])
  poly = np.polyfit(x_coords, y_coords,deg = 1)

  point_min = (np.min(x_coords), np.polyval(poly,np.min(x_coords)))
  point_max = (np.max(x_coords), np.polyval(poly,np.max(x_coords)))
  return   np.array([point_min,point_max], dtype = np.int_ )

print("left_lane")
left_lane = least_fit(left_lines)
print(least_fit(left_lines))
print("right_lane")
right_lane = least_fit(right_lines)
print(least_fit(right_lines))

cv.line(color_road,tuple(left_lane[0]),tuple(left_lane[1]),(0,255,255),9)
cv.line(color_road,tuple(right_lane[0]),tuple(right_lane[1]),(0,255,255),5)
cv.imshow('road_line',color_road)
cv.waitKey(0)

基于opencv的车道检测(附源码&注释)_第1张图片
配套图片

效果图

基于opencv的车道检测(附源码&注释)_第2张图片

有关车道检测一些函数的使用方法

二值化函数cv2.threshold()将灰度图二值化:

基于opencv的车道检测(附源码&注释)_第3张图片

ret,mask = cv2.threshold(img,175,255,cv2.THRESH_BINARY)
plt.imshow(mask,cmap='gray')

这个函数就是将上图,灰度值大于175的转化为255(白色),小于175的转化为0(黑色)

基于opencv的车道检测(附源码&注释)_第4张图片
基于opencv的车道检测(附源码&注释)_第5张图片
基于opencv的车道检测(附源码&注释)_第6张图片
或者

ret,mask1 = cv2.threshold(masked,175,255,cv2.THRESH_BINARY_INV)
cv2.imshow('thershold',mask1)

参数ret 为True 或者False,代表有没有读取到图片

基于opencv的车道检测(附源码&注释)_第7张图片
了解更多请点击:opencv位运算

canny边缘检测

cv2.Canny(image, threshold1, threshold2)
image:源图像
threshold1:阈值1
threshold2:阈值2

其中,较大的阈值2用于检测图像中明显的边缘,但一般情况下检测的效果不会那么完美,边缘检测出来是断断续续的。所以这时候用较小的第一个阈值用于将这些间断的边缘连接起来

Canny边缘检测分四个阶段:
1.去噪。通过一个5*5的高斯滤波器完成;

2.找图像的密度梯度。听起来有点难懂,实际上就是找“边缘”,边缘两侧图像的亮度一般会相差比较大。通过分别在图像的水平和垂直方向利用Sobel kernel得到两个方向的梯度。

3.过滤非最大值。在高斯滤波中,边缘很有可能被放大了。这个步骤使用一个规则来过滤不是边缘的点,使边缘宽度尽可能是一个像素点。

4.使用两个值域来检测边缘。
基于opencv的车道检测(附源码&注释)_第8张图片
我的办法是先建立一个滑动栏,来调试出较好的阈值,再写上去
基于opencv的车道检测(附源码&注释)_第9张图片

import cv2 as cv
import numpy as np
def calulate_slope(line):
    x_1, y_1, x_2, y_2 = line[0]
    return(y_2-y_1)/(x_2-x_1)
def nothing(x):
    pass#在我们的例子中,函数什么都不做,所以我们简单地通过。
road = cv2.imread('road_lr.jpg',cv.IMREAD_GRAYSCALE)  #霍夫变化只能读灰度图,'road2.jfif'是filename
cv.imshow('road',road)
edge = np.zeros((300,512,3), np.uint8)
cv2.namedWindow('edge')
# cv2.createTrackbar('max','edge',50,1000,lambda x:x)
# cv2.createTrackbar('min','edge',50,1080,lambda x:x)
cv2.createTrackbar('max','edge',50,1000,nothing)
cv2.createTrackbar('min','edge',50,1080,nothing)
# print(edge_dis.shape)
while True:
    cv2.imshow('roadname', road)
    Min = cv2.getTrackbarPos('min','edge')
    Max = cv2.getTrackbarPos('max', 'edge')
    edge1 = cv2.Canny(road, Min, Max)  # 经验
    cv2.imshow('edge', edge1)
    cv.waitKey(60)  #一定要加!!
cv.waitKey(0)

基于opencv的车道检测(附源码&注释)_第10张图片

roi_mask

霍夫变化

离群值过滤

最小二乘拟合

你可能感兴趣的:(opencv,opencv,边缘检测,python,计算机视觉)