Nanometer 发表于 2021-7-9 13:17

[Python] OpenCV+霍夫直线检测的车道线识别

本帖最后由 Nanometer 于 2021-7-10 14:21 编辑

简单路面还说的过去 遇到复杂路面直接白给












代码:
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt


def do_canny(frame):
    # 边缘检测
    gray = cv.cvtColor(frame, cv.COLOR_RGB2GRAY)
    # 使用5*5的高斯模糊 具体参数自己调
    blur = cv.GaussianBlur(gray, (5, 5), 0)
    # 边缘检测最小值50 最大值150
    canny = cv.Canny(blur, 50, 150)
    return canny


def do_segment(frame):
    # height = frame.shape
    # 适合 D:\\sys\\wfpri\\Videos\\Euro Truck Simulator 2\\3.mp4 的区域遮罩
    polygons = np.array([
      [(850, 490), (1030, 490), (1200, 600), (800, 600)]
    ])

    mask = np.zeros_like(frame)
    cv.fillPoly(mask, polygons, 255)
    segment = cv.bitwise_and(frame, mask)
    return segment


def calculate_lines(frame, lines):
    left = []
    right = []
    mid = []
    for line in lines:
      # print(line)
      x1, y1, x2, y2 = line.reshape(4)
      parameters = np.polyfit((x1, x2), (y1, y2), 1)
      # print(parameters)
      slope = parameters
      y_intercept = parameters
      if slope < 0:
            left.append((slope, y_intercept))
      else:
            right.append((slope, y_intercept))

    left_avg = np.average(left, axis=0)
    right_avg = np.average(right, axis=0)
    left_line = calculate_coordinates(frame, left_avg)
    right_line = calculate_coordinates(frame, right_avg)

    minx1 = left_line + int((right_line - left_line) / 2)
    miny1 = right_line
    minx2 = left_line + int((right_line - left_line) / 2)
    miny2 = right_line

    mid_line_tmp = [
      minx1,
      miny1,
      minx2,
      miny2]
    # 左边缘线中点坐标
    left_line_minPX = int((left_line + left_line) / 2)
    left_line_minPY = int((left_line + left_line) / 2)
    # 右边缘线中点坐标
    right_line_minPX = int((right_line + right_line) / 2)
    right_line_minPY = int((right_line + right_line) / 2)
    # 左右边缘线中点辅助线
    left_line_minP = np.array()
    right_line_minP = np.array()
    # 左右边缘线中点连接辅助线
    connect_left_line_minP_right_line_minP = np.array(
      )
    # 左右边缘线中点连接辅助线中点
    min_linePX1 = int((left_line_minPX + right_line_minPX) / 2)
    min_linePY1 = int((left_line_minPY + right_line_minPY) / 2)
    # 左右边缘线中点连接辅助线中点辅助线
    connect_left_line_minP_right_line_minP_min = np.array(
      )
    # 车道线数组
    lane_line = np.array()
    isHave, point = cross_point(left_line, right_line)

    # 相对于中心的偏移
    deviationX = min_linePX1 - int(point)

    connect_deviation = np.array()
    # 方向纠正提示
    if deviationX > 20:
      cv.putText(frame, 'You need to turn the direction to the right', (0, 40), cv.FONT_HERSHEY_DUPLEX, 2,
                   (255, 255, 255), 1)
    elif deviationX < -20:
      cv.putText(frame, 'You need to turn the direction to the left', (0, 40), cv.FONT_HERSHEY_DUPLEX, 2,
                   (255, 255, 255), 1)
    else:
      cv.putText(frame, 'Driving in a straight line', (0, 40), cv.FONT_HERSHEY_DUPLEX, 2, (255, 255, 255), 1)
    deviation_line = np.array(
      )
    # 偏移线数组
    deviations = np.array()
    # mid_line_tmp,
    # 复制线数组
    guide = np.array()

    return lane_line, guide, deviations


def calculate_coordinates(frame, parameters):
    slope, intercept = parameters
    y1 = 700
    y2 = int(y1 - 150)
    x1 = int((y1 - intercept) / slope)
    x2 = int((y2 - intercept) / slope)

    return np.array()


def visualize_lines(frame, lines):
    lines_visualize = np.zeros_like(frame)
    if lines is not None:
      index = 0
      last = []
      for x1, y1, x2, y2 in lines:
            index += 1
            cv.line(lines_visualize, (x1, y1), (x2, y2), (0, 255, 0), 6)
            if index % 2 == 0:
                b = np.array([[, , , last], , last]]], dtype=np.int32)
                cv.fillPoly(lines_visualize, b, (225, 0, 20))
            last =

    return lines_visualize


def visualize_guide_lines(frame, lines):
    lines_guide_visualize = np.zeros_like(frame)
    if lines is not None:
      for x1, y1, x2, y2 in lines:
            cv.line(lines_guide_visualize, (x1, y1), (x2, y2), (255, 255, 0), 3)
    return lines_guide_visualize


def visualize_deviations_lines(frame, lines):
    lines_deviations_visualize = np.zeros_like(frame)
    if lines is not None:
      for x1, y1, x2, y2 in lines:
            cv.line(lines_deviations_visualize, (x1, y1), (x2, y2), (0, 0, 255), 2)
    return lines_deviations_visualize


"""
# 计算两条直线的交点

:parameter line1 直线1
:parameter line2 直线2

:return Bool point_is_exist 交点是否存在
:return Array 交点
"""


def cross_point(line1, line2):
    point_is_exist = False
    x = y = 0
    x1, y1, x2, y2 = line1
    x3, y3, x4, y4 = line2
    if (x2 - x1) == 0:
      k1 = None
      b1 = 0
    else:
      k1 = (y2 - y1) * 1.0 / (x2 - x1)# 计算k1,由于点均为整数,需要进行浮点数转化
      b1 = y1 * 1.0 - x1 * k1 * 1.0# 整型转浮点型是关键
    if (x4 - x3) == 0:# L2直线斜率不存在
      k2 = None
      b2 = 0
    else:
      k2 = (y4 - y3) * 1.0 / (x4 - x3)# 斜率存在
      b2 = y3 * 1.0 - x3 * k2 * 1.0
    if k1 is None:
      if not k2 is None:
            x = x1
            y = k2 * x1 + b2
            point_is_exist = True
    elif k2 is None:
      x = x3
      y = k1 * x3 + b1
    elif not k2 == k1:
      x = (b2 - b1) * 1.0 / (k1 - k2)
      y = k1 * x * 1.0 + b1 * 1.0
      point_is_exist = True

    return point_is_exist,


# cap = cv.VideoCapture("D:\\sys\\wfpri\\Videos\\Euro Truck Simulator 2\\2.mp4")
# cap = cv.VideoCapture("C:\\vol0\\input.mp4")
# cap = cv.VideoCapture("input.mp4")


cap = cv.VideoCapture("D:\\sys\\wfpri\\Videos\\Euro Truck Simulator 2\\3.mp4")

while (cap.isOpened()):
    # ret = a boolean return value from getting the frame, frame = the current frame being projected in the video
    ret, frame = cap.read()
    canny = do_canny(frame)
    cv.imshow("canny", canny)
    # plt.imshow(frame)
    # plt.show()
    segment = do_segment(canny)

    segment2 = do_segment(frame)
    cv.imshow("segment", segment2)

    # hough = cv.HoughLinesP(segment, 2, np.pi / 180, 100, np.array([]), minLineLength=0, maxLineGap=100)
    # hough = cv.HoughLinesP(segment, 1, np.pi / 180, 100, np.array([]), minLineLength=0, maxLineGap=100)
    # 霍夫直线参数
    rho = 1
    theta = np.pi / 180
    threhold = 10
    minlength = 40
    maxlengthgap = 150
    hough = cv.HoughLinesP(segment, rho, theta, threhold, np.array([]), minlength, maxlengthgap)
    if hough is not None:

      try:
            lines, guide, deviations = calculate_lines(frame, hough)
            lines_guide = visualize_guide_lines(frame, guide)
            lines_visualize = visualize_lines(frame, lines)
            lines_deviations = visualize_deviations_lines(frame, deviations)
            output = cv.addWeighted(frame, 0.9, lines_guide, 1, 1)
            output2 = cv.addWeighted(output, 0.9, lines_visualize, 0.2, 1)
            output3 = cv.addWeighted(output2, 0.9, lines_deviations, 1, 1)
            cv.imshow("output", output3)
      except Exception as e:
            pass
    if cv.waitKey(10) & 0xFF == ord('q'):
      break
cap.release()
cv.destroyAllWindows()

视频素材:链接:https://pan.baidu.com/s/1JSoERfSwoy50fN51HJo_-Q 提取码:pykk

Nanometer 发表于 2021-7-10 14:12

本帖最后由 Nanometer 于 2021-7-10 14:18 编辑

hj170520 发表于 2021-7-9 15:40
请问这需要训练模型吗?
不需要 这个只是识别指定区域里的实线 总之挺拉胯的 但是之前看了一个大佬的语义分割的视频 可以尝试做一下语义分割 把车道线 车辆 行车标志分割出来 还是苦于数学基础不过关 哎

pandora01 发表于 2021-7-9 13:29

太强了,老哥厉害啊

默默 发表于 2021-7-9 13:39

看起来还不错,下载试一试。感谢楼主分享!

ileave 发表于 2021-7-9 13:43

先膜拜再学习

失重ss 发表于 2021-7-9 14:44

可以可以,好久没用OpenCV了

Magical-E 发表于 2021-7-9 14:49

插眼,下学期我们也要搞这个

IITSUKI 发表于 2021-7-9 14:51

D盘的视频提供一下可以吗{:301_999:}

hj170520 发表于 2021-7-9 15:40

请问这需要训练模型吗?{:301_984:}

KevINBy 发表于 2021-7-9 16:00

自动驾驶?

Nanometer 发表于 2021-7-10 14:04

KevINBy 发表于 2021-7-9 16:00
自动驾驶?

不是 车道线识别而已 高级东西做不出来
页: [1] 2
查看完整版本: [Python] OpenCV+霍夫直线检测的车道线识别