LingBot-Depth 2.0 在外参标定完成后,深度输出的可信范围仍然需要通过真实样本验证。这里给出一套可执行的边界确认流程:采集不同距离和光照条件下的真实场景数据,用激光测距仪记录真值,对比模型输出的深度图,按距离和光照分组统计误差,最后用预设误差阈值划定可靠工作范围。这套流程可以被固化为脚本,便于标定参数更新或模型调整后重复执行。
判断方向:外参标定后模型输出仍需要用真值样本做误差统计来确定可靠边界。操作动作:采集1m、2m、3m等距离和强光、暗光场景的配对数据;调用模型得到深度图;用激光测距仪记录真实距离;计算MAE、RMSE和分组标准差;以误差>5%作为弃用阈值画出误差-距离折线。验证方式:将流程写成自动化脚本,每次标定后重跑生成边界报告。风险边界:阈值需要结合具体应用调整,光照和物体表面材质会影响深度质量,单次采样不能代表所有环境条件。
设计标定后验证场景与样本采集
验证场景需要覆盖模型实际使用时可能遇到的输入条件。距离档位选取1m、2m、3m、5m,光照条件分成强光、正常光、暗光三档。若相机标称的最小或最大测距范围与这些档位差距较大,则在范围边界外各增加一个距离点。目标物体建议使用平面墙体或标准漫反射板,避免镜面反射和透明材质。
每个距离×光照组合建议采集20-50张图像,同时用激光测距仪记录真实距离。采集时让相机在目标距离附近小幅移动,覆盖画面中心和边缘区域,因为外参标定误差在边缘位置通常会放大。所有图像按“距离_光照_序号.jpg”命名,便于后续分组处理。
调用模型输出深度图并记录真值
得到验证图片后,需要将每张图片传入深度模型,并保存预测的深度图。以下代码给出通用接入骨架,实际模型加载与推理方法需要按所用SDK替换。
import cv2
import numpy as np
import json
# 实际使用时替换为LingBot-Depth 2.0的模型加载与推理接口
model = load_lingbot_depth_model()
def predict_depth(image_path):
img = cv2.imread(image_path)
depth_map = model.infer(img) # 返回浮点型深度图,单位米
return depth_map
# 真值记录结构
records = [
{
'name': '1m_normal_001.jpg',
'group': '1m_normal',
'truth': 1.02, # 激光测距仪读数
'pred': 0.95, # 从深度图对应位置提取的预测值
'depth_map_path': 'output/1m_normal_001.npy'
},
# ...
]
# 保存预测深度图
depth = predict_depth('captures/1m_normal_001.jpg')
np.save('output/1m_normal_001.npy', depth)
在记录真值时,需要确定深度图中的哪个位置对应激光测距仪的测量点。通常取图像中心区域一个固定大小的窗口平均值,或者用外参标定得到的坐标映射关系计算对应像素。真值数据统一保存为CSV文件,便于后续脚本读取。
计算深度误差与标准差
用统计量量化预测值与真值的偏差。以下脚本读取上一步生成的记录,计算整体MAE、RMSE和每个距离分组的误差标准差。
import pandas as pd
import numpy as np
# records来自上一步,也可以从CSV加载
df = pd.DataFrame(records)
df['error'] = df['pred'] - df['truth']
df['abs_error'] = np.abs(df['error'])
mae = df['abs_error'].mean()
rmse = np.sqrt((df['error'] ** 2).mean())
print(f'MAE: {mae:.3f} m, RMSE: {rmse:.3f} m')
# 按分组统计标准差和平均绝对误差
grouped = df.groupby('group')['error'].agg(['mean', 'std', 'count'])
grouped['MAE'] = df.groupby('group')['abs_error'].mean()
print(grouped.round(4))
标准差能反映深度输出在同一个条件下的稳定性。如果某个距离分组的std-dev明显高于其他组,说明该距离处预测值波动大,即便平均误差接近阈值也应谨慎处理。
根据误差阈值标定可靠边界
设定一个应用允许的最大误差阈值,例如相对真值误差大于5%则视为不可用。绘制误差-距离折线图,找出各个距离分组的平均绝对百分误差超过阈值的点,并据此划出可靠边界。
import matplotlib.pyplot as plt
df['abs_percent_error'] = df['abs_error'] / df['truth']
dist_groups = sorted(df['group'].unique())
mean_ape = df.groupby('group')['abs_percent_error'].mean().reindex(dist_groups)
threshold = 0.05
reliable_groups = mean_ape[mean_ape <= threshold].index.tolist()
plt.figure(figsize=(8, 5))
plt.plot(range(len(dist_groups)), mean_ape.values, 'o-')
plt.axhline(y=threshold, color='r', linestyle='--', label=f'Threshold {threshold:.0%}')
plt.xticks(range(len(dist_groups)), dist_groups, rotation=45)
plt.ylabel('Mean Absolute Percentage Error')
plt.xlabel('Distance Group')
plt.title('Depth Reliability Boundary')
plt.legend()
plt.tight_layout()
plt.savefig('reliability_boundary.png')
图中被虚线穿越的组就是可靠与不可靠的分界点。最大可靠距离通常是所有误差不超过阈值的距离组中最大的那个。如果1m、2m、3m稳定,5m出现超过5%误差,则可靠边界可标定为“在测试光照条件下最大可靠距离约3m”。实际应用中的阈值不一定是5%,需要结合具体任务对深度精度的容错要求来确定。
将验证流程固化为自动化脚本
把上述步骤封装成一个入口函数,输入图像文件夹和真值表,输出边界报告。这样每次外参重新标定或模型更新后,都能用同一套测试数据快速回归。
import os
import pandas as pd
def validate_boundary(image_folder, groundtruth_csv, output_dir='boundary_report'):
os.makedirs(output_dir, exist_ok=True)
gt = pd.read_csv(groundtruth_csv)
records = []
for _, row in gt.iterrows():
image_path = os.path.join(image_folder, row['image'])
depth_map = predict_depth(image_path)
# 从深度图中心区域提取预测距离
h, w = depth_map.shape[:2]
crop = depth_map[h//2-10:h//2+10, w//2-10:w//2+10]
pred = np.nanmean(crop)
records.append({
'name': row['image'],
'group': row['group'],
'truth': row['truth_m'],
'pred': pred
})
df = pd.DataFrame(records)
df['error'] = df['pred'] - df['truth']
df['abs_error'] = df['error'].abs()
df['abs_percent_error'] = df['abs_error'] / df['truth']
# 汇总统计
grouped = df.groupby('group')['error'].agg(['mean', 'std', 'count'])
grouped['MAE'] = df.groupby('group')['abs_error'].mean()
grouped['MAPE'] = df.groupby('group')['abs_percent_error'].mean()
grouped.to_csv(os.path.join(output_dir, 'group_stats.csv'))
# 判断可靠边界
reliable = grouped[grouped['MAPE'] <= 0.05].index.tolist()
with open(os.path.join(output_dir, 'boundary_summary.txt'), 'w') as f:
f.write(f'Reliable groups: {reliable}\n')
f.write('Boundary report generated.\n')
return os.path.join(output_dir, 'boundary_summary.txt')
# 调用示例
# report = validate_boundary('./captures', './truths.csv')
脚本需要将预测深度图临时保存的步骤删去或改为可选,避免重复IO。边界报告只输出分组统计和可靠组列表,实际使用时可以再扩展为生成折线图。这里采用的5%阈值是示例,请根据项目需求修改为对应的误差容忍度,并保留阈值参数。