[Python] 纯文本查看 复制代码
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[0]
# 适合 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[0]
y_intercept = parameters[1]
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[0] + int((right_line[0] - left_line[0]) / 2)
miny1 = right_line[1]
minx2 = left_line[2] + int((right_line[2] - left_line[2]) / 2)
miny2 = right_line[3]
mid_line_tmp = [
minx1,
miny1,
minx2,
miny2]
# 左边缘线中点坐标
left_line_minPX = int((left_line[0] + left_line[2]) / 2)
left_line_minPY = int((left_line[1] + left_line[3]) / 2)
# 右边缘线中点坐标
right_line_minPX = int((right_line[0] + right_line[2]) / 2)
right_line_minPY = int((right_line[1] + right_line[3]) / 2)
# 左右边缘线中点辅助线
left_line_minP = np.array([left_line_minPX, left_line_minPY + 20, left_line_minPX, left_line_minPY - 20])
right_line_minP = np.array([right_line_minPX, right_line_minPY + 20, right_line_minPX, right_line_minPY - 20])
# 左右边缘线中点连接辅助线
connect_left_line_minP_right_line_minP = np.array(
[left_line_minPX, left_line_minPY, right_line_minPX, right_line_minPY])
# 左右边缘线中点连接辅助线中点
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(
[min_linePX1, min_linePY1 + 10, min_linePX1, min_linePY1 - 10])
# 车道线数组
lane_line = np.array([left_line, right_line])
isHave, point = cross_point(left_line, right_line)
# 相对于中心的偏移
deviationX = min_linePX1 - int(point[0])
connect_deviation = np.array([min_linePX1, min_linePY1, min_linePX1 + deviationX, min_linePY1])
# 方向纠正提示
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(
[min_linePX1 + deviationX, min_linePY1 + 10, min_linePX1 + deviationX, min_linePY1 - 10])
# 偏移线数组
deviations = np.array([deviation_line, connect_left_line_minP_right_line_minP_min, connect_deviation])
# mid_line_tmp,
# 复制线数组
guide = np.array([left_line_minP, right_line_minP, connect_left_line_minP_right_line_minP])
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([x1, y1, x2, y2])
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([[[x1, y1], [x2, y2], [last[2], last[3]], [last[0], last[1]]]], dtype=np.int32)
cv.fillPoly(lines_visualize, b, (225, 0, 20))
last = [x1, y1, x2, y2]
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 [x, y] 交点
"""
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, [x, y]
# 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()