You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
3.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import math
import cameramodel
import calc_way
from scipy import stats
def get_k(
cameraModel,
x: float,
y: float,
calc_distance_func # 传入计算距离的函数
) -> float:
"""计算斜率参数 k。
参数:
cameraModel: 包含相机参数的类实例,需有以下属性:
rotation_alpha, rotation_beta: 旋转角度
x, y: 像素坐标
calc_distance_func: 计算距离的函数,需返回 (Xw, Yw)
返回:
斜率参数 k
"""
# 1. 预计算常用三角函数值
tan_alpha = math.tan(cameraModel.rotation_alpha)
tan_beta = math.tan(cameraModel.rotation_beta)
# 2. 计算 gamma 和 seta 角度
gamma = math.atan2(1, tan_alpha * tan_beta) # 使用 atan2 提高稳定性
seta = math.atan2(1, math.sqrt(tan_beta ** 2 + 1 / tan_alpha ** 2))
# 3. 计算世界坐标
Xw, Yw = calc_distance_func(cameraModel, x, y)
# 4. 坐标旋转
cos_gamma = math.cos(gamma)
sin_gamma = math.sin(gamma)
u = Xw * cos_gamma - Yw * sin_gamma
v = Xw * sin_gamma + Yw * cos_gamma
# 5. 处理u=0的边界情况
if math.isclose(u, 0, abs_tol=1e-10):
return float('inf') # 垂直线斜率为无穷大
# 6. 计算 lambda 角度
tan_seta_complement = math.tan(math.pi / 2 - seta)
denominator = u * math.sqrt(1 + tan_seta_complement ** 2)
tan_lambda = -v / denominator
lambda_angle = math.atan(tan_lambda)
# 7. 计算斜率 k
k = math.tan(math.pi / 2 - lambda_angle)
return k
def get_k2(
cameraModel,
Xw: float,
Yw: float
) -> float:
"""计算从世界坐标(Xw,Yw)到斜率k的转换。
参数:
cameraModel: 包含相机参数的类实例,需有以下属性:
rotation_alpha, rotation_beta: 旋转角度
Xw, Yw: 世界坐标系下的坐标
返回:
斜率参数k
"""
# 1. 预计算常用三角函数值
tan_alpha = math.tan(cameraModel.rotation_alpha)
tan_beta = math.tan(cameraModel.rotation_beta)
# 2. 计算gamma和seta角度使用更稳定的atan2
gamma = math.atan2(1, tan_alpha * tan_beta) # 避免除零错误
seta = math.atan2(1, math.sqrt(tan_beta ** 2 + 1 / tan_alpha ** 2))
# 3. 坐标旋转预计算sin/cos
cos_gamma = math.cos(gamma)
sin_gamma = math.sin(gamma)
u = Xw * cos_gamma - Yw * sin_gamma
v = Xw * sin_gamma + Yw * cos_gamma
# 4. 处理u=0的边界情况
if math.isclose(u, 0, abs_tol=1e-10):
return float('inf') # 垂直线斜率为无穷大
# 5. 计算lambda角度更稳定的表达式
tan_seta_complement = math.tan(math.pi / 2 - seta)
denominator = u * math.sqrt(1 + tan_seta_complement ** 2)
tan_lambda = -v / denominator
lambda_angle = math.atan(tan_lambda)
# 6. 计算最终斜率k
k = math.tan(math.pi / 2 - lambda_angle)
return k
"""
计算地面点的竖直垂线在图像中的截距
参数点在图像中的坐标x、y斜率k
返回值截距b
"""
def get_b(x,y,k):
b = y - x * k
return b
"""
将检测到的路沿上侧数据点拟合为一条直线
参数上侧数据点坐标x_top,y_top
返回值拟合出直线的斜率slope、截距intercept、r方值
"""
def linear_regression(x, y):
slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
return slope, intercept, abs(r_value)
"""
计算图像中两条直线的交点
参数: line1: 第一条直线的系数 (A1, B1, C1)
line2: 第二条直线的系数 (A2, B2, C2)
返回值交点在图像中的二维坐标x、y
"""
def find_intersection(line1, line2):
A1, B1, C1 = line1
A2, B2, C2 = line2
# 计算行列式
denominator = A1 * B2 - A2 * B1
if denominator == 0:
# 直线平行或重合
return None
else:
x = (B1 * C2 - B2 * C1) / denominator
y = (A2 * C1 - A1 * C2) / denominator
return (x, y)