删除临时代码运行文件,更新横向赛道边缘检测功能,改进斜率计算方法,增强可视化效果,添加交点计算的可视化内容。

This commit is contained in:
Havoc 2025-05-14 13:32:07 +08:00
parent 16a7ccd101
commit 04613d685d
3 changed files with 130 additions and 5 deletions

BIN
res/path/test/edge_img.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -1 +0,0 @@
True

View File

@ -2,6 +2,7 @@ import cv2
import numpy as np
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn import linear_model
def preprocess_image(image):
"""
@ -558,14 +559,14 @@ def estimate_distance_to_track(image):
return distance, path_info["track_angle"], target_line_info
def detect_horizontal_track_edge(image, observe=False, delay=1500):
def detect_horizontal_track_edge(image, observe=False, delay=1000):
"""
检测正前方横向黄色赛道的边缘并返回y值最大的边缘点
参数:
image: 输入图像可以是文件路径或者已加载的图像数组
observe: 是否输出中间状态信息和可视化结果默认为False
delay: 展示每个步骤的等待时间(毫秒)默认为1500ms
delay: 展示每个步骤的等待时间(毫秒)
返回:
edge_point: 赛道前方边缘点的坐标 (x, y)
@ -828,8 +829,111 @@ def detect_horizontal_track_edge(image, observe=False, delay=1500):
# 计算这个点到中线的距离
distance_to_center = bottom_edge_point[0] - center_x
# 使用选定组的斜率
slope = selected_slope
# 改进斜率计算使用BFS找到同一条边缘线上的更多点
def get_better_slope(start_point, points, max_distance=20):
"""使用BFS算法寻找同一条边缘线上的点并计算更准确的斜率"""
queue = [start_point]
visited = {start_point}
line_points = [start_point]
# BFS搜索相连的点
while queue and len(line_points) < 200: # 增加最大点数
current = queue.pop(0)
cx, cy = current
# 对所有未访问点计算距离
for point in points:
if point in visited:
continue
px, py = point
# 计算欧氏距离
dist = np.sqrt((px - cx) ** 2 + (py - cy) ** 2)
# 如果距离在阈值内,认为是同一条线上的点
# 降低距离阈值,使连接更精确
if dist < max_distance:
queue.append(point)
visited.add(point)
line_points.append(point)
# 如果找到足够多的点,计算斜率
if len(line_points) >= 5: # 至少需要更多点来拟合
x_coords = np.array([p[0] for p in line_points])
y_coords = np.array([p[1] for p in line_points])
# 使用RANSAC算法拟合直线更加鲁棒
# 尝试使用RANSAC进行更鲁棒的拟合
try:
# 创建RANSAC对象
ransac = linear_model.RANSACRegressor()
X = x_coords.reshape(-1, 1)
# 拟合模型
ransac.fit(X, y_coords)
new_slope = ransac.estimator_.coef_[0]
# 获取内点(符合模型的点)
inlier_mask = ransac.inlier_mask_
inlier_points = [line_points[i] for i in range(len(line_points)) if inlier_mask[i]]
# 至少需要3个内点
if len(inlier_points) >= 3:
return new_slope, inlier_points
except:
# 如果RANSAC失败回退到普通拟合
pass
# 标准拟合方法作为后备
if np.std(x_coords) > 0:
new_slope, _ = np.polyfit(x_coords, y_coords, 1)
return new_slope, line_points
return selected_slope, line_points
# 尝试获取更准确的斜率
improved_slope, better_line_points = get_better_slope(bottom_edge_point, selected_group)
# 使用改进后的斜率
slope = improved_slope
if observe:
improved_slope_img = img.copy()
# 画出底部边缘点
cv2.circle(improved_slope_img, bottom_edge_point, 10, (0, 0, 255), -1)
# 画出改进后找到的所有点
for point in better_line_points:
cv2.circle(improved_slope_img, point, 3, (255, 255, 0), -1)
# 使用改进后的斜率画线
line_length = 300
# 确保线条经过边缘点
mid_x = bottom_edge_point[0]
mid_y = bottom_edge_point[1]
# 计算线条起点和终点
end_x = mid_x + line_length
end_y = int(mid_y + improved_slope * line_length)
start_x = mid_x - line_length
start_y = int(mid_y - improved_slope * line_length)
# 绘制线条
cv2.line(improved_slope_img, (start_x, start_y), (end_x, end_y), (0, 255, 0), 2)
# 添加文本显示信息
cv2.putText(improved_slope_img, f"原始斜率: {selected_slope:.4f}", (10, 150),
cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
cv2.putText(improved_slope_img, f"改进斜率: {improved_slope:.4f}", (10, 190),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2)
cv2.putText(improved_slope_img, f"找到点数: {len(better_line_points)}", (10, 230),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 255), 2)
# 显示所有原始点和改进算法选择的点之间的比较
cv2.putText(improved_slope_img, f"原始点数: {len(selected_group)}", (10, 270),
cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
cv2.imshow("改进的斜率计算", improved_slope_img)
cv2.waitKey(delay)
# 计算中线与检测到的横向线的交点
# 横向线方程: y = slope * (x - edge_x) + edge_y
@ -877,6 +981,7 @@ def detect_horizontal_track_edge(image, observe=False, delay=1500):
cv2.putText(slope_img, f"中线交点: ({intersection_point[0]}, {intersection_point[1]})", (10, 150),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.imshow("边缘斜率和中线交点", slope_img)
cv2.imwrite("res/path/test/edge_img.png", slope_img)
cv2.waitKey(delay)
# 创建边缘信息字典
@ -976,6 +1081,27 @@ def visualize_horizontal_track_edge(image, save_path=None, observe=False, delay=
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
cv2.putText(output, f"中线交点: ({intersection_point[0]}, {intersection_point[1]})", (10, 210),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
# 绘制交点计算的可视化内容
# 用线条显示边缘点到中线的连接(交点计算的辅助线)
cv2.line(output, edge_point, (center_x, edge_point[1]), (255, 153, 51), 2)
# 在边缘点处标注其y值
cv2.putText(output, f"y={edge_point[1]}", (edge_point[0] + 10, edge_point[1] - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 153, 51), 2)
# 在交点处标注其坐标
cv2.putText(output, f"({intersection_point[0]}, {intersection_point[1]})",
(intersection_point[0] + 10, intersection_point[1] - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 255), 2)
# 用箭头显示从边缘点到交点的路径(表示计算过程)
cv2.arrowedLine(output, edge_point, intersection_point, (102, 204, 255), 2)
# 添加交点计算的方程说明
equation_text = f"y = {selected_slope:.2f} * (x - {edge_point[0]}) + {edge_point[1]}"
cv2.putText(output, equation_text, (10, 240),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (102, 204, 255), 2)
else:
# 如果没有检测到,添加提示
cv2.putText(output, "未检测到横向赛道", (width//4, height//2),