首页 / 资讯中心 / 文章详情

鸟瞰图与逆透视映射:MATLAB实现原理、单应性矩阵与避坑指南

鸟瞰图与逆透视映射:MATLAB实现原理、单应性矩阵与避坑指南 ★ FEATURED ARTICLE
做视觉感知的同学应该都遇到过这种场景拿到一张前视相机图像道路明明是直的但画面里两条车道线却在远处汇聚成一个点近处的车和远处的车在图像里的宽度差异极大这时候想直接量出前车距离、判断自车是否压线十个人里有九个会被透视投影整得头疼。把图像转成鸟瞰视角也就是 BirdView这个问题会直观很多。所谓鸟瞰图本质是把相机拍摄的透视图重新投影到与地面平行的平面相当于把视角从“人眼平视”切换成“无人机垂直俯视”在自动驾驶、车道线检测、停车辅助这些场景里几乎是标配操作。这篇文章就想把 BirdView 的原理和 MATLAB 实现讲透包括两种最常用的求解路线、完整可跑的实例代码以及我在实际项目中踩过的那些坐标顺序、尺度换算、投影方向相关的坑。无论是刚接触逆透视映射的学生还是想快速搭一个鸟瞰图 Demo 验证方案的工程师应该都能在这里找到能直接抄作业的内容。1. 为什么要做鸟瞰图先想清楚在解决什么问题1.1 相机图像天生不适合做距离感知先花点时间把“为什么需要鸟瞰图”这个问题想明白后面理解公式会顺畅很多。普通相机成像遵循透视投影模型空间中的一个点在图像上的位置由它和光心的连线与成像平面的交点决定。这个模型带来的直接后果是同样大小的物体离相机越远在图像上占据的像素越少。一条等宽的标准车道近处占了图像下半部分很宽的一块远处却缩到接近一个点这种失真本质上不是“镜头畸变”而是透视投影的几何特性畸变校正是解决不了这个问题的。透视投影对算法很不友好。举个例子原始的图像坐标系里一条车道线的左右边界方程是两条在远处相交的斜线你要拟合它、评估曲率、计算横向偏差都得处理那套恼人的交点约束。再看距离估计如果你只知道目标在图像里的像素高度想要换算成物理距离必须把相机的安装高度、俯仰角、焦距全部代入一个非线性模型任何一个标定参数有偏差远距离的估计值就会以二次方的速度发散。这些问题横在那边逼着我们换一种几何上更干净的视角。BirdView 的思路很简单假设地面是平面把图像上属于地面的那些像素重新投影到与地面平行的虚拟平面上。在这个平面里车道线是平行的物体的宽度不再随距离变化目标的物理坐标可以直接用平面上的 X、Y 表示。你在鸟瞰图里量到的横向距离就是真实世界的横向距离你拟合出来的车道线曲率也是真实的道路曲率。这相当于给算法提供了一个“尺度感”完全正确的坐标系。1.2 BirdView能做什么车道线拟合、目标定位、路径规划鸟瞰图最经典的应用是车道线检测。原始图里车道线是倾斜且收敛的换到鸟瞰图以后变成近似平行的曲线可以用三次多项式直接拟合曲率、横向偏移量一目了然。很多车道线模型在鸟瞰空间里训练和推理精度比直接在原图上处理高不少因为模型不需要额外学习透视变形。目标定位也依赖鸟瞰图。车载相机检测到前车时我们通常取检测框底边的中点作为车辆与地面的接触点把这个点从图像坐标投射到地面平面就得到前车的物理位置。有了连续帧的位置序列才能做速度估计、轨迹预测、碰撞时间计算。如果缺了这层鸟瞰变换底边中点对应的物理位置会随距离改变轨迹预测根本没法做。环视全景泊车系统更是鸟瞰图的直接产物。车辆前后左右四颗大广角相机各自把采集到的图像逆透视映射到车身周围的地面坐标系再拼接成一张完整的俯视全景图停车的时候车身四周的障碍物、车位线一目了然。另外可通行区域分析、占据栅格地图构建很多也是建立在鸟瞰或俯视坐标系上的。可以说 BirdView 是视觉感知从“看到”走向“能量化、能做决策”的那座桥。1.3 两个关键误区这个技术也不是万能药。第一个误区是觉得鸟瞰图能无损恢复所有信息。逆透视映射依赖“地面是平面”这个假设只有落在地面上的点才满足投影关系。站立的人、车辆侧面、路肩、树冠这些立体的物体投影到地面平面以后会被拉成奇怪的放射状条纹。所以鸟瞰图只负责“把地面信息摆正”涉及立体目标的语义分析还是要回到原始视角或者借助深度信息来补充。第二个误区是认为做鸟瞰图必须上深度学习。很多人一听要测距、要建图第一反应是训练一个端到端的 BEV 神经网络。其实如果相机内外参是已知的或者只需要一个离线鸟瞰图做数据标注经典的逆透视映射IPM几行 MATLAB 就搞定了不需要 GPU、不需要训练数据。神经网络方案适合在动态场景、多相机融合、遮挡严重的条件下端到端学习 BEV 特征但纯几何方案作为理解原理、快速验证的起点永远是性价比最高的那一步。2. 鸟瞰图的核心原理针孔模型、坐标变换与单应性矩阵2.1 一张图看懂的成像链路世界坐标系到像素坐标系要用代码实现鸟瞰图先得把相机成像的数学模型捋清楚。整个成像链路可以拆成三次坐标变换。第一步是世界坐标系到相机坐标系。世界坐标系是你自己定义的比如以车辆后轴中心为原点、车辆前方为 X 轴、左侧为 Y 轴、垂直地面向上为 Z 轴。相机相对这个原点有一个固定的旋转和平移用旋转矩阵 R3×3和平移向量 t3×1表示Xc R * Xw t。R 和 t 合起来叫相机外参描述了“相机在世界中的位置和朝向”。第二步是相机坐标系到图像物理坐标系。相机坐标系的原点在光心Z 轴指向拍摄方向。空间点经过针孔投影落到成像平面上物理坐标为 x f * Xc / Zcy f * Yc / Zc其中 f 是焦距。这一步把三维信息压缩成了二维信息距离信息在这一步丢失。第三步是图像物理坐标系到像素坐标系。成像平面上的物理坐标还要乘以像素的物理尺寸再加上主点偏移得到最终像素坐标。合并起来用一个内参矩阵 K 表示K [fx, 0, cx; 0, fy, cy; 0, 0, 1]其中 fx、fy 是以像素为单位的焦距cx、cy 是主点像素坐标。三条链路合在一起就是经典的针孔相机投影公式s * [u, v, 1]ᵀ K * [R | t] * [Xw, Yw, Zw, 1]ᵀ这里的 s 是缩放因子。这个公式看起来有点吓人但你只要抓住一点它把一个三维世界点映射到了二维图像像素点而我们的目标是把二维图像像素点映射回地面平面上对应的二维世界点。这正好是上述映射的逆过程只不过因为深度信息在投影时被压缩了逆过程不是单靠矩阵求逆就能完成的需要引入额外的约束也就是接着要讲的“地面假设”。2.2 地面假设与单应性矩阵的数学推导关键的一步来了。我们只关心地面上的点那就可以加一个约束所有目标点的世界坐标 Z 恒等于 0。代入刚才的投影公式[R | t] 矩阵中与 Zw 相乘的那一列根本没参与计算只有旋转矩阵的前两列 r1、r2 起作用s * [u, v, 1]ᵀ K * [r1, r2, t] * [Xw, Yw, 1]ᵀ把中间的 3×3 矩阵记为 H就得到s * [u, v, 1]ᵀ H * [Xw, Yw, 1]ᵀ这个 H 就是单应性矩阵。它直接把地面平面上的一个点映射到图像平面上的一个像素点。反过来H 的逆矩阵 H⁻¹ 就可以把图像像素点映射回地面平面。整条链路就是图像像素坐标 → H⁻¹ → 地面物理坐标这就是逆透视映射Inverse Perspective Mapping简称 IPM的数学本质。单应性矩阵 H 有 8 个自由度9 个元素除以一个缩放因子剩下 8 个独立参数所以理论上最少只要 4 对匹配点就能求解。这也是为什么后面直接选点法只需要选四个角点。但要注意单应性成立的前提是那个平面假设地面必须是平面。如果路面上有减速带、井盖突出或者车辆行驶时车身俯仰导致相机外参变化H 就不再完全准确地图上离得越远的点误差越大。理解了这一层你就能解释很多鸟瞰图边缘模糊扭曲的根源。2.3 MATLAB中projective2d的转置陷阱用 MATLAB 处理投影变换时最大的坑往往不是数学推导而是库函数的矩阵存储习惯。图像处理工具箱里的projective2d对象用一个 3×3 的矩阵 T 表示变换但文档明确写了T 是传统数学单应性矩阵 H 的转置。也就是说如果你在论文或者教科书里推导出了一个标准的 H要构建等价变换必须写tform projective2d(H);如果把 H 直接传进去变换结果往往会表现成镜像错乱或者某种诡异的仿射变形肉眼看着就是“图翻转了”或者“拉伸方向完全不对”。fitgeotrans返回的tform.T同样遵循这个转置存储规则很多人后续手动修改tform.T时把元素位置填错也会踩进去。养成一个好习惯每次构建完projective2d对象先用一个已知点验证。比如你知道地面坐标为 (10, 2) 的点经过 H 应该落在原图像素 (320, 240) 上那就用[x, y] transformPointsForward(tform, [10, 2])检查结果是否接近预期。如果偏差巨大第一件事就是去看是不是转置写反了。3. 两条路线求解鸟瞰变换直接选点法与相机内外参法3.1 直接选点法只靠四对对应点就能干活第一种求解单应性矩阵的方式完全不依赖相机标定只需要在原图和目标鸟瞰图之间找到四组对应点。实际操作里一般是在原图中的道路区域选一个四边形通常是近处宽、远处窄的梯形区域然后指定这个梯形在鸟瞰图中对应的矩形位置。比如车辆前方的道路在原图中近处两个角点偏下方两侧远处两个角点偏向画面中心靠近消失点。选点后把四个角点映射到目标鸟瞰图的矩形四角fitgeotrans内部会直接用最小二乘或直接求解法算出 3×3 的单应矩阵。用 MATLAB 写就是tform fitgeotrans(imgPts, fixedPts, projective);这里的imgPts是原图中的点fixedPts是目标鸟瞰图中的点。projective表示求解完整的 8 自由度投影变换而不是简单的仿射变换。直接选点法的优点是门槛低不需要标定相机、不需要物理尺寸几分钟就能看到效果缺点是目标鸟瞰图的尺度完全依赖你指定的坐标不够精确。比如你把横向指定成 8 米但实际道路宽度是 3.5 米那鸟瞰图里的比例就全是错的。所以它适合做快速验证、视觉效果展示、或者为后续标定工作准备训练数据不太适合用来做依赖真实物理坐标的工程任务。3.2 内外参法物理意义明确适合工程落地第二种方法是先做相机标定得到内参和外参然后直接用前面推导的公式构建单应性矩阵 H K * [r1, r2, t]。这条路线看起来步骤更多但每个参数都有明确的物理含义鸟瞰图中每个像素都能换算成真实世界的米数或厘米数这是工程落地必须的。具体来说分三步先用棋盘格标定板获取相机内参 K 和畸变系数然后在车辆前方地面放置已知尺寸的标定物估计相机相对地面坐标系的外参 R、t最后用 H K * [r1, r2, t] 构建单应矩阵求逆后配合imwarp输出鸟瞰图。这条路线输出的鸟瞰图坐标系是可以和车辆导航、里程计对齐的。比如你定义世界坐标系以车为原点那鸟瞰图上的点直接就是车辆坐标系下的物理坐标下游模块可以直接拿去规划路径。3.3 两种方案的适用场景对比两条路线不矛盾甚至经常配合使用。直接选点法产生的结果如果配合实际距离测量可以反过来估算外参我做过的一个项目就是这么干的先用选点法做外观验证再用实际测量的车道宽度反推外参效果意外地稳。把两种方法的特点排个对比对比项直接选点法内外参法所需条件原图四个对应点坐标相机内参、外参、畸变系数物理尺度不准确依赖人工指定准确像素可对应米实现难度低几分钟见效中需要标定流程相机更换后需重新选点内参变化才需重新标定适合场景快速验证、离线标注、Demo工程落地、实时系统、多相机融合工程里先做内参标定再用选点法生成的地面点来估计外参是性价比很高的组合。这样既避开了外参标定板上繁杂的位姿测量又能保证鸟瞰图的尺度基本准确。4. MATLAB实操手把手实现一张前方鸟瞰图4.1 第一步读图与选点注意顺序先准备一张车载前视相机拍摄的道路图像越接近水平视角越好。读图后显示出来用ginput手动选四个点。选点前先明确目标区域我想看车辆前方多远的道路横向宽度是多少。假设我想看前方 30 米、左右各 4 米、共 8 米宽的区域。选点顺序非常关键必须保证原图点与目标矩形点一一对应。我的习惯是按顺时针方向选先近左、再近右、再远右、再远左。这样在原图中四个点的位置分别对应车头左下方、车头右下方、远处道路右侧、远处道路左侧。如果顺序乱了比如选了近左、远左、近右、远右变换结果就会呈现折叠或者镜像错位。I imread(road_frame.png); figure; imshow(I); title(请依次点击近左、近右、远右、远左); [x, y] ginput(4); imgPts [x(1), y(1); x(2), y(2); x(3), y(3); x(4), y(4)];这里imgPts保存的就是原图中的四个角点。选点时尽量点在车道边界与图像下边缘的交点附近以及远处车道线消失点两侧合适的位置。远处的点不要太靠近消失点否则梯形太窄求解出的单应矩阵数值稳定性会变差。4.2 第二步构建目标坐标并计算变换接下来定义这四个点对应的目标鸟瞰坐标。我在下面的代码里使用一个很关键的约定世界坐标 X 轴指向车辆前方Y 轴指向车辆左侧。近处的点 X 坐标小远处的点 X 坐标大左侧的点 Y 坐标小右侧的点 Y 坐标大。这里按之前的选点顺序近左、近右、远右、远左分别映射为scale 20; % 比例尺20像素/米 worldPts [0, 0; % 近左 30, 0; % 近右其实近右的Y更大这里方向需要调整 30, 8; % 远右 0, 8]; % 远左等一下这个排列有问题。刚才我定义了 Y 轴指左但四个点的目标位置需要重新整理近左、近右、远右、远左在车辆前方 30m、横向 8m 的矩形里物理坐标应该是近左 (0, -4)、近右 (0, 4)、远右 (30, 4)、远左 (30, -4)。直接用下面的矩阵更严谨scale 20; % 20像素/米 worldPts [0, -4; % 近左 0, 4; % 近右 30, 4; % 远右 30, -4]; % 远左 fixedPts worldPts * scale;把物理坐标乘以比例尺就得到目标鸟瞰图中的像素坐标。这里中心线在 Y0 位置图片左右各占 4 米。然后用fitgeotrans求解单应矩阵tform fitgeotrans(imgPts, fixedPts, projective);imgPts是源图像中的点fixedPts是目标鸟瞰图中的点projective指定求解完整的投影变换。选完四个点以后输出 tform 对象它内部存的就是一个 3×3 的单应变换矩阵只是按照转置方式存储。4.3 第三步定义输出视图并生成鸟瞰图得到变换后还需要告诉 MATLAB 输出图像的像素尺寸和世界坐标范围这就要用到imref2d。imref2d前两个参数分别代表输出图像的行数和列数后面两个是 X 和 Y 方向的世界坐标范围。注意行数对应 Y 方向列数对应 X 方向搞反了鸟瞰图就会被转置。outW round(30 * scale); % 列数30米宽对应600像素 outH round(8 * scale); % 行数8米宽对应160像素 ref imref2d([outH, outW], [0, 30], [-4, 4]); J imwarp(I, tform, OutputView, ref); figure; imshow(J);这里outW是图像宽度方向对应车辆前方 0 到 30 米的纵向距离outH是图像高度方向对应横向 -4 米到 4 米。这样生成的鸟瞰图里车辆正前方的道路会被拉成竖直方向上的矩形左右车道线基本平行。跑完代码建议先肉眼检查车道线是否平行、道路边缘是否平直。如果出现明显的“V”形交叉或扭曲先检查选点顺序再看imref2d的 X、Y 方向是否写反。5. 进阶用相机内外参做逆透视映射IPM5.1 先做相机标定拿到内参矩阵直接选点法简单但缺少物理尺度。工程上我更推荐先做一次标定然后用内外参构建单应矩阵这样鸟瞰图的每个像素都能对应真实世界的物理尺寸。相机内参标定最常用的方法是棋盘格标定。在 MATLAB 里流程很短准备十几张不同角度拍摄的棋盘格照片用detectCheckerboardPoints检测角点用generateCheckerboardPoints生成棋盘格世界坐标然后交给estimateCameraParameters完成标定[imagePoints, boardSize] detectCheckerboardPoints(imageFiles); worldPoints generateCheckerboardPoints(boardSize, squareSize); cameraParams estimateCameraParameters(imagePoints, worldPoints); K cameraParams.IntrinsicMatrix;这里要特别注意MATLAB 中cameraParams.IntrinsicMatrix返回的是 3×3 矩阵的转置形式所以要用K cameraParams.IntrinsicMatrix转回来得到我们推导公式时用的标准内参矩阵。忘了这一步后面构建的 H 就是错的整张鸟瞰图都会偏差。标定完成后利用undistortImage对原始图像做畸变校正。这一步不要省。前视车载相机虽然有畸变校正但镜头边缘依然存在明显的桶形畸变如果不先校正单应变换的结果会在图像边缘区域失真。5.2 估计外参构建地面平面单应矩阵有了内参还需要知道相机相对地面的外参。可以这样操作在车辆前方地面平放一块棋盘格标定板用检测到的点作为图像点用标定板的物理坐标作为世界点通过estimateWorldCameraPose估计相机在世界坐标系中的位姿[worldOrientation, worldLocation] estimateWorldCameraPose(imagePoints, worldPoints, cameraParams); R worldOrientation; t worldLocation;这里R是相机在世界坐标系中的旋转矩阵worldLocation是相机光心在世界系中的位置。构建单应矩阵时需要注意R与t的方向t是从世界系到相机系的平移向量直接取自worldLocation时要确认坐标系定义一致。更稳妥的方式是用extrinsics函数直接得到外参[R, t] extrinsics(imagePoints, worldPoints, cameraParams); t t(:); % 转成列向量R 是 3×3t 是 3×1。然后按公式构建 HH K * [R(:,1), R(:,2), t]; H H / H(3,3);因为世界坐标系中我们约束地面点的 Z0所以[R, t]里只取了旋转矩阵的前两列再拼上平移向量 t组成 3×3 矩阵。这个 H 就是把地面平面坐标映射到图像像素坐标的单应矩阵。我们接下来要做的 IPM需要把图像像素坐标映射回地面因此真正传给 MATLAB 的变换是 H 的逆tform projective2d(inv(H));转置陷阱再次出现。projective2d里的矩阵要以转置形式传入所以在inv(H)后面加了一撇。5.3 输出带真实尺度的鸟瞰图选定输出范围。假设我们想看车辆前方 0 到 30 米、横向左右各 4 米的区域比例尺用 20 像素/米xLim [0, 30]; yLim [-4, 4]; scale 20; outW round((xLim(2) - xLim(1)) * scale); outH round((yLim(2) - yLim(1)) * scale); ref imref2d([outH, outW], xLim, yLim); J imwarp(I, tform, OutputView, ref);跑完以后鸟瞰图上的每个像素就对应 5 厘米 × 5 厘米的真实地面你可以直接通过像素坐标换算实际距离。比如鸟瞰图上两个目标相距 100 像素对应物理距离就是 100 / 20 5 米。5.4 参数选择的实操讨论比例尺scale是个需要权衡的参数。设大了输出图像分辨率更高细节更清楚但是能覆盖的物理范围变小设小了覆盖范围大但远处车道线会被压得很模糊。我一般先用 20 像素/米起步既能看清车道线细节覆盖范围也基本够用后续根据实际检测目标的大小再调。xLim的起点也不一定从 0 开始。车载相机安装在车头车头前方零点零几米到一两米往往存在盲区这个区域在原图里也拍不全。如果只关心 10 米以外的区域可以把xLim设成[10, 40]这样同样分辨率的图像能覆盖更远的范围只是要记得下游模块处理坐标时做偏移校正。6. 工程化要点从单相机鸟瞰到环视拼接6.1 实时系统里的查表法加速不要每次都做投影用imwarp做一次 IPM 在 Demo 里没问题但在实时系统里不能这么干。imwarp每次都要动态计算每个输出像素对应的源图像坐标计算量大。工程上常见的做法是预计算映射表LUT。因为相机外参固定后像素间的映射关系是确定的完全可以离线算一遍遍历鸟瞰图每个像素用transformPointsInverse求出对应原图的坐标存成一张和输出图尺寸相同的坐标表。运行时就只需要查表再用双线性插值把原图像素搬过去。我做过的一个项目里用查表法比每次直接interp2快了几倍内存占用也稳定。查表法还有个额外好处单应矩阵如果因为车辆俯仰角变化需要更新只需要在启动时重新生成一次映射表运行期间不需要改算法其他部分。配合惯性测量单元的姿态补偿可以在车身上下颠簸时维持不错的鸟瞰图稳定性。6.2 多相机融合与全景拼接环视全景图是四路鱼眼相机各自做 IPM然后拼到同一个地面坐标系。这个流程分几步每路相机分别标定得到各自的内参和外参定义统一的自车地面坐标系每个相机把采集图像映射到这个统一坐标系下的对应区域最后处理重叠区域决定各相机的融合权重。拼接的重点和难点是重叠区域。相邻相机在车身周围有重叠视野同一段车道线可能同时出现在两路相机的鸟瞰图中。如果外参标定稍有偏差重叠区域就会出现错位车道线变成“双影”。解决方法是先精确标定再在融合时给重叠区域分配权重比如越靠近相机图像中心权重越大越靠近边缘权重越小让过渡平滑。多频段融合能进一步减少接缝闪烁但计算量也更大需要根据平台算力权衡。6.3 ROI处理与性能折中很多情况下不需要把整幅前视图都转换成鸟瞰图。比如车道线检测只关注车辆前方和左右一定范围完全可以把图像下部的路面区域裁剪出来只对这个 ROI 做 IPM大幅减少计算量。天空区域、远处地平线以上的部分本来就不满足地面假设投过去只会变成一团团放射状噪点留着还干扰后续处理。性能上还有一个小技巧输出分辨率不必和输入一致。如果检测算法只需要判断车道线的横向位置200×400 像素的鸟瞰图往往足够如果要做像素级语义分割那再提到 400×800。先定算法需求再定输出分辨率不要一开始就追求大图。7. 常见问题与排查实录7.1 鸟瞰图严重扭曲或折叠这个现象十有八九是选点顺序错乱。四个对应点的顺序如果原图点和目标图点不一一对应单应矩阵求解结果会出现翻折或错位呈现一种“图被从中间撕开再拼起来”的诡异效果。排查方法输出imgPts和fixedPts打印出来按顺序检查每一对点在地面上的相对方位是否一致。通常从近到远、从左到右依次记录就不会乱。另一个常见原因是点没有落在同一平面上。逆透视映射要求四个点都在地面平面上选点如果不小心点到了路沿顶面、机盖、路边台阶这些高度不为零的物体上它们并不满足 Z0 的约束变换出来的图会有奇怪的倾斜和缩放。选点的时候尽量放大图像把点落在车道线或路面材质交界处。7.2 输出的道路区域缺失或范围偏移imwarp默认的输出视图坐标范围是输入图像的坐标范围。如果你不指定OutputView鸟瞰图只会把变换后的有效区域塞到原来图像大小的一块区域里经常出现路面只占了画面一小块、其他全是黑边的情况。解决方案是显式创建imref2d并传给imwarp的OutputView明确告诉它输出图像的世界坐标范围和像素尺寸。X、Y 方向写反也是很常见的问题。表现为输出图横竖比例不对或者车道线方向跑到横向去了。检查imref2d([outH, outW], xLim, yLim)里第一个参数的行数对应 YWorldLimits第二个参数的列数对应 XWorldLimits。你的地面坐标里如果 X 是车辆纵向那xLim就该对应图像宽度方向也就是列数方向Y 是横向对应图像高度方向也就是行数方向。7.3 变换后的图模糊或边缘有锯齿投影变换本质是重采样输出图像每一个像素都要从原图取一个对应位置这个过程会引入采样误差。近处区域在鸟瞰图被放大远处区域被压缩分辨率天然不均匀。缓解手段有三个第一提高输出分辨率让地图上的细节有更多像素承载第二在imwarp里设置插值方法为双三次而非默认形式边缘更平滑第三先做畸变校正再做 IPM畸变区域的重采样误差会小很多。还有一个隐蔽问题图像压缩噪点。拍摄的图像如果压缩率太高在鸟瞰图里压缩伪影会被拉伸放大表现为背景纹理上有规则的网格状图案。这种情况下最好的办法是回到数据源头提高原始图像质量比任何后处理都有效。7.4 内外参法里各种转置和方向坑内参矩阵转置坑前面提过cameraParams.IntrinsicMatrix需要转置。外参方向同样容易出问题extrinsics返回的t是 1×3 向量参与矩阵乘法前要转成列向量estimateWorldCameraPose返回的worldLocation与t的符号关系还要依赖坐标系定义用之前最好拿一个已知地面点做投影验证。我踩过一次很深的坑外参方向弄反之后鸟瞰图表面看完全正常但测量距离整体偏差了 20%后来拿真实车道宽度一对比才发现。标定板摆放位置也很关键。外参标定板必须平放在地面上并且标定板平面要和地面平面重合否则 Z0 的假设在标定阶段就不成立构建出来的 H 自然不准确。标定时尽量多拍几张、覆盖画面不同位置再检查重投影误差是否小于 0.5 像素。一些个人的经验体会做了几个和 BirdView 相关的视觉项目之后我的体会是理论推导部分相对清爽真正考验人的是坐标约定和边界条件。同一个投影公式你们团队约定 X 轴指前还是指右Y 轴指左还是指上直接决定后续所有代码能不能互相衔接。所以开始写代码前最好把坐标系定义写成一页纸的说明贴在文档最上面让大家一致遵守。还有一个经验是不要盲目追求大范围的鸟瞰图。我曾把前方 50 米的范围全部拉进鸟瞰图里结果远处的车道线扭曲得没法看因为地面在大范围上不是严格平整的。后来收敛到前方 30 米、左右各 4 米的范围效果一下子稳了。多数感知任务的兴趣区域本来就不会太远与其纠结远距离的几何漂移不如把可用的近中距离做到高精度工程上收益更大。最后想说BirdView 这件事的计算量非常小但几何先验的威力却很大。很多看起来需要堆数据、堆算力才能解决的问题其实一个正确的投影变换就能让下游模型省掉大量工作。希望这篇文章能帮你少走一点弯路把精力花在真正有价值的部分上。
阅读完成 · 觉得有帮助?
咨询建站