面灵AI→

智驾新程定位算法:相机标定公式与 RANSAC

时间
2026-10
来源
牛客网

《面试题目》

  1. 自我介绍。
  2. 项目盘问。
  3. 八股:C++ 智能指针相关问题。
  4. 八股:ROS2 相关问题。
  5. 标定内参、外参的求解公式是什么?
  6. 手撕:用 RANSAC 拟合直线(非力扣题)。

《参考解析》

内参标定要能推出公式,而不是只说「用张正友标定法」。 相机模型分两步:世界点经外参 [R|t] 变到相机坐标,再由内参矩阵 K = [[fx,0,cx],[0,fy,cy],[0,0,1]] 投影到像素,畸变再补径向系数 k1,k2,k3 与切向系数 p1,p2。平面靶标法的推导链条是:同一个平面上的点满足 s·m = K[r1 r2 t]·M(把靶标平面设为 Z=0,所以外参只剩两列),于是像素与靶标坐标之间是一个单应矩阵 H = K[r1 r2 t];H 可以从四对以上对应点用 DLT 线性解出来,再由 r1 与 r2 正交且等长(r1ᵀr2 = 0、r1ᵀr1 = r2ᵀr2)建立两个约束,每张图贡献两个方程,三张以上不同姿态就能线性解出 B = K⁻ᵀK⁻¹,再从中反解出 fx, fy, cx, cy 与倾斜因子;拿到初值后用 LM 做非线性最小化,目标函数是所有角点的重投影误差平方和,同时把畸变系数一起优化。要主动提几个实践要点:靶标姿态要覆盖图像四角与不同倾角(否则参数耦合、外推误差大)、用重投影 RMS 与不确定性(协方差)评估标定质量、大畸变镜头用鱼眼或多项式模型、标定板平整度与拍摄模糊是常见误差源。

外参标定按「已知靶标」和「无靶标」两条路讲。 已知靶标时,从靶标求解相机位姿用 PnP(3D-2D 对应,EPnP 给初值 + LM 精修),两个传感器之间的外参就是两次位姿的组合,本质是可写成 AX = XB 的手眼标定形式,先解旋转(R_A R_X = R_X R_B,用四元数或 SVD 取最小二乘解)再解平移;无靶标时靠运动与静止特征,用点云配准(ICP/NDT)或路面、车道线等自然特征做配准,代价是需要充分的运动激励(多轴向旋转与平移)才能让参数可观。还要讲清常见追问:时间同步与延迟标定(时延会让外参在高速运动下失真)、标定结果如何在线验证(重投影、点云重影、里程计一致性)、以及参数漂移后的在线更新策略。

RANSAC 拟合直线,要写得出流程也算得清参数。 流程是:随机取最少样本(直线取 2 点)拟合模型 → 计算所有点到直线的距离 → 距离小于阈值的记为内点 → 记录内点最多的模型 → 重复 N 次 → 用最终内点集做最小二乘精修(随机采样只用来筛外点,求精度还是靠全部内点)。迭代次数由公式给出:N = log(1 − p) / log(1 − w^s),其中 p 是期望成功概率(常取 0.99)、w 是内点率、s 是最少样本数,内点率低时 N 会迅速变大,所以可以自适应更新——每次发现更好的模型就用新的内点率重算 N。距离阈值一般按测量噪声的尺度取(如 2σ),取太小会把内点判成外点、太大则外点混入。退化与坑要主动提:随机取到两个几乎重合的点会得到数值不稳定的直线(要检查点间距离下限);点云近似一条线但含大量离群点时最小二乘精修仍会被拉偏,可以改用加权或多次 RANSAC + 一致性检验;另外要说明 RANSAC 只能给「最一致的模型」而不保证是「正确的模型」,在结构重复的场景(多条平行线)要结合先验或方向约束。

C++ 智能指针按「所有权模型 + 使用边界」回答。 unique_ptr 表达独占所有权,不可拷贝只能移动,零开销、无法共享;shared_ptr 用控制块里的强引用计数共享所有权,拷贝有原子操作开销,循环引用会导致永不释放,这时要用 weak_ptr 打破环(weak_ptr 不增加强计数,用 lock() 提升并判空);make_shared 一次分配把对象和控制块放一起,效率和异常安全更好,但会让对象内存在最后一个 weak_ptr 消失前都不能回收,且无法给对象单独指定删除器。要讲清几个常被追问的点:enable_shared_from_this 为什么必要(对象内部拿 this 造 shared_ptr 会生成第二个控制块,导致重复析构);引用计数的线程安全边界(计数增减是原子的,但所指对象的读写不是);shared_ptr 传参尽量传引用以免无谓的计数操作;以及 unique_ptr 的自定义删除器适合封装 C 风格资源。

ROS2 的追问一般落在通信与执行模型上。 话题/服务/动作三种通信方式要能说清取舍:话题是单向异步、适合高频数据流(点云、图像、里程计),服务是同步请求响应、适合短小的查询与配置,动作带目标与反馈、适合长时间任务(导航到点);底层是 DDS,QoS 策略(reliability 可靠还是尽力而为、durability 是否给晚加入的节点补数据、history 与 depth、deadline)直接决定「为什么我的消息收不到」——传感器数据常用 best effort 降延迟,控制指令用 reliable;执行器与回调组决定回调在哪条线程上跑,长耗时的回调要放到独立回调组或单独执行器,否则会阻塞整个节点;组件化(component container)把多个节点放进同一进程做零拷贝,是性能优化的常用手段;再加一句生命周期节点(configure → activate)让启动顺序可控。答的时候最好把「你自己项目里怎么配的 QoS、踩过什么坑」带上,比背概念有说服力。