基于OpenCV的高效巡线方案解析

目录

背景

实际效果:

两侧车道线效果:

 单侧车道线效果:

 十字路口车道线补齐

 代码讲解:

基础部分:

十字路口补线:

缺点:

 注意事项:


背景

        在参加17届智能车百度智慧交通组竞赛的时候我脑子里就有两套方案,一套是基于传统opencv的巡线,一套是用paddle搭建神经网络框架,但由于时间有限,只能利用假期闲余时间继续写完未完成的opencv巡线

        灵感来源于CSDN一位老哥的博客,但我找不到了他的那篇博客,只有代码(图中csdn借取.py)感谢老哥

实际效果:

两侧车道线效果:

 单侧车道线效果:

 十字路口车道线补齐

 

 代码讲解:

基础部分:

import cv2
import numpy
import numpy as np

# cap = cv2.VideoCapture(0)
cap = cv2.VideoCapture("./1.mp4")

while True:
    test, frame = cap.read()

    frame = cv2.resize(frame, (int(frame.shape[0] / 1080 * 640), int(frame.shape[1] / 1920 * 480)))
    frameBGR = cv2.GaussianBlur(frame, (7, 7), 0)

    hsv = cv2.cvtColor(frameBGR, cv2.COLOR_BGR2HSV)
    # 车道线颜色
    colorLow = numpy.array([16, 65, 65])
    colorHigh = numpy.array([80, 225, 180])
    # 加入掩膜
    mask = cv2.inRange(hsv, colorLow, colorHigh)

    kernal = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7))
    # 通胀腐蚀消除干扰
    mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernal)
    mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernal)

    left = np.array([])
    leftb = np.array([])
    right = np.array([])
    rightb = np.array([])
    center = []
    center_1andex = []
    center_y = []
    left_jump_point = 0
    right_jump_point = 0
    crossroads_count = 0
    point_of_inflectionleft_down_x = 0
    point_of_inflectionleft_down_y = 0
    point_of_inflectionleft_up_x = 0
    point_of_inflectionleft_up_y = 0
    point_of_inflectionright_down_x = 0
    point_of_inflectionright_down_y = 0
    point_of_inflectionright_up_x = 0
    point_of_inflectionright_up_y = 0
    left_up = left_down = right_up = right_down = 0
    left_down1 = left_up1 = right_down1 = right_up1 = ()
    count = flag = 0
    for high_count in range(480, 0, -1):
        # 扫左线
        for width_count_left in range(321, 0, -1):
            if mask[high_count - 1][width_count_left] != mask[high_count - 1][width_count_left - 1]:  # 跳点
                left = np.append(left, width_count_left)
                leftb = np.append(leftb, width_count_left)
                left_jump_point = width_count_left
                count_left = 1

                break
            elif (width_count_left == 1):

                lost_point_left = 0
                count_left = 0
                # count+=1
                left = np.append(left, lost_point_left)
                leftb = np.append(leftb, lost_point_left)
        # 扫右线
        for width_count_right in range(322, 639, 1):
            if mask[high_count - 1][width_count_right] != mask[high_count - 1][width_count_right + 1]:  # 跳点
                right = np.append(right, width_count_right)
                rightb = np.append(rightb, width_count_right)
                right_jump_point = width_count_right
                count_right = 1
                break
            elif (width_count_right == 638):
                lost_point_right = 639
                count_right = 0
                # count+=1
                right = np.append(right, lost_point_right)
                rightb = np.append(rightb, lost_point_right)

        if count_left == count_right == 1:
            center_point_x = left_jump_point + (right_jump_point - left_jump_point) / 2
            center_point_y = high_count
        elif count_left == count_right == 0:
            count += 1
            pass


        elif count_left == 1 and count_right == 0:
            center_point_x = left_jump_point + (lost_point_right - left_jump_point) / 2
            center_point_y = high_count
        elif count_left == 0 and count_right == 1:
            center_point_x = lost_point_left + (right_jump_point - lost_point_left) / 2
            center_point_y = high_count

        center.append([center_point_x, center_point_y])

        center_1andex.append([1, center_point_x])

        center_y.append(center_point_y)
     for i in range(len(center)):

            if center[i][1] >= 240:

                if abs(int(center[i][0]) - int(center[i - 1][0])) > 50:
                    pass
                else:
                    center[i][0] = center[i][0] - (int(center[i][0]) - int(center[i - 1][0])) / 1.1
                    cv2.circle(mask, (int(center[i][0]), int(center[i][1])), 1, (255, 0, 255), thickness=3)
            cv2.imshow('hsv+opencv', mask)
            if center[i][1] == 240:
                if center[i][0] < 300:
                    print("turn left")
                    angle = abs(300 - center[i][0]) / 320
                    print(angle)
                elif center[i][0] > 340:
                    print("turn right")
                    angle = abs(340 - center[i][0]) / 320
                    print(angle)
                else:
                    print("go straight")

十字路口补线:

    for i in range(len(left) - 10):
        if (left[i] == 0 and left[i + 3] == 0 and left[i + 5] > 0 and left[i + 10] > 0):
            left_up = 1
            left_up1 = (i + min(len(left[i + 2:]), sm), left[i + min(len(left[i + 2:]), sm)])  # 480 - i-sm
        if (left[i] > 0 and left[i + 3] > 0 and left[i + 5] == 0 and left[i + 10] == 0):
            left_down = 1
            left_down1 = (i - min(i, sm), left[i - min(i, sm)])  # 480 - i+sm
        if (right[i] == 639 and right[i + 3] == 639 and right[i + 5] < 639 and right[i + 10] <= 639):
            right_up = 1
            right_up1 = (i + min(len(left[i + 2:]), sm), right[i + min(len(left[i + 2:]), sm)])
        if (right[i] < 639 and right[i + 3] < 639 and right[i + 5] == 639 and right[i + 10] == 639):
            right_down = 1
            right_down1 = (i - min(i, sm), right[i - min(i, sm)])
    if (left_up and not left_down):
        left_down1 = (0, left_up1[1])
    elif (not left_up and left_down):
        left_up1 = (479, left_down1[1])
    if (right_up and not right_down):
        right_down1 = (0, right_up1[1])
    elif (not right_up and right_down):
        right_up1 = (479, right_down1[1])
    if (left_up or right_up) or (left_down or right_down):
        for k in range(len(leftb)):
            if len(left_down1) > 0 and len(left_up1) > 0 and len(right_down1) > 0 and len(right_up1) > 0:
                if (k >= left_down1[0] and k <= left_up1[0]) or (k <= left_down1[0] and k >= left_up1[0]):
                    leftb[k] = ((left_up1[1] - left_down1[1]) / (left_up1[0] -
                                                                 left_down1[0])) * (k - left_up1[0]) + left_up1[1]
                if (k >= right_down1[0] and k <= right_up1[0]) or (k <= right_down1[0] and k >= right_up1[0]):
                    rightb[k] = ((right_up1[1] - right_down1[1]) / (right_up1[0] -
                                                                    right_down1[0])) * (k - right_up1[0]) + right_up1[1]
    for k in range(340, -1, -1):
        point3 = (int(leftb[k]), 479 - k)  # 中
        point1 = (int(rightb[k]), 479 - k)  # 右
        x = int((int(rightb[k]) - int(leftb[k])) / 2) + int(leftb[k])
        x_1 = int((int(rightb[k + 1]) - int(leftb[k + 1])) / 2) + int(leftb[k + 1])
        point2 = (x, 479 - k)
        if count > 200:
            print(count)
            flag = 1
            cv2.circle(mask, point2, 1, (0, 0, 250), 3)
            cv2.circle(mask, point3, 1, (255, 255, 0), 0)
            cv2.circle(mask, point1, 1, (255, 0, 0), 0)
            cv2.imshow("hsv+opencv", mask)
            if k == 240:
                if x < 300:
                    print("turn left")
                    angle = abs(300 - x) / 200
                    print(angle)
                elif x > 340:
                    print("turn right")
                    angle = abs(340 - x) / 200
                    print(angle)
                else:
                    print("go straight")

缺点:

        由于阈值设置问题,如果count阈值太大会导致十字路口跳线太慢,但阈值太小会在其他情况下蹦出一堆杂线(下图就是由于hsv提取阈值小导致失线,本来运用在十字路口的补线策略乱入)

        找阈值就交给别人了哈哈

 注意事项:

hsv提取阈值尽量多试,在其他场地因素影响的情况下别忘了视觉补救工具:抹布

物联沃分享整理
物联沃-IOTWORD物联网 » 基于OpenCV的高效巡线方案解析

发表评论