文章目录

  • 前言
  • 一、openCV安装
  • 二、尝试使用cv2中库函数
    • 1.读取图片
    • 2.图片显示
    • 3.延时/暂停
    • 4.保存图片
    • 5.清楚所有窗口
  • 三、Canny边缘检测
    • 1.高斯滤波
    • 2.图片转换
    • 3.边缘检测
  • 四、ROI and mask
  • 五、霍夫变换
  • 六、离群值过滤
  • 七、最小二乘法拟合
  • 八、车道线标注
  • 九、视频读写
    • 1.打开视频
    • 2.按帧读取视频
    • 3.视频编码格式设置
    • 4.写视频参数设置
  • 十、其他
  • 总结
  • 附视频检测完整程序

前言

本文使用python+openCV
用到的算法:
高斯滤波
Canny边缘检测
ROI和mask
霍夫变换
离群值过滤
最小二乘法拟合


一、openCV安装

win+x选择运行,然后输入cmd
输入pip install opencv-python等待安装
在IDLE中新建脚本.py文件,输入import cv2,如果无报错即为安装成功。
再输入print(cv2.__version__)可查看openCV版本。

二、尝试使用cv2中库函数

1.读取图片

cv2.imread(const String & filename, int flags = IMREAD_COLOR)

第一个参数是窗口的名字,第二个参数是读取格式(彩色或灰度),函数返回值是图片转换格式后所对应的列表。

img = cv2.imread('img.jpg',cv2.IMREAD_GRAYSCALE)

2.图片显示

cv2.imshow(window_name, img)

第一个参数是窗口的名字,可以创建多个窗口,但是必须给他们不同的名字。第二个参数是显示格式,可以是img图片格式,也可以是mat数组格式。

3.延时/暂停

cv2.waitKey(int x)

相当于程序延时,调整cv2.imshow()的显示时间。延时时间为x毫秒。返回值为在延时期间按下键盘上按键所对应的ASCII值。

x=0时,即cv2.waitKey(0)表示程序停在此处,直到手动关闭cv2.imshow()的窗口。
例如设计一个,无穷延时,当键盘按下q时退出。

if cv2.waitKey(1) & 0xFF == ord(‘q’): break
#ord()是将字符转换为ASCII码

4.保存图片

cv2.imwrite(newfile_name, img)

第一个参数是保存的新图片的文件名,第二个参数是应保存的图片对应的列表。

5.清楚所有窗口

cv2.destroyAllWindows()

关闭所有openCV打开的窗口。

三、Canny边缘检测

CV2提供了提取图像边缘的函数canny。其算法思想如下:
1. 使用高斯模糊,去除噪音点(cv2.GaussianBlur)
2. 灰度转换(cv2.cvtColor)
3. 使用sobel算子,计算出每个点的梯度大小和梯度方向
4. 使用非极大值抑制(只有最大的保留),消除边缘检测带来的杂散效应
5. 应用双阈值,来确定真实和潜在的边缘
6. 通过抑制弱边缘来完成最终的边缘检测

1.高斯滤波

gaussian = cv2.GaussianBlur(color_img, (gaussian_ksize,gaussian_ksize), gaussian_sigmax)

color_img 输入图片
gaussian_ksize 高斯核大小,可以为方形矩阵,也可以为矩形
gaussian_sigmax X方向上的高斯核标准偏差
没看太懂这个函数,目前仅局限于搬来直接用,下次一定

2.图片转换

gray_img = cv2.cvtColor(input_image, flag)

用于颜色空间转换。input_image为需要转换的图片,flag为转换的类型,返回值为颜色空间转换后的图片矩阵。flag对应:
cv2.COLOR_BGR2GRAY BGR -> Gray
cv2.COLOR_BGR2RGB BGR -> RGB
cv2.COLOR_BGR2HSV BGR -> HSV
可以了解一下该函数和cv2.imread()的区别

3.边缘检测

edge_img = cv2.Canny(gray_img,canny_threshold1,canny_threshold2)

imag为所操作的图片,threshold1为下阈值,threshold2为上阈值,返回值为边缘图。

四、ROI and mask

利用数组选取ROI(region of interest,感性趣的区域,然后与原图进行布尔运算(与运算)。

poly_pts = numpy.array([[[0,368],[300,210],[340,210],[640,368]]])

四个数组创建后保存在变量poly_pts中。

mask = np.zeros_like(gray_img)

构建一个与gray_img同维度的数组,并初始化所有变量为零。

cv2.fillPoly(mask, pts, color)

绘制多边形函数。mask为绘制对像,pts为绘制范围,color为绘制颜色。

img_mask = cv2.bitwise_and(gray_img, mask)

与运算

五、霍夫变换

得到一系列的直线

lines = cv2.HoughLinesP(edge_img,  1, np.pi / 180, 15, minLineLength=40, maxLineGap=20)

edge_img: 要检测的图片矩阵
参数2: 距离r的精度,值越大,考虑越多的线
参数3: 距离theta的精度,值越大,考虑越多的线
参数4: 累加数阈值,值越小,考虑越多的线
minLineLength: 最短长度阈值,短于这个长度的线会被排除
maxLineGap:同一直线两点之间的最大距离
返回值::
[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]])]

六、离群值过滤

循环查找超出设定范围的斜率,并去除。

idx = np.argmax(diff)

当diff中存放的是一维时,找到diff中最大的数值,并返回该值所在位置。

示例:
one_dim_array = np.array([1, 4, 5, 3, 7, 2, 6])
print(np.argmax(one_dim_array))打印结果为    4
lines.pop(idx)

从列表lines中把第idx数去除

七、最小二乘法拟合

获得左车道线和右车道线的理想直线

x_coords = np.ravel([[line[0][0], line[0][2]] for line in lines])

将多维数组降为一维
还未想明白转换关系,下次一定

poly = np.polyfit(x, y, deg)

x, y为各个点的横纵坐标,deg为拟合曲线的次数

y_e = np.polyval(poly, x)

拟合曲线之后,x在曲线上对应的y值

八、车道线标注

cv2.line(img, tuple(line[0]), tuple(line[1]), color,thickness)

在图片上画线,img为所标注的目标图片,ine[0]为起点坐标,line[1]为终点坐标,thickness为线宽。
注意两个坐标需要为tuple元组格式,即tuple(line[0])

九、视频读写

1.打开视频

capture = cv2.VideoCapture('video.mp4')

如果为cv2.VideoCapture(0),表示打开笔记本的内置摄像头。

2.按帧读取视频

ret, frame = capture.read()

其中ret是布尔值,如果读取帧是正确的则返回True,如果文件读取到结尾,它的返回值就为False。
frame就是每一帧的图像,是个三维矩阵。

3.视频编码格式设置

fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')

fourcc意为四字符代码(Four-Character Codes),顾名思义,该编码由四个字符组成,下面是VideoWriter_fourcc对象一些常用的参数,注意:字符顺序不能弄混
cv2.VideoWriter_fourcc(‘I’, ‘4’, ‘2’, ‘0’),该参数是YUV编码类型,文件名后缀为.avi
cv2.VideoWriter_fourcc(‘P’, ‘I’, ‘M’, ‘I’),该参数是MPEG-1编码类型,文件名后缀为.avi
cv2.VideoWriter_fourcc(‘X’, ‘V’, ‘I’, ‘D’),该参数是MPEG-4编码类型,文件名后缀为.avi
cv2.VideoWriter_fourcc(‘T’, ‘H’, ‘E’, ‘O’),该参数是Ogg Vorbis,文件名后缀为.ogv
cv2.VideoWriter_fourcc(‘F’, ‘L’, ‘V’, ‘1’),该参数是Flash视频,文件名后缀为.flv

4.写视频参数设置

outfile = cv2.VideoWriter(filename, fourcc, 25, (1280,368))

filename为写入视频的文件名,fourcc为视频编码格式cv2.VideoWriter_fourcc()的返回值,25为帧率,(1280,368)为视频大小。

ret, frame = capture.read()

第一个参数ret 为布尔值即True 或者False,代表有没有读取到图片,第二个参数frame表示截取到一帧的图片

output = np.concatenate((origin, frame), axis=1)

能够一次完成多个数组的拼接
不写axis参数的话,默认为按列拼接;若axis = 1的话,即为按行拼接;
axis参数意义没搞太明白,下次一定

十、其他

程序存在小bug但不影响检测视频生成,如果哪位大佬知道bug怎么解决记得踢我一脚。
cv2.imshow()总是卡住无响应,无法自己关闭窗口,使用cv2.destroyAllWindows()也还是卡住;
而且报告错误:

error: OpenCV(4.5.5) D:\a\opencv-python\opencv-python\opencv\modules\imgproc\src\smooth.dispatch.cpp:617: error: (-215:Assertion failed) !_src.empty() in function 'cv::GaussianBlur'
> 卡住的问题有人说是openCV对一部分硬件的适配不好,我比较在赞成这种观点。 报错  cv2.error  error:
> (-215:Assertion failed) dst.data == (uchar*)dst_ptr in function
> 'cvShowImage'
>
> 同样的代码,我发现在公司电脑1060上,cv2.imshow()就可以显示,但在自己2080ti上就总是报错如上。于是锁定在cv2版本问题,果然卸掉最新的4.0版本,换上3.4.4.19就好了。
>
> 可能是4.0版本与2080ti的卡还不兼容。
> 来源:https://blog.csdn.net/qq_39938666/article/details/88179966

报错的问题目前未解决,也修改不掉。

总结

完全实现对视频形式的单车道直线行驶时对车道线检测和标注。

附视频检测完整程序

import cv2
import numpy as np#高斯滤波+canny边缘检测
def get_edge_img(color_img, gaussian_ksize=5, gaussian_sigmax=1,canny_threshold1=50, canny_threshold2=100):#param intoduction#color_img 输入图片    gaussian_ksize 高斯核大小#gaussian_sigmax X方向上的高斯核标准偏差gaussian = cv2.GaussianBlur(color_img, (gaussian_ksize, gaussian_ksize),gaussian_sigmax)gray_img = cv2.cvtColor(gaussian,cv2.IMREAD_GRAYSCALE)edge_img = cv2.Canny(gray_img,canny_threshold1,canny_threshold2);return edge_imgdef roi_mask(gray_img):poly_pts = np.array([[[0,368],[300,210],[340,210],[640,368]]])mask = np.zeros_like(gray_img)cv2.fillPoly(mask, pts=poly_pts, color=255)img_mask = cv2.bitwise_and(gray_img, mask)return img_maskdef get_lines(edge_img):#斜率计算def calculate_slope(line):x_1, y_1, x_2, y_2 = line[0]slope = (y_2-y_1)/(x_2-x_1)return slope#离群值过滤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 lines#最小二乘拟合def least_squares_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])# 2. 进行直线拟合.得到多项式系数poly = np.polyfit(x_coords, y_coords, deg=1)# 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.int0)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, threshold=0.2)right_lines = reject_abnormal_lines(right_lines, threshold=0.2)return least_squares_fit(left_lines),least_squares_fit(right_lines)def draw_line(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_line(color_img, lines)return color_imgif __name__ == '__main__':capture = cv2.VideoCapture('video.mp4')fourcc = cv2.VideoWriter_fourcc('X', 'V', 'I', 'D')outfile = cv2.VideoWriter('output.avi', fourcc, 25, (1280,368))while True:ret, frame = capture.read() origin = np.copy(frame)frame = show_lane(frame)output = np.concatenate((origin, frame), axis=1)outfile.write(output)cv2.imshow('video', output)cv2.waitKey(10)

分步操作检测图片和检测视频的源码、测试图片和测试视频连接:https://download.csdn.net/download/qq_27839923/75831347

python+openCV (入门级)车道线检测 学习笔记相关推荐

  1. Python+OpenCV实现车道线检测代码部分

    实验时 使用的是python3.7+cv2,直接在Anaconda上面直接安装,代码在Jupyter上跑的,图片是老师给的(-.-) 经过各个滤波后,划定区域 : 最终合成的图像 : 最后实际上是先把 ...

  2. Python实现道路车道线检测(附源码)

    车道线检测是自动驾驶汽车以及一般计算机视觉的关键组件.这个概念用于描述自动驾驶汽车的路径并避免进入另一条车道的风险. 在本文中,我们将构建一个机器学习项目来实时检测车道线. 我们将使用 OpenCV ...

  3. 使用OpenCV实现车道线检测

    点击上方"小白学视觉",选择"星标"公众号 重磅干货,第一时间送达 图0 印度泰米尔纳德邦安纳马莱森林公路上的车道检测 本文源码:https://github. ...

  4. 车道线检测传统方法笔记

    车道线检测是自动驾驶中的一个基础模块,车道保持,自适应巡航,自动变道:对于全自动驾驶汽车后续的车道偏离或轨迹规划决策也很重要. 目前车道线检测主要有两种方案:传统方法与深度学习. 1.传统方法 (1) ...

  5. Python初步实现车道线检测

    车道线检测是一个常见的问题,本文主要介绍如何简单有效的用python实现这个功能 主要思路 1 读取图像并选择感兴趣的区域ROI进行下一步处理 2 对ROI区域进行预处理包括灰度化,膨胀和腐蚀 3 对 ...

  6. 基于OpenCV 的车道线检测方法

    车道线检测是图像处理运用到无人驾驶的一项技术,目前也过渡到了部分汽车上,高速公路的自动车道保持就是一个应用. 最近研究了两个基于opencv的车道检的代码,先放链接: A.Udacity车道线检测代码 ...

  7. 机器学习实践系列之11 - OpenCV实战车道线检测

    ADAS 在经过资本的一轮热炒之后已经不新鲜了,Mobile Eye的技术积累和效果也让很多童鞋叹为观止,然后奋起直指! 初学者为代表的童鞋,二话不说,上来就是霍夫变换,还是直接用opencv里带的, ...

  8. python车道线检测

    车道线检测是一种利用计算机视觉技术来识别和跟踪道路上的车道线的方法,它对于自动驾驶和智能交通系统等领域有着重要的应用价值.车道线检测的基本步骤如下: 边缘检测:使用Canny算法对输入的图像进行边缘检 ...

  9. Opencv-Python处理车道线检测

    利用Opencv和Python结合完成车道线检测 1 前言 去年对Opencv系统学习了一段时间,后面没有继续更新博客,但自己也有继续学习啦,哈哈,最近做了一个小项目,利用图像处理算法解决车道线检测. ...

最新文章

  1. 生信服务器 | 防火墙基本配置
  2. java接口和实例_java – 接口和实例化
  3. Hadoop手动升级HA配置手册
  4. python web django base skill
  5. java读取csv文件
  6. switch字符串jdk_从JDK 12删除原始字符串文字
  7. Word 2003中为什么修改一个段落的文章结果整篇文档的格式都变?
  8. 计算机课设容易挂吗,数学差的学生避开这4大专业,挂科是常态,每年都有学生不能毕业...
  9. python使用英汉大字典离线获取单词释义
  10. 武科大计算机专业分数线,2020武汉科技大学录取分数线_历年各专业分数线(2017-2019)_各省投档线_一品高考网...
  11. java里有位移吗_Java 中位移运算符 ,,
  12. 龙腾世纪:起源(推荐一个可以用来英语学习的RPG游戏)
  13. python 列表定义 初始化为0_Python为列表添加一个foreach方法
  14. VRRP技术原理与注意点
  15. Matlab将double类型转换为正整数类型
  16. JavaScript详细教程归纳
  17. 机器人关节伺服电机PID串级控制
  18. 关于如何职业规划和选择换工作
  19. js随机飘动的广告图片代码demo效果示例(整理)
  20. 银行卡正则,验证银行卡是否有效

热门文章

  1. 双击 计算机 打不开,电脑软件双击打不开,是什么回事?怎么处理?
  2. 开源云原生平台对比 KubeSphere vs Rainbond
  3. 两个玻璃球和100层楼的问题
  4. mybatis集成p6spy
  5. iphone4拆机换屏宝典
  6. 戏说 .NET GDI+系列学习教程(二、Graphics类的方法)
  7. dlib人脸对齐源码详解
  8. php安装与下载,学习PHP网站开发 连载——PHPCMS的下载与安装详解
  9. [转]借闪光灯的东风 成就你完美的摄影作品
  10. 李嘉诚的商业忠告(转)