[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:18 编辑
hj170520 发表于 2021-7-9 15:40
请问这需要训练模型吗?
不需要 这个只是识别指定区域里的实线 总之挺拉胯的 但是之前看了一个大佬的语义分割的视频 可以尝试做一下语义分割 把车道线 车辆 行车标志分割出来 还是苦于数学基础不过关 哎 太强了,老哥厉害啊 看起来还不错,下载试一试。感谢楼主分享!
先膜拜再学习 可以可以,好久没用OpenCV了 插眼,下学期我们也要搞这个 D盘的视频提供一下可以吗{:301_999:} 请问这需要训练模型吗?{:301_984:} 自动驾驶? KevINBy 发表于 2021-7-9 16:00
自动驾驶?
不是 车道线识别而已 高级东西做不出来
页:
[1]
2