• SLAM从入门到精通(车道线检测)


    【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

            对于slam而言,大家一般想到的就是去通过传感器找特征点,进而借助于特征点去定位机器人的位置。但是对于用户或者厂家来说,他们很多时候对机器人在道路上的精度不做要求,但对工位上的对接要求很高。所以,对于供应商来说,是不是整个定位和导航都需要借助于传感器或者反光柱,这就两说了。

            此外,相比较室外而言,工厂内部的光源一般会好一点。就算条件不是很好,我们自己也可以通过补充光源的形式加以修正。所以,对于机器人来说,一种不错的导航方法就是借助于路面来机器人的自我定位,相信也是可以考虑的一个选择。

            网上关于车道线检测的代码不少,我们不妨找一个来学习和参考下,之前文章的地址如下,

    https://www.cnblogs.com/wojianxin/p/12624096.html

    1、图像灰化,提取边缘信息

    1. # 1. 灰度化、滤波和Canny
    2. gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
    3. blur_gray = cv.GaussianBlur(gray, (blur_ksize, blur_ksize), 1)
    4. edges = cv.Canny(blur_gray, canny_lth, canny_hth)

    2、兴趣区域截取

    1. # 2. 标记四个坐标点用于ROI截取
    2. rows, cols = edges.shape
    3. points = np.array([[(0, rows), (460, 325), (520, 325), (cols, rows)]])
    4. # [[[0 540], [460 325], [520 325], [960 540]]]
    5. roi_edges = roi_mask(edges, points)

    3、利用HoughLinesP函数提取直线

    1. # 3. 霍夫直线提取
    2. drawing, lines = hough_lines(roi_edges, rho, theta,
    3. threshold, min_line_len, max_line_gap)

    4、车道线拟合

            生成的车道线很多,这个步骤主要是将多个车道线拟合成左右各两条直线。其中左边直线的斜率大于等于0,右边直线的斜率小于等于0。整个拟合的过程中使用到了最小二乘法。

    1. # 4. 车道拟合计算
    2. draw_lanes(drawing, lines)

    5、绘制车道线

            拟合出来的车道线,最终需要放到原来的图片上,验证一下实现的效果。

    1. # 5. 最终将结果合在原图上
    2. result = cv.addWeighted(img, 0.9, drawing, 0.2, 0)

    6、完整的代码

    1. import cv2 as cv
    2. import numpy as np
    3. # 高斯滤波核大小
    4. blur_ksize = 5
    5. # Canny边缘检测高低阈值
    6. canny_lth = 50
    7. canny_hth = 150
    8. # 霍夫变换参数
    9. rho = 1
    10. theta = np.pi / 180
    11. threshold = 15
    12. min_line_len = 40
    13. max_line_gap = 20
    14. def process_an_image(img):
    15. # 1. 灰度化、滤波和Canny
    16. gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
    17. blur_gray = cv.GaussianBlur(gray, (blur_ksize, blur_ksize), 1)
    18. edges = cv.Canny(blur_gray, canny_lth, canny_hth)
    19. # 2. 标记四个坐标点用于ROI截取
    20. rows, cols = edges.shape
    21. points = np.array([[(0, rows), (460, 325), (520, 325), (cols, rows)]])
    22. # [[[0 540], [460 325], [520 325], [960 540]]]
    23. roi_edges = roi_mask(edges, points)
    24. # 3. 霍夫直线提取
    25. drawing, lines = hough_lines(roi_edges, rho, theta,
    26. threshold, min_line_len, max_line_gap)
    27. # 4. 车道拟合计算
    28. draw_lanes(drawing, lines)
    29. # 5. 最终将结果合在原图上
    30. result = cv.addWeighted(img, 0.9, drawing, 0.2, 0)
    31. return result
    32. def roi_mask(img, corner_points):
    33. # 创建掩膜
    34. mask = np.zeros_like(img)
    35. cv.fillPoly(mask, corner_points, 255)
    36. masked_img = cv.bitwise_and(img, mask)
    37. return masked_img
    38. def hough_lines(img, rho, theta, threshold, min_line_len, max_line_gap):
    39. # 统计概率霍夫直线变换
    40. lines = cv.HoughLinesP(img, rho, theta, threshold,
    41. minLineLength=min_line_len, maxLineGap=max_line_gap)
    42. # 新建一副空白画布
    43. drawing = np.zeros((img.shape[0], img.shape[1], 3), dtype=np.uint8)
    44. # 画出直线检测结果
    45. # draw_lines(drawing, lines)
    46. # print(len(lines))
    47. return drawing, lines
    48. def draw_lines(img, lines, color=[0, 0, 255], thickness=1):
    49. for line in lines:
    50. for x1, y1, x2, y2 in line:
    51. cv.line(img, (x1, y1), (x2, y2), color, thickness)
    52. def draw_lanes(img, lines, color=[255, 0, 0], thickness=8):
    53. # a. 划分左右车道
    54. left_lines, right_lines = [], []
    55. for line in lines:
    56. for x1, y1, x2, y2 in line:
    57. k = (y2 - y1) / (x2 - x1)
    58. if k < 0:
    59. left_lines.append(line)
    60. else:
    61. right_lines.append(line)
    62. if (len(left_lines) <= 0 or len(right_lines) <= 0):
    63. return
    64. # b. 清理异常数据
    65. clean_lines(left_lines, 0.1)
    66. clean_lines(right_lines, 0.1)
    67. # c. 得到左右车道线点的集合,拟合直线
    68. left_points = [(x1, y1) for line in left_lines for x1, y1, x2, y2 in line]
    69. left_points = left_points + [(x2, y2)
    70. for line in left_lines for x1, y1, x2, y2 in line]
    71. right_points = [(x1, y1)
    72. for line in right_lines for x1, y1, x2, y2 in line]
    73. right_points = right_points + \
    74. [(x2, y2) for line in right_lines for x1, y1, x2, y2 in line]
    75. left_results = least_squares_fit(left_points, 325, img.shape[0])
    76. right_results = least_squares_fit(right_points, 325, img.shape[0])
    77. # 注意这里点的顺序
    78. vtxs = np.array(
    79. [[left_results[1], left_results[0], right_results[0], right_results[1]]])
    80. # d.填充车道区域
    81. cv.fillPoly(img, vtxs, (0, 255, 0))
    82. # 或者只画车道线
    83. # cv.line(img, left_results[0], left_results[1], (0, 255, 0), thickness)
    84. # cv.line(img, right_results[0], right_results[1], (0, 255, 0), thickness)
    85. def clean_lines(lines, threshold):
    86. # 迭代计算斜率均值,排除掉与差值差异较大的数据
    87. slope = [(y2 - y1) / (x2 - x1)
    88. for line in lines for x1, y1, x2, y2 in line]
    89. while len(lines) > 0:
    90. mean = np.mean(slope)
    91. diff = [abs(s - mean) for s in slope]
    92. idx = np.argmax(diff)
    93. if diff[idx] > threshold:
    94. slope.pop(idx)
    95. lines.pop(idx)
    96. else:
    97. break
    98. def least_squares_fit(point_list, ymin, ymax):
    99. # 最小二乘法拟合
    100. x = [p[0] for p in point_list]
    101. y = [p[1] for p in point_list]
    102. # polyfit第三个参数为拟合多项式的阶数,所以1代表线性
    103. fit = np.polyfit(y, x, 1)
    104. fit_fn = np.poly1d(fit) # 获取拟合的结果
    105. xmin = int(fit_fn(ymin))
    106. xmax = int(fit_fn(ymax))
    107. return [(xmin, ymin), (xmax, ymax)]
    108. if __name__ == "__main__":
    109. img = cv.imread('img02.jpg')
    110. result = process_an_image(img)
    111. cv.imshow("lane", np.hstack((img, result)))
    112. cv.waitKey(0)

            执行方法也非常简单,直接输入python3 checkplane.py即可。注意,这里测试的图片是img02.jpg,大家可以换成自己的测试图片。最后,非常感谢原作者给出的参考代码。

  • 相关阅读:
    【HarmonyOS】鸿蒙入门学习
    基于Vite初始化前端项目
    SpringBoot后端解决跨域问题
    Spark和Hadoop的对比
    点云从入门到精通技术详解100篇-低重叠率三维点云配准及点云数据一体化处理系统开发
    Jquery会议室布局含门入口和投影位置调整,并自动截图
    Redis基础篇:初识Redis(认识NoSQL,单机安装Redis,配置Redis自启动,Redis客户端的基本使用)
    一般处理程序ashx接入微信服务器配置
    决策树详解
    word使用攻略
  • 原文地址:https://blog.csdn.net/feixiaoxing/article/details/134258632