自动驾驶车道检测中如何记录前3帧的均值斜率与截距
实现前3帧车道参数的存储与校验修正
我来帮你搞定保存前3帧左右侧均值斜率和截距的需求,这样就能用历史数据来校验当前帧的参数,减少检测误差啦。下面是具体的实现思路和修改后的代码:
核心思路
- 用
collections.deque创建固定长度的队列,专门存储每帧的左右侧斜率、截距数据,队列长度设为3,满了之后自动移除最旧的帧数据。 - 每帧计算完当前的均值斜率和截距后,把有效数据(非None的情况)加入队列。
- 当队列积累了足够数据(至少3帧),可以通过历史数据的均值来校验当前帧的参数,比如如果当前帧的斜率和历史均值偏差超过阈值,就用历史值或者加权平均来修正。
修改后的完整代码
import numpy as np import cv2 import math from collections import deque cap = cv2.VideoCapture('video3.mov') # 初始化存储前3帧数据的队列,每个元素是(left_slope, left_intercept, right_slope, right_intercept) history_queue = deque(maxlen=3) while (cap.isOpened()): ret, frame = cap.read() if not ret: break # 处理视频结束的情况 hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HLS) # HSL color mask lower_white = np.uint8([0, 140, 0]) upper_white = np.uint8([255, 255, 255]) mask = cv2.inRange(hsv, lower_white, upper_white) res = cv2.bitwise_and(frame, frame, mask=mask) height = np.size(hsv, 0) width = np.size(hsv, 1) rows, cols = hsv.shape[:2] bottom_left = [cols * 0, rows * 0.9] top_left = [cols * 0.4, rows * 0.7] bottom_right = [cols * 1, rows * 0.9] top_right = [cols * 0.6, rows * 0.7] vertices = np.array([[bottom_left, top_left, top_right, bottom_right]], dtype=np.int32) maskzero = np.zeros_like(res) cv2.fillPoly(maskzero, vertices, (255,) * maskzero.shape[2]) maskedimg = cv2.bitwise_and(res, maskzero) gaussian = cv2.GaussianBlur(maskedimg, (3, 3), 0) cannymask = cv2.Canny(gaussian, 150, 250) lines = cv2.HoughLinesP(cannymask, rho=1, theta=np.pi / 180, threshold=20, minLineLength=10, maxLineGap=300) left_slope = [] right_slope = [] left_intercept = [] right_intercept = [] total_right_length = [] total_left_length = [] if lines is not None: for line in lines: for x1, y1, x2, y2 in line: if (x2 - x1) != 0: slope = (y2 - y1) / (x2 - x1) intercept = y1 - slope * x1 length = np.sqrt((y2 - y1) ** 2 + (x2 - x1) ** 2) angle = math.atan2(y2-y1,x2-x1) degree = angle * 180 / np.pi if x2 == x1 or y2 == y1: continue elif slope > 0: if int(degree) in range (27,41): right_slope.append(slope) right_intercept.append(intercept) total_right_length.append(length) elif slope < 0: if int(degree) in range (-62,-31): left_slope.append(slope) left_intercept.append(intercept) total_left_length.append(length) # 计算当前帧的均值参数 right_mean_slope = np.mean(right_slope) if len(right_slope) > 0 else None right_mean_intercept = np.mean(right_intercept) if len(right_intercept) > 0 else None left_mean_slope = np.mean(left_slope) if len(left_slope) > 0 else None left_mean_intercept = np.mean(left_intercept) if len(left_intercept) > 0 else None # 将当前帧的有效参数加入历史队列(只存非None的,或者可以用占位符,这里选存实际有效数据) current_frame_data = (left_mean_slope, left_mean_intercept, right_mean_slope, right_mean_intercept) history_queue.append(current_frame_data) # --- 这里是校验修正逻辑,你可以根据需求调整 --- # 当队列有至少3帧数据时,计算历史均值来修正当前帧参数 corrected_left_slope = left_mean_slope corrected_left_intercept = left_mean_intercept corrected_right_slope = right_mean_slope corrected_right_intercept = right_mean_intercept if len(history_queue) >= 3: # 提取历史中的有效左侧斜率和截距 hist_left_slopes = [data[0] for data in history_queue if data[0] is not None] hist_left_intercepts = [data[1] for data in history_queue if data[1] is not None] # 提取历史中的有效右侧斜率和截距 hist_right_slopes = [data[2] for data in history_queue if data[2] is not None] hist_right_intercepts = [data[3] for data in history_queue if data[3] is not None] # 计算历史均值 hist_left_slope_mean = np.mean(hist_left_slopes) if hist_left_slopes else None hist_left_intercept_mean = np.mean(hist_left_intercepts) if hist_left_intercepts else None hist_right_slope_mean = np.mean(hist_right_slopes) if hist_right_slopes else None hist_right_intercept_mean = np.mean(hist_right_intercepts) if hist_right_intercepts else None # 示例:如果当前帧参数存在,且和历史均值偏差超过阈值(比如斜率偏差0.1),则用历史均值修正 slope_threshold = 0.1 intercept_threshold = 50 if left_mean_slope is not None and hist_left_slope_mean is not None: if abs(left_mean_slope - hist_left_slope_mean) > slope_threshold: corrected_left_slope = hist_left_slope_mean corrected_left_intercept = hist_left_intercept_mean if right_mean_slope is not None and hist_right_slope_mean is not None: if abs(right_mean_slope - hist_right_slope_mean) > slope_threshold: corrected_right_slope = hist_right_slope_mean corrected_right_intercept = hist_right_intercept_mean # --- 用修正后的参数计算车道线坐标 --- y1 = frame.shape[0] # bottom of the image y2 = y1 * 0.7 right_x1, right_y1, right_x2, right_y2 = 0,0,0,0 left_x1, left_y1, left_x2, left_y2 = 0,0,0,0 if corrected_right_intercept is not None and corrected_right_slope is not None: right_x1 = int((y1 - corrected_right_intercept)/corrected_right_slope) right_x2 = int((y2 - corrected_right_intercept)/corrected_right_slope) right_y1 = int(y1) right_y2 = int(y2) if corrected_left_intercept is not None and corrected_left_slope is not None: left_x1 = int((y1 - corrected_left_intercept)/corrected_left_slope) left_x2 = int((y2 - corrected_left_intercept)/corrected_left_slope) left_y1 = int(y1) left_y2 = int(y2) cv2.line(frame, (right_x1, right_y1), (right_x2, right_y2), (0, 0, 255), 10) cv2.line(frame, (left_x1, left_y1), (left_x2, left_y2), (255, 0,0), 10) cv2.imshow("New_lines", frame) if cv2.waitKey(100) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
关键部分说明
- 历史队列初始化:用
deque(maxlen=3)创建最多存3帧数据的队列,自动维护最新的3帧数据,不用手动处理旧数据的删除。 - 数据存入队列:每帧计算完参数后,把当前帧的左右斜率、截距打包存入队列,确保历史数据的完整性。
- 校验修正逻辑:当队列满3帧时,提取历史中的有效数据计算均值,然后和当前帧参数对比。如果偏差超过设定的阈值,就用历史均值替换当前参数——你可以根据实际场景调整阈值和修正策略,比如采用加权平均(当前帧权重更高)来平衡实时性和稳定性。
- 使用修正后参数绘制车道线:最后用修正后的斜率和截距计算车道线坐标,这样就能得到更平滑、稳定的车道检测结果。
内容的提问来源于stack exchange,提问作者SSR
相关产品推荐
相关产品推荐

