目录
背景
在参加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提取阈值尽量多试,在其他场地因素影响的情况下别忘了视觉补救工具:抹布
文章出处登录后可见!
已经登录?立即刷新