Python和OpenCV - 改进我的车道检测算法

Hil*_*man 12 python algorithm opencv image-processing hough-transform

我需要从视频中检测道路车道.这是我的方式.

  1. 通过切片图像确定感兴趣区域(ROI)(聚焦中间部分)
  2. 灰度ROI
  3. 将灰度级投资回报率与平均值相等 cv2.equalizeHist
  4. 将高斯模糊应用于(3)
  5. 阈值(4)使用 cv2.adaptiveThreshold
  6. Skeletonize(5)使用 skimage.morphology.skeletonize
  7. 适用cv2.HoughLines于(6)

对于cv2.HoughLines,我设置为:

  1. 如果rho是正的(这意味着直线向右倾斜(自下而上),它只会绘制线条,如果它处于某个角度(我设置了角度的范围))
  2. 如果rho是负数(直线向左倾斜(自下而上),只有在特定角度时才会绘制直线)

这是我绘制线条的代码:

lines = cv2.HoughLines(image_bin, 1, np.pi/180, 50)
    try:
        range = lines.shape[0]
    except AttributeError:
        range = 0

    for i in xrange(range):
        for rho, theta in lines[i]:
            if rho > 0 and (np.pi*1/10 < theta < np.pi*4/10):
                a = np.cos(theta)
                b = np.sin(theta)
                x0 = a * rho
                y0 = b * rho
                x1 = int(x0 + 1000 * (-b))
                y1 = int(y0 + 1000 * (a))
                x2 = int(x0 - 1000 * (-b))
                y2 = int(y0 - 1000 * (a))

                cv2.line(roi, (x1, y1), (x2, y2), (0, 255, 0))

            if rho < 0 and (np.pi*7/10 < theta < np.pi*9/10):
                a = np.cos(theta)
                b = np.sin(theta)
                x0 = a * rho
                y0 = b * rho
                x1 = int(x0 + 1000 * (-b))
                y1 = int(y0 + 1000 * (a))
                x2 = int(x0 - 1000 * (-b))
                y2 = int(y0 - 1000 * (a))

                cv2.line(roi, (x1, y1), (x2, y2), (0, 255, 0))
Run Code Online (Sandbox Code Playgroud)

如果我没有做上面我刚才做的cv2.HoughLines功能,我相信会有很多不必要的线条被绘制出来.

调整参数后,我得到了一个相当不错的结果,但这只是一张图片.我不认为对于一个会不断变化的视频会有好处.最让我烦恼的是关于我绘制所需线条的算法(即道路车道).有没有更好的方法?至少比我好.

这是我的结果:

原始图片: 原始图片

ROI的均衡直方图,阈值化和骨架化图像: 均衡直方图,阈值化和镂空

最后结果: 最后结果

Aen*_*ed1 6

我建议考虑使用Probabilistic Hough Line Transform来满足您的应用需求.在OpenCV的Python API中,它是在函数中实现的cv2.HoughLinesP.这实际上会为您提供线段,因此您无需计算端点.它也比标准Hough Line变换快得多.

但是有一些权衡取舍.例如,您可能需要添加逻辑以将线段拼接在一起.另一方面,我发现这并不是一件坏事.我的一个玩具项目(一个自动驾驶的微型公共汽车),采用这种方法,并有单独的线段拼接在一起,使得更容易处理弯曲的道路,标准的霍夫线变换将不会给你任何线路.

希望有所帮助.

编辑:关于线段"拼接"的细节,这取决于你想要完成的.如果您只想显示道路,并且您对线段之间存在间隙感到满意,则可能不需要进行任何拼接 - 只显示所有线段.在我的应用中,我需要确定车道的曲率,所以我做了一些缝合来建立每个道路车道的模型,其中包括车道的平均坡度 - 用作负责控制车道的模块的输入.伺服相应地移动车轮.

通过"拼接"我并不意味着任何特别复杂的东西,但我不知道任何特定的OpenCV功能来实现它.我只需要一种相关线段的方式,它们是同一条线的一部分.因此,我处理了从HoughLinesP向下工作的图像顶部返回的线段,并使用每个线段的斜率和y轴截距来确定线段的相交位置.