Pixiv - KiraraShss
OpenCV 车道线识别
903 字
5 分钟
OpenCV 车道线识别
1 【基础操作】读取、展示、保存图片
import cv2
img = cv2.imread('img.jpg', cv2.IMREAD_COLOR) # 读取print(type(img)) # 获取 img 的类型,是 numpy 的矩阵print(img.shape) # 获取 img 的大小(长、宽),位深度
cv2.imshow('image', img) # 显示图片
if cv2.waitKey(0) == ord('q'): # 直到键盘按下某个值,退出显示图片。 cv2.destoryAllWindows()
cv2.imwrite('img_gray.jpg', img) # 保存图片其中,IMGREAD_COLOR 是读取类型,是彩色 。还有其他的类型:
IMREAD_GRAYSCALE:灰度图(那么 img.shape 将没有深度这一参数)
对于 imwrite() ,它会根据给定字符串中的后缀名,自动确定图片类型。必须给定合法的图片扩展名,否则会报错。
2 Canny 边缘检测

梯度是有方向的:

代码实现:
import cv2
img = cv2.imread('img.jpg', cv2.IMREAD_GRAYSCALE)
edge_img = cv2.Canny(img, 50, 100) # 图片,上阈值,下阈值,需调节优化
cv2.imshow('edges', edge_img)cv2.waitKey(0)调高下边缘与上边缘,可以有效减小噪点数量。而车道线在灰度后,有非常强的边缘(黑与白),所以保持较高的阈值是方便的。
3 ROI mask - 获取要紧的区域
ROI - Region Of Interest,感兴趣的区域。

import cv2import numpy as np
edge_img = cv2.imread('edges_img.jpg', cv2.IMREAD_GRAYSCALE)
mask = np.zero_like(edge_img)cv2.fillPoly(mask, np.array([[[0, 368], [240, 210], [300, 210], [640,368]]]), color=255) # 假设已经获取到了顶点坐标
masked_edge_img = cv2.bitwise_and(edge_img, mask) # 布尔和运算cv2.imshow('masked', masked_edge_img)cv2.waitKey(0)
4 霍夫变换,获取直线
需要使用极坐标, 确定一条直线。
liens = cv2.HoughLinesP(edge_img, 1, np.pi / 180, 15, minLineLength=40, maxLineGap=20)- edge_img:要处理的图片
- 1:精度,值越大,考虑越多的线
- np.pi/180:精度,值越大,考虑越多的线
- 累加数阈值,值越小,考虑越少的线
minLineLength:最短长度阈值,短于这个长度的线会被排除maxLineLength:同一直线两点之间最大距离
返回一个列表,里面是直线的两个端点的坐标。

5 离群值过滤
因为种种情况,可能有噪点被识别为车道线,而真正的车道线未被成功识别。
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: slops.pop(idx) lines.pop(idx) else: break return lines
# 分别对左、右车道线进行过滤reject_abnormal_lines(left_lines, threshold=0.2)reject_abnormal_liens(right_lines, threshold=0.2)过滤后的效果:

6 最小二乘拟合 - 最后一步
对于识别出来的这么多左车道线、右车道线,我们需要将它们合并成同一条完整的车道线。
import numpy as np
np.ravel() # 将高维数组压成一维函数(比如把矩阵变成数组)poly = np.polyfit([0, 3, 6, 9], [0, 5, 9, 14], deg=1) # 多项式拟合,参数:几个 x 坐标,几个 y 坐标,多项式次数np.polyval(poly, x0) # 多项式求值ravel 示例:

7 车道线标注
绘制直线:cv2.line
cv2.line(img, (10, 10), (200, 100), 255, 3)# 图像,一个端点,另一个端点,色彩值(彩色图为(r, g, b)),宽度

8 视频流处理
读取视频流:capture = cv2.VideoCapture('video.mp4') ,如果传入的是数字,就会使用相应序号的摄像头。
读取:ret, frame = capture.read() ,分别读取状态、图片帧。
capture = cv2.VideoCapture('video.mp4')
while True: ret, frame = capture.read() # frame = show_lane(frame) cv2.imshow('frame', frame) cv2.waitKey(100) # 等待 100 ms9 值得改进的地方
- 边缘检测时,有很多弱边缘,可以尝试使用高斯模糊,或给它腐蚀一下,让弱边缘变得更模糊!这样就能有效过滤掉了。
- 左车道线只有一部分,很容易只画出一部分(如图),可以尝试使它延伸到图像边缘。

支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!
OpenCV 车道线识别
https://www.0x3f.foo/posts/opencvtutorial/ 相关文章 智能推荐
1
高中信息技术之递归题解(一)
笔记本 2024-10-06
2
信息技术之链表
笔记本 2024-07-07
3
Pandas 学习笔记
笔记本 2024-04-14
4
技术学习笔记之 PIL 模块
笔记本 2024-01-24
5
技术学习笔记之 Python 语言基础
笔记本 2023-12-07
随机文章 随机推荐
无穷大?