无人驾驶 OpenCV (F) 识别车道线

接下来进入代码环节,这里详细给大家解释一下 HoughLinesP 参数的含义以及如何使用。

lines = cv2.HoughLinesP(cropped_image,2,np.pi/180,100,np.array([]),minLineLength=40,maxLineGap=5)

第一参数是我们要检查的图片
Hough accumulator 数组
第二个和第三个参数用于定义我们 Hough 坐标如何划分 bin,也就是小格的精度。我们通过曲线穿过 bin 格子来进行投票,我们根据投票数量来决定 p 和 theta 的值。2 表示我们小格宽度以像素为单位 。


我们可以通过下图划分小格,只要曲线穿过就会对小格进行投票,我们记录投票数量,记录最多的作为参数

如果定义尺寸过大也就失去精度,如果定义格子尺寸过小虽然精度上来了,这样也会打来增长计算时间。

接下来参数 100 表示我们投票为 100 以上的线才是符合要求是我们要找的线。也就是在 bin 小格子需要有 100 以上线相交于此才是我们要找的参数。

minLineLength 给 40 表示我们检查线长度不能小于 40 pixel
maxLineGap=5 作为线间断不能大于 5 pixel

定义显示车道线方法

def disply_lines(image,lines):
    pass

通过定义函数将找到的车道线显示出来。

line_image = disply_lines(lane_image,lines)

查看探测车道线数据结构

def disply_lines(image,lines):
    line_image = np.zeros_like(image)
    if lines is not None:
        for line in lines:
            print(line)

先定义一个尺寸大小和原图一样的矩阵用于绘制查找到车道线,我们先判断一下是否已经找到车道线,lines 返回值应该不为 None 是一个矩阵,我们可以简单地打印一下看一下效果

[[704 418 927 641]]
[[704 426 791 516]]
[[320 703 445 494]]
[[585 301 663 381]]
[[630 341 670 383]]

探测车道线

看数据结构[[x1,y1,x2,y2]] 的二维数组,这就需要我们转换一下为一维数据[x1,y1,x2,y2]

def disply_lines(image,lines):
    line_image = np.zeros_like(image)
    if lines is not None:
        for line in lines:
            x1,y1,x2,y2 = line.reshape(4)
            cv2.line(line_image,(x1,y1),(x2,y2),(255,0,0),10)
    return line_image
line_image = disply_lines(lane_image,lines)
cv2.imshow('result',line_image)
探测线

合成影响

combo_image = cv2.addWeighted(lane_image,0.8, line_image, 1, 1,1)

有关合成图片我们是将两张图片通过给一定权重进行叠加合成。


优化

我们通过学习霍夫变换探测到的车道线还是不够平滑,我们需要优化,基本思路就是对这些直线的斜率和截距取平均值然后将所有探测出点绘制到一条直线上。

averaged_lines = average_slope_intercept(lane_image,lines);

首先定义我们的函数,接收道路图片和探测点做为参数。

def average_slope_intercept(image,lines):
    left_fit = []
    right_fit = []
    for line in lines:
        x1, y1, x2, y2 = line.reshape(4)
        parameters = np.polyfit((x1,x2),(y1,y2),1)
        print(parameters)

这里定义两个数组 left_fit 和 right_fit 分别用于存放左右两侧车道线的点,我们打印一下 lines 的斜率和截距,通过 numpy 提供 polyfit 方法输入两个点我们就可以得到通过这些点的直线的斜率和截距。

[   1. -286.]
[   1.03448276 -302.27586207]
[  -1.672 1238.04 ]
[   1.02564103 -299.
def average_slope_intercept(image,lines):
    left_fit = []
    right_fit = []
    for line in lines:
        x1, y1, x2, y2 = line.reshape(4)
        parameters = np.polyfit((x1,x2),(y1,y2),1)
        # print(parameters)
        slope = parameters[0]
        intercept = parameters[1]
        if slope < 0:
            left_fit.append((slope,intercept))
        else:
            right_fit.append((slope,intercept))
        print(left_fit)
        print(right_fit)

由于左侧和右侧线的斜率不同,我们根据斜率可以划分点到左右两侧的直线矩阵上。

    left_fit_average = np.average(left_fit,axis=0)
    right_fit_average = np.average(right_fit,axis=0)

然后通过取平局值来得到他们平均斜率和截距。

[  -1.61019355 1201.00387097]
[   1.0243751  -298.80648538]
def make_coordinates(image, line_parameters):
    slope, intercept = line_parameters
    print(image.shape)
    return 

我们输出一下图片大小,我们图片是以其左上角作为原点 0 ,0 来开始计算的,所以我们直线从图片底部 700 多向上绘制我们无需绘制全部可以截距一部分即可。
![图(https://upload-images.jianshu.io/upload_images/8207483-367e149bfb5a5165.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

(704, 1279, 3)
(704, 1279, 3)
    left_line = make_coordinates(image, left_fit_average)
    right_line = make_coordinates(image, right_fit_average)
def make_coordinates(image, line_parameters):
    slope, intercept = line_parameters
    y1 = image.shape[0]
    y2 = int(y1*(3/5)) 
    x1 = int((y1 - intercept)/slope)
    x2 = int((y2 - intercept)/slope)
    # print(image.shape)
    return np.array([x1,y1,x2,y2])

所以直线开始和终止我们给定 y1,y2 然后通过方程的斜率和截距根据y 算出 x。

averaged_lines = average_slope_intercept(lane_image,lines);
line_image = disply_lines(lane_image,averaged_lines)
combo_image = cv2.addWeighted(lane_image,0.8, line_image, 1, 1,1)

cv2.imshow('result',combo_image)
result_optimize.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,711评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,079评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,194评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,089评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,197评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,306评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,338评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,119评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,541评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,846评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,014评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,694评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,322评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,026评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,257评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,863评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,895评论 2 351

推荐阅读更多精彩内容