目录

一、首先进行canny边缘检测,为获取车道线边缘做准备

二、进行ROI提取获取确切的车道线边缘(红色线内部)

三、利用概率霍夫变换获取直线,并将斜率正数和复数的线段给分割开来

四、离群值过滤,剔除斜率相差过大的线段

五、最小二乘拟合,实现将左边和右边的线段互相拟合成一条直线,形成车道线

六、绘制线段

全部代码(视频显示)


一、首先进行canny边缘检测,为获取车道线边缘做准备

import cv2gray_img = cv2.imread('img.jpg',cv2.IMREAD_GRAYSCALE)
canny_img = cv2.Canny(gray_img,50,100)
cv2.imwrite('canny_img.jpg',canny_img)
cv2.imshow('canny',canny_img)cv2.waitKey(0)

二、进行ROI提取获取确切的车道线边缘(红色线内部)

方法:在图像中,黑色表示0,白色为1,那么要保留矩形内的白色线,就使用逻辑与,当然前提是图像矩形外也是0,那么就采用创建一个全0图像,然后在矩形内全1,之后与之前的canny图像进行与操作,即可得到需要的车道线边缘。

import cv2
import numpy as npcanny_img = cv2.imread('canny_img.jpg',cv2.IMREAD_GRAYSCALE)
roi = np.zeros_like(canny_img)
roi = cv2.fillPoly(roi,np.array([[[0, 368],[300, 210], [340, 210], [640, 368]]]),color=255)
roi_img = cv2.bitwise_and(canny_img, roi)
cv2.imwrite('roi_img.jpg',roi_img)
cv2.imshow('roi_img',roi_img)
cv2.waitKey(0)

三、利用概率霍夫变换获取直线,并将斜率正数和复数的线段给分割开来

TIPs:使用霍夫变换需要将图像先二值化

概率霍夫变换函数:

  • lines=cv2.HoughLinesP(image, rho,theta,threshold,minLineLength, maxLineGap)
  • image:图像,必须是8位单通道二值图像
  • rho:以像素为单位的距离r的精度,一般情况下是使用1
  • theta:表示搜索可能的角度,使用的精度是np.pi/180
  • threshold:阈值,该值越小,判定的直线越多,相反则直线越少
  • minLineLength:默认为0,控制接受直线的最小长度
  • maxLineGap:控制接受共线线段的最小间隔,如果两点间隔超过了参数,就认为两点不在同一直线上,默认为0
  • lines:返回值由numpy.ndarray构成,每一对都是一对浮点数,表示线段的两个端点
import cv2
import numpy as np#计算斜率
def calculate_slope(line):x_1, y_1, x_2, y_2 = line[0]return (y_2 - y_1) / (x_2 - x_1)edge_img = cv2.imread('masked_edge_img.jpg', cv2.IMREAD_GRAYSCALE)
#霍夫变换获取所有线段
lines = cv2.HoughLinesP(edge_img, 1, np.pi / 180, 15, minLineLength=40,maxLineGap=20)#利用斜率划分线段
left_lines = [line for line in lines if calculate_slope(line) < 0]
right_lines = [line for line in lines if calculate_slope(line) > 0]

四、离群值过滤,剔除斜率相差过大的线段

流程:

  • 获取所有的线段的斜率,然后计算斜率的平均值
  • 遍历所有斜率,计算和平均斜率的差值,寻找最大的那个斜率对应的直线,如果差值大于阈值,那么就从列表中剔除对应的线段和斜率
  • 循环执行操作,直到剩下的全部都是小于阈值的线段
def reject_abnormal_lines(lines, threshold):slopes = [calculate_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] > threshold:slopes.pop(idx)lines.pop(idx)else:breakreturn linesreject_abnormal_lines(left_lines, threshold=0.2)
reject_abnormal_lines(right_lines, threshold=0.2)

五、最小二乘拟合,实现将左边和右边的线段互相拟合成一条直线,形成车道线

流程:

  • 取出所有的直线的x和y坐标,组成列表,利用np.ravel进行将高维转一维数组
  • 利用np.polyfit进行直线的拟合,最终得到拟合后的直线的斜率和截距,类似y=kx+b的(k,b)
  • 最终要返回(x_min,y_min,x_max,y_max)的一个np.array的数据,那么就是用np.polyval求多项式的值,举个example,np.polyval([3,0,1], 5) # 3 * 5**2 + 0 * 5**1 + 1,即可以获得对应x坐标的y坐标。
def least_squares_fit(lines):# 1. 取出所有坐标点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])# 2. 进行直线拟合.得到多项式系数poly = np.polyfit(x_coords, y_coords, deg=1)print(poly)# 3. 根据多项式系数,计算两个直线上的点,用于唯一确定这条直线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")
print(least_squares_fit(left_lines))
print("right lane")
print(least_squares_fit(right_lines))

六、绘制线段

cv2.line(img, tuple(left_line[0]), tuple(left_line[1]), color=(0, 255, 255), thickness=5)
cv2.line(img, tuple(right_line[0]), tuple(right_line[1]), color=(0, 255, 255), thickness=5)

全部代码(视频显示)

import cv2
import numpy as npdef get_edge_img(color_img, gaussian_ksize=5, gaussian_sigmax=1,canny_threshold1=50, canny_threshold2=100):"""灰度化,模糊,canny变换,提取边缘:param color_img: 彩色图,channels=3"""gaussian = cv2.GaussianBlur(color_img, (gaussian_ksize, gaussian_ksize),gaussian_sigmax)gray_img = cv2.cvtColor(gaussian, cv2.COLOR_BGR2GRAY)edges_img = cv2.Canny(gray_img, canny_threshold1, canny_threshold2)return edges_imgdef roi_mask(gray_img):"""对gray_img进行掩膜:param gray_img: 灰度图,channels=1"""poly_pts = np.array([[[0, 368], [300, 210], [340, 210], [640, 368]]])mask = np.zeros_like(gray_img)mask = cv2.fillPoly(mask, pts=poly_pts, color=255)img_mask = cv2.bitwise_and(gray_img, mask)return img_maskdef get_lines(edge_img):"""获取edge_img中的所有线段:param edge_img: 标记边缘的灰度图"""def calculate_slope(line):"""计算线段line的斜率:param line: np.array([[x_1, y_1, x_2, y_2]]):return:"""x_1, y_1, x_2, y_2 = line[0]return (y_2 - y_1) / (x_2 - x_1)def reject_abnormal_lines(lines, threshold=0.2):"""剔除斜率不一致的线段:param lines: 线段集合, [np.array([[x_1, y_1, x_2, y_2]]),np.array([[x_1, y_1, x_2, y_2]]),...,np.array([[x_1, y_1, x_2, y_2]])]"""slopes = [calculate_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] > threshold:slopes.pop(idx)lines.pop(idx)else:breakreturn linesdef least_squares_fit(lines):"""将lines中的线段拟合成一条线段:param lines: 线段集合, [np.array([[x_1, y_1, x_2, y_2]]),np.array([[x_1, y_1, x_2, y_2]]),...,np.array([[x_1, y_1, x_2, y_2]])]:return: 线段上的两点,np.array([[xmin, ymin], [xmax, ymax]])"""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)# 获取所有线段lines = cv2.HoughLinesP(edge_img, 1, np.pi / 180, 15, minLineLength=40,maxLineGap=20)# 按照斜率分成车道线left_lines = [line for line in lines if calculate_slope(line) > 0]right_lines = [line for line in lines if calculate_slope(line) < 0]# 剔除离群线段left_lines = reject_abnormal_lines(left_lines)right_lines = reject_abnormal_lines(right_lines)return least_squares_fit(left_lines), least_squares_fit(right_lines)def draw_lines(img, lines):left_line, right_line = linescv2.line(img, tuple(left_line[0]), tuple(left_line[1]), color=(0, 255, 255),thickness=5)cv2.line(img, tuple(right_line[0]), tuple(right_line[1]),color=(0, 255, 255), thickness=5)def show_lane(color_img):edge_img = get_edge_img(color_img)mask_gray_img = roi_mask(edge_img)lines = get_lines(mask_gray_img)draw_lines(color_img, lines)return color_imgcapture = cv2.VideoCapture('video.mp4')
while True:ret, frame = capture.read()if not ret:breakframe = show_lane(frame)cv2.imshow('frame', frame)cv2.waitKey(10)

OpenCV实战案例——车道线识别相关推荐

  1. 自动驾驶入门(十二):基于Opencv的车道线识别

    车道线识别有两种方法: 基于Opencv的传统视觉车道线识别方案 基于深度学习的车道线识别方案 本文将介绍基于Opencv的传统视觉车道线识别方案. 传统的车道线识别解决方案流程图如下: 代码实现如下 ...

  2. Python OpenCV车道线识别侦测

    Python OpenCV车道线识别侦测 如需安装运行环境或远程调试,可加QQ905733049, 或QQ2945218359由专业技术人员远程协助! 运行结果如下: 代码如下: import cv2 ...

  3. python+opencv图像处理之边缘检测车道线识别

    python+opencv图像处理之边缘检测车道线识别 1.自行安装python和opencv 2.导入我们要使用的相关库 import cv2 from matplotlib import pypl ...

  4. 基于opencv的车道线识别(python)(极易实现)

    简易车道线识别方法 文章目录 简易车道线识别方法 1.先上效果图 1.1原图: 1.2结果图 2.源代码 3.阈值脚本 4.谈谈优缺点 优点: 缺点: 1.先上效果图 1.1原图: 1.2结果图 2. ...

  5. python视觉识别线条_简单车道线识别

    本文将介绍如何利用Opencv,对简单场景下的车道线进行离线识别.梳理整个识别过程的逻辑,并对过程中使用的相关知识点进行介绍.正文中使用C++实现,在文末也会附上利用python实现的代码,读者完全可 ...

  6. 基于OpenCV的实时车道线分割&车道保持系统(源码&教程)

    1.研究背景 汽车主动安全系统能够实现风险的主动预防和规避,其能有力缓解当前我国汽车交通事故频发的困境,故对其的相关研究得到了国家的大力支持. 车道保持辅助系统(LKAS,Lane Keeping A ...

  7. 基于视觉的车道线识别技术在智能车导航中的应用研究

    密级:公开 摘  要 摘  要 室外移动机器人的研究是机器人研究领域的重要分支,同时也是备受关注的热点领域.面向高速公路等结构化道路的室外移动机器人研究已成为现阶段民用交通运输领域移动机器人研究的主流 ...

  8. 基于 Amazon DeepRacer Opensource 实现自定义车道线识别任务

    点击上方[凌云驭势 重塑未来] 一起共赴年度科技盛宴! 自动驾驶的视觉感知流程 在自动驾驶系统中,作为识别周边环境的"感官"角色,感知模块是整个系统安全.高效运行的基础,让汽车得以 ...

  9. 总奖金64万!含吸烟打电话检测、车道线识别等,2020中国华录杯·数据湖算法大赛火热进行中!...

    ●赛题背景● 以"数据驱动创新,赋能智慧城市"为主题的2020中国华录杯·数据湖算法大赛,围绕"华录数据湖+智慧城市"的核心理念,着力于智慧城市业务中的真实应用 ...

  10. 吸烟打电话检测、车道线识别等,2020中国华录杯·数据湖算法大赛火热进行中!...

    ●赛题背景● 随着互联网的高速发展,"万物数据化"浪潮奔腾而来.数据湖围绕数据的全生命周期管理打造新一代数字基础设施,在硬件层面构筑了高性能.低成本.智能化.高安全的数字经济底座, ...

最新文章

  1. 《OpenCV3编程入门》学习笔记10 角点检测(二)Shi-Tomasi角点检测
  2. kd-tree理论以及在PCL 中的代码的实现
  3. 001.搭建开发环境
  4. c语言1 2 3 10000,在网上看到一个求2的10000次方的方法,有个地方看不懂,求大佬...
  5. lombok几个基本注解的使用及遇到的坑点
  6. LeetCode 1178. 猜字谜(状态压缩+枚举二进制子集+哈希)
  7. Event Organization Site - To be published on 4th August
  8. c#位数不够0补充完_C# 位数不足补零
  9. android返回键返回指定目录,Android 返回键返回到指定的Activity
  10. [SharePoint][SharePoint 2013从入门到精通]Chapter 1 介绍 SharePoint2013
  11. windows下的yolov3的运行及结果,实例所需的weights,cfg与names文件
  12. Yii2.0 两次奇葩的数据库连接经历
  13. 探索性测试ET(Exploratory Test)
  14. python再计算无限循环小数的循环节
  15. BUUCTF misc 专题(83)从娃娃抓起
  16. C++实现Socket连接通信
  17. 梯度是什么,简单说梯度下降是什么
  18. java sqlserver 插入数据_java中怎样向SQLserver中插入数据
  19. 红旗 linux 在哪儿 看 版本,简介红旗Linux不同版本的介绍
  20. Python学习 Day30 正则表达式(二)

热门文章

  1. twaver API笔记
  2. Python 多行注释
  3. 2022-03-02 组建raft集群实战及日志复制与主从切换调研
  4. 渗透测试技术_Nessus工具(一)Linux centos7下 Nessus8.13的下载、安装
  5. java微信小程序毕业设计 java微信校园运动会报名小程序系统毕业设计毕设作品参考
  6. 软考中级网络工程师的就业前景以及考试要求
  7. MySQL(4) 数据库增删改查SQL语句(整理集合大全)
  8. 使用Python进行文件快速搜索(建立文件搜索索引)
  9. 一组NOKIA数据线电路图及制作图例
  10. Cmake查找所有指定cpp文件并进行编译