十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从零实现上帝视角:逆透视映射与相机标定实战解析

从零实现上帝视角:逆透视映射与相机标定实战解析 “gods-eye-view”这个名字我第一次看到的时候还以为是个什么玄学项目结果一查这不就是大家常说的“上帝视角”嘛。在图像和视觉领域它对应的就是鸟瞰图视角Birds Eye ViewBEV也就是把摄像头拍到的前视画面通过一系列坐标变换改造成从空中垂直往下看的那种俯视图。这个需求在现实里太常见了。倒车影像里的360环视、自动驾驶里的道路感知、体育转播里的战术回放、安防监控里的全景漫游背后都用到了同一套底层能力把多个相机或单个相机拍到的东西投影到一个统一的地平面上变成机器人或车辆真正能看懂、能规划路线的那种“平面图”。这篇文章我就来完整拆解一下用传统计算机视觉的方式把“gods-eye-view”从概念落到代码到底需要做哪些事每个环节的技术点是什么以及我实际踩坑之后换来的经验。1. 项目到底在做什么先搞清“上帝视角”的本质1.1 为什么叫“gods-eye-view”而不是简单叫俯视图很多人第一次接触这个概念时会下意识觉得“俯视图”不就是把无人机飞高一点拍出来的画面吗这句话对了一半。无人机的确是“真的”从上方往下拍所以物理上就具备上帝视角但现实里我们手上的摄像头绝大多数是装在车前、墙边或者机器人头部它们的朝向基本是斜前方或者近似水平。这种情况下画面里地面是斜着往后拉伸的远处的物体很小近处的物体很占画面空间关系和我们人类站在高处往下看完全不一样。“gods-eye-view”要做的就是在一张或者多张普通视角的图像上通过几何变换重建出一个从正上方往下观察的虚拟视图这个视图中的地面网格是均匀的、米制单位是对得上的道路边线是平行的车身周围障碍物的相对位置关系也变得非常直观。它解决的痛点就是“视角造成的距离误判”让下游算法或者人类观察者能在统一的空间坐标系里理解场景。1.2 这个项目适合谁做以及从哪里下手如果你想做的是一个车载360环视系统大家通常采用的做法是四个广角/鱼眼相机各覆盖一个方向然后各自生成俯视图再拼成一个完整的环视画面。但如果你的场景相对简单比如固定摄像头监控停车场的一个角落或者给桌面级机器人做视觉避障那么单目方案就足够起步了也就是说只用一个相机也能先体验一下“上帝视角”的完整流程。我这次做的“gods-eye-view”项目选择的路线也是先单目后扩展。第一步先解决“单相机怎么生成一块能用的俯视图”把射影几何、相机标定、逆透视映射IPM的核心流程跑通第二步再改成多相机版本把四路画面通过标定参数变换到同一个地面坐标系然后做图像拼接和融合。这样做的好处是每一步的错误都能定位清楚不会一上来就面对“四个图都对不齐不知道是相机标定错了还是拼接算法写错了”这种玄学问题。1.3 技术路线选型传统IPM还是深度学习BEV在做技术选型的时候我明确比较过两条路线。传统路线以IPMInverse Perspective Mapping逆透视映射为核心它的数学基础是针孔相机模型和单应性变换。你只需要知道相机的内参、外参以及假设地面是一个平面就能把图像中每个像素映射到世界坐标系下的地面网格上。优点是计算量小、原理透明、没有黑盒普通CPU都能实时跑缺点是它严格依赖“地面是平面”的假设遇到坡道、台阶、路面起伏就会产生形变。深度学习路线则是近年来大火BEV感知像LSSLift, Splat, Shoot这类方法用网络去学习从图像特征到BEV特征的映射可以直接输出带语义的“上帝视角”网格。优点是对复杂地形、动态场景鲁棒性高缺点是需要大量标注数据、GPU训练环境而且整个映射过程可解释性差。对于“gods-eye-view”这个项目来说如果你是为了工业部署或者产品原型我建议先学习并跑通传统IPM因为它是所有BEV方案的基础——哪怕深度学习方案最后也是试图从一个虚拟相机模型出发去理解地面网格先把几何搞明白后面看深度学习BEV论文才会真正看懂它在“学”什么。2. 逆透视映射IPM的核心原理摄像头是怎么“骗人”的2.1 针孔相机模型与内参矩阵要理解IPM绕不开相机的成像模型。普通相机可以简化成“针孔相机”三维世界中的一个点经过相机光心投射到成像平面上形成一个像素点。这个映射关系里最重要的参数分为两类一类是内参一类是外参。内参矩阵K描述的是“从相机坐标系到像素坐标系”的变换它长这样K [fx 0 cx 0 fy cy 0 0 1]其中fx、fy是焦距的像素表达cx、cy是光心在图像上的像素坐标。这个矩阵加上畸变系数径向畸变k1、k2、k3切向畸变p1、p2就是相机标定要产出的核心结果。你可以把内参理解为“镜头本身的性格”不管相机装在哪里它的内参是固定的。2.2 透视投影和鸟瞰投影的关键差异同样是看地面上的一条白线前视相机画面里它是一条从近处延伸到远处的斜线从宽变窄最后汇聚成一个消失点而在鸟瞰视图里这条白线应该是一条笔直的、宽度不变的平行线。为什么会这样因为两种投影方式对“深度”的处理不一样。透视投影perspective projection近大远小远处物体压缩到几乎看不到这正是人眼和普通相机的成像方式。正交投影orthographic projection所有平行线保持平行尺寸和距离成线性比例关系鸟瞰图就是近似这种投影。IPM要做的事情就是把成像平面上的像素点反投影到地平面世界坐标系中的Z0平面然后把这个地平面用一个虚拟的“垂直向下”相机重新成像。这个过程可以用一个3x3的单应矩阵H直接描述。2.3 单应矩阵H八个自由度里到底装了什么单应矩阵H是IPM的核心它把一张图像上的点映射到另一张图像上的点。对于一个固定安装的相机只要地面是平的那么“相机图像”和“鸟瞰图像”之间就存在一个确定的单应变换。H是3x3的矩阵但它有8个自由度9个元素减掉一个尺度归一化。这8个自由度背后对应着相机相对地面的俯仰角、偏航角、滚转角、安装高度以及焦距、光心等等参数的综合效果。换句话说不论是直接量相机外参再去构造H还是直接找四个对应点解算H最后得到的东西本质上是同一个几何关系。我在实际项目中最常用的做法是后者如果你懒得整套相机标定可以先让相机固定拍一张图在这张图上手动选四个你知道地面真实坐标的点比如用卷尺量好四个角点之间的距离然后对应到你想生成的鸟瞰图的四个像素位置调用OpenCV的getPerspectiveTransform就能得到H。这种方法很土但非常快适合快速原型验证。2.4 外参相机安装位姿决定了俯仰和朝向当你想把“相机随便一拍”升级成“可复用的精确安装方案”时手动选点的弊端就出来了你每次动过相机支架就得重新选点而且手动选点误差很大边缘的像素可能偏好几个像素。所以生产级方案必须要做完整标定其中就包括求解外参。外参包含旋转矩阵R和平移向量t描述的是相机坐标系在世界坐标系的哪个位置、朝哪个方向看。对于车载或者机器人场景我们通常会定义一个“车身坐标系”或“地面坐标系”比如让X轴朝前Y轴朝左Z轴垂直地面向上然后地面平面就是Z0。相机相对于地面的姿态最简单的情况就是相机离地面高度h俯仰角为pitch滚转roll很小偏航yaw朝向车身正前。有了外参后IPM的实现就不是简单地用四个点去拟合而是可以通过一个固定公式把图像坐标和地面坐标直接互相映射。这也是多相机环视系统能够统一拼接的基础每个相机都把自己的图像投影到同一个Z0的地面网格上那么四路图像天然就落在同一个坐标系里。3. 实操落地从标定到生成俯视图的完整流程3.1 环境准备与工具链选择这套流程我建议直接用Python OpenCV来完成因为OpenCV已经把相机标定、张量变换、图像融合都封装得很好了不需要自己造轮子。依赖其实只有两个opencv-python负责相机标定、单应变换、图像读写和融合。numpy负责矩阵运算。另外为了标定相机你需要一个棋盘格标定板。不用买那种非常昂贵的工业标定板用普通打印机在A4纸上打印一个6x9或者7x10的棋盘格然后贴在平整的硬纸板或亚克力板上就能用。需要注意的是棋盘格必须平整如果纸面起皱或者板子弯曲标定出来的畸变系数会带上一堆假误差。3.2 相机内参标定的具体步骤与代码这一步的目标是得到相机内参矩阵K和畸变系数。标准流程是手持标定板在不同角度、不同距离、不同位置下拍摄10到20张照片然后调用OpenCV的角点检测和标定函数。我一般会写一个很小的采集脚本抽帧保存为jpg然后统一处理。核心代码如下import cv2 import numpy as np # 棋盘格内部角点数不是格子数 pattern_size (9, 6) # 7x10格子的棋盘格内部角点就是9x6 objp np.zeros((pattern_size[0] * pattern_size[1], 3), np.float32) objp[:, :2] np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2) obj_points [] # 世界坐标系中的三维点 img_points [] # 图像坐标系中的二维点 images [fcalib_{i:02d}.jpg for i in range(1, 21)] for fname in images: img cv2.imread(fname) gray cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, corners cv2.findChessboardCorners(gray, pattern_size, None) if ret: # 亚像素细化精度更高 criteria (cv2.TERM_CRITERIA_EPS cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) corners2 cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria) obj_points.append(objp) img_points.append(corners2) else: print(fskip {fname}) ret, mtx, dist, rvecs, tvecs cv2.calibrateCamera( obj_points, img_points, gray.shape[::-1], None, None ) print(内参矩阵:\n, mtx) print(畸变系数:\n, dist)注意几个细节pattern_size (9, 6)对应的是内部角点数如果你的棋盘格是10x7个格子内部角点才是9x6别搞反了。拍摄时要把标定板放到画面的边缘和角落位置因为畸变在边缘最明显如果所有照片里标定板都只在画面正中央畸变系数几乎是学不到的。calibrateCamera返回的ret是重投影误差正常情况下应该小于0.5像素如果大于1像素说明有照片抖动模糊或者角点检测错位了。3.3 畸变矫正为什么不能跳过这一步有了内参和畸变系数之后原始图像在用来做IPM之前一定要先做畸变矫正。鱼眼相机或者广角相机的桶形畸变非常严重如果不矫正画面边缘的直线都是弯的矫正完才能保证“画面中的直线对应现实中的直线”。h, w img.shape[:2] newcameramtx, roi cv2.getOptimalNewCameraMatrix(mtx, dist, (w, h), 1, (w, h)) undistorted cv2.undistort(img, mtx, dist, None, newcameramtx)这里有一个可选参数alpha控制输出图像保留多少边缘像素。alpha越大保留的边缘越多但输出图像会出现黑色无效区域alpha越小输出图像裁剪得越狠丢掉的原始像素越多。我一般设成1宁可保留黑边也不希望有用的画面边缘被裁掉因为后面的透视变换还会再裁一次。3.4 外参标定让相机坐标系和地面坐标系对齐内参解决的是“镜头是什么样的”外参解决的是“相机装在哪里、朝哪看”。这一步我推荐用solvePnP来解而不是手动量角度。做法是在相机正前方地面上摆放标定板让标定板平面和地面重合然后选取标定板上的角点作为地面坐标系中的已知点再通过图像中对应的角点位置求解出相机相对地面坐标系的旋转和平移。# 假设标定板放在地面上每个格子边长 square_size 米 square_size 0.025 # 2.5cm pattern_size (9, 6) objp_ground np.zeros((pattern_size[0] * pattern_size[1], 3), np.float32) objp_ground[:, :2] np.mgrid[0:pattern_size[0], 0:pattern_size[1]].T.reshape(-1, 2) objp_ground * square_size # 角点检测同上 ret, corners cv2.findChessboardCorners(gray, pattern_size, None) # 注意solvePnP 要求输入是至少4个非共线的3D点 success, rvec, tvec cv2.solvePnP(objp_ground, corners2, mtx, dist) R, _ cv2.Rodrigues(rvec) # 旋转向量转旋转矩阵 # camera_pos_in_ground -R.T tvec # 相机在世界坐标系中的位置这里要特别注意objp_ground的坐标是定义在“地面坐标系”里的也就是说Z坐标全为0。solvePnP解出来的rvec、tvec就是“从地面坐标系到相机坐标系”的外参。在这个步骤里我踩过一个比较大的坑标定板放在地面上时如果地面有反光或者标定板和地面之间有空隙比如纸板边缘翘起solvePnP结果会差非常多。所以最好选一个室外柏油路或者室内瓷砖地面这种比较平的环境铺好板子之后要确认板子完全贴地不要用手去压边角。3.5 构造俯视图从点到面的完整映射现在的目标很明确已知畸变矫正后的图像、内参、外参我想算出一个坐标变换把图像上每个像素都投影到地面网格上的目标位置。有两种实现路径。路径A手动选点 getPerspectiveTransform这是最快的方式。在相机画面中找出地面上已知的四个点。比如你知道地面上一块矩形区域的长宽是2米x3米那么你在画面里点出这四个角点的像素坐标对应到目标俯视图里的四个角的位置比如一个1200x1800像素的图像调用一次getPerspectiveTransform和warpPerspective就完成了。src_pts np.float32([[x1, y1], [x2, y2], [x3, y3], [x4, y4]]) dst_pts np.float32([[0, 0], [1200, 0], [1200, 1800], [0, 1800]]) H cv2.getPerspectiveTransform(src_pts, dst_pts) bird_view cv2.warpPerspective(img, H, (1200, 1800))这个方法的好处是快缺点是一旦相机动了就需要重新选点而且选点精度决定了俯视图质量。路径B基于相机模型直接映射如果你已经做了完整的内参和外参标定那么可以建立一个固定大小的地面网格比如车辆周围10米x10米分辨率0.05米/像素然后对网格上的每个地面点反投影到图像坐标再用OpenCV的remap一次性重采样效率会高很多。这个流程我后面细讲。3.6 用remap做实时俯视图在实际部署阶段逐帧调用warpPerspective虽然能用但有重复计算相机的内外参是不会变的所以像素映射关系一直不变。更好的做法是预先算好映射表map_x和map_y然后每次只做一次remap查表速度能提升好几倍。# 定义输出俯视图的地面网格 output_size (400, 600) # (height_pixels, width_pixels) resolution 0.05 # 每像素0.05米 width_m output_size[1] * resolution height_m output_size[0] * resolution # 构建地面网格坐标单位米 x_coords np.linspace(-width_m/2, width_m/2, output_size[1]) y_coords np.linspace(0, height_m, output_size[0]) xx, yy np.meshgrid(x_coords, y_coords) zz np.zeros_like(xx) # 转成齐次坐标 ones np.ones_like(xx) grid_homo np.stack([xx, yy, zz, ones], axis-1) # shape: (H, W, 4) # 利用外参把地面点变换到相机坐标系 # P_cam [R | t] P_ground pts_cam (R grid_homo[..., :3, None]).squeeze(-1) tvec.reshape(1, 1, 3) # 透视投影到像素坐标 x_cam pts_cam[..., 0] y_cam pts_cam[..., 1] z_cam pts_cam[..., 2] u (mtx[0, 0] * x_cam / np.where(z_cam 0, 1e-6, z_cam) mtx[0, 2]) v (mtx[1, 1] * y_cam / np.where(z_cam 0, 1e-6, z_cam) mtx[1, 2]) u u.astype(np.float32) v v.astype(np.float32) # 超出图像范围的像素设为-1remap时自动赋0 u_out (u 0) | (u img.shape[1]) v_out (v 0) | (v img.shape[0]) u[u_out | v_out] -1 v[u_out | v_out] -1 bird_view cv2.remap(undistorted, u, v, cv2.INTER_LINEAR)麻烦的是如果你不熟悉齐次坐标和矩阵维度这里很容易写错。一个更稳妥的检查方法随便挑几个地面点手算一下它应该落在图像哪个位置再看代码输出是否匹配。比如地面上1米1米的点如果相机俯仰角是30度、高度1米它大约会出现在图像偏下方的一个位置你直接打印u[0, 0]、v[0, 0]判断是否合理。4. 多相机版本从单目扩展成真正的环视“上帝视角”4.1 四路相机方案的整体架构当你把单目的整套流程跑通后多相机环视其实是在同一个框架上做扩展。每个相机各自完成内参标定 外参标定 畸变矫正然后全部投影到同一个地面网格上。我在项目中用的方案是前后左右四路广角相机每路都有一个大概100度以上的水平视角保证相邻相机之间有重叠区域。整体流程可以分成离线阶段和在线阶段离线阶段对每个相机单独标定内参再把车辆停在平坦空地放置标定布/标定板对每个相机求解外参顺便利用标定布上的特征点微调相机间相对位姿。在线阶段每路图像先做畸变矫正再通过预先算好的查表remap生成各自的俯视图最后把四幅俯视图放到同一个canvas上做融合。4.2 多相机外参对齐的经验多相机环视最大的坑在于你单独标定每个相机的外参时它们参考的地面坐标系可能不一致。比如前相机的外参是相对“前保险杠中心地面点”定义的左相机是相对“左后视镜下方”定义的那它们投影到同一个地面网格时就会有平移偏差。所以你需要预先定义一个统一的车身坐标系比如车辆后轴中心在地面上的投影点作为原点X轴向前Y轴向左然后所有相机外参都转换到这个坐标系下。这一转换其实不难你在每个相机外参标定完后记录下当时标定板放置的位置相对车身坐标系原点的偏移量再把平移向量tvec做一个增量平移即可。千万不要让每路相机图省事各自定义原点否则后面的拼接一定乱套。4.3 重叠区域的图像融合四路俯视图生成后相邻相机之间必然有重叠区域。如果直接拼接重叠区域会出现明显的亮度差异和重影。最简单的解法是羽化融合feather blending也就是在重叠区域根据离图像中心的距离做一个线性权重。alpha_map np.ones_like(img_left, dtypenp.float32) # 在重叠区左边部分alpha从1渐降到0 alpha_map[:, overlap_left:overlap_right] np.linspace(1, 0, overlap_width) blended left * alpha_map right * (1 - alpha_map)如果两个相机在同一位置拍摄同一地面亮度差异很大单靠线性融合还是会有“虚影”此时建议先对每路图像做整体亮度增益补偿gain compensation。做法是对重叠区域计算两图的平均亮度比值然后乘一个全局系数把亮度拉齐。若还想更好可以用多频段融合multi-band blending但一般车载环视里羽化融合增益补偿已经够用了。4.4 拼接时另一个重要问题俯视图分辨率怎么定俯视图的分辨率不是越大越好。分辨率太大像素面积大但每个像素对应的物理尺寸过小而相机的原始分辨率有限拉伸后只是插值并没有增加细节反而让边缘更虚。一个合理的选择是让输出俯视图的“地面采样率”和图像边缘的地面采样率大致匹配。比如相机安装高度1.5米水平视角90度画面底部靠近车身的区域每像素可能对应1厘米左右的实际地面长度而画面顶部远处每像素可能对应5到10厘米。此时如果把整个俯视图都设成0.01米/像素远处必然糊成一片。所以实践中我会把分辨率设在0.03到0.05米/像素之间后续如果做深度学习检测再考虑更高分辨率的ROI局部放大。5. 常见问题与排雷记录我踩过的坑和排查经验5.1 相机标定阶段最容易踩的坑标定是整个流程里隐性成本最高的环节。我总结过一张自查表现象可能原因排查与解决部分图片角点检测失败标定板反光、边缘被截断、画面过暗改变拍摄角度确保棋盘格完整入镜避免强光和镜面反射重投影误差大于1像素照片模糊、标定板不平整、角点亚像素细化失败拍摄时用三脚架或提高快门速度换更平整的板子内参矩阵输出明显异常fx和fy差别过大图片比例不对、棋盘格方向输入错误检查pattern_size是否和实际板子一致标定结果每次都不一样照片数量太少或拍摄角度过于单一保证20张以上覆盖画面中心和四角距离远近都拍最有意思的一次是我用了某个手机广角镜头做标定20张照片拍完重投影误差一直在0.9像素上下。排查了半天发现是标定板贴在了一块微弯的塑料板上板子中心比边缘高出了大概两个毫米。后来换成玻璃台面加亚克力板误差立刻降到0.3。标定板的“平”有时候比相机的素质还重要。5.2 IPM之后画面拉伸变形怎么办做完逆透视映射后最常见的反馈是画面两侧怎么是歪的地面上的直线为什么变成曲线了如果直线变成弧线大概率是畸变矫正没做好。你可以在原图上随便找一条靠近画面边缘的直线边缘比如墙面和地面的交界线先做畸变矫正看这条线是不是变直了。如果没有变直说明标定出的畸变系数不对需要重新标定。另一种情况是俯视图中间的尺度对但越往两边越拉伸呈现放射状扭曲。这通常是因为外参不准特别是滚转角roll和偏航角yaw有误差。排查办法是打印一些网格点的位置和实际地面用卷尺量出来的坐标做对比哪个方向偏差大就去调整哪个角。还有一种情况是地面本身就不平。IPM假设地面是Z0的平面如果你在坡度路面或者马路牙子旁边测试远处一定会翘起来。这是物理限制不是算法bug。生产产品时要么限制使用场景要么用局部平面拟合把地面切分成多个小平面分别映射来缓解。5.3 拼接重影和亮暗不一致的处理经验多相机拼接时重影问题基本有三个来源。第一外参没对齐。两路相机对同一个地面特征点投影到不同坐标就会重影。这时用上面提到的车身统一坐标系重新确认每路外参。第二融合权重太生硬。重叠区域如果从1直接跳到0会出现一条非常明显的接缝。用渐变的羽化权重可以缓解但不能完全消除尤其是当两路相机的曝光参数不一致时。第三曝光不一致。这是最难缠的。两个相机朝向不同一个对着太阳方向一个背着太阳方向两者的自动曝光差异会很大。我建议在环视系统中把自动曝光锁死使用固定曝光时间和固定增益。如果硬件不支持锁定那就必须在软件里做增益补偿。5.4 实时性能优化从30ms降到8ms的优化记录最开始我的原型是Python直接逐帧warpPerspective一帧640x480的俯视图大概要花30到40毫秒勉强能跑20多帧。后来做了三步优化直接把耗时压到了8毫秒左右预计算remap查找表。相机标定好后map_x和map_y提前生成运行时只做一次cv2.remap不用每帧算透视变换矩阵。压缩输入图像尺寸。畸变矫正和remap都在半分辨率或者640x480下做输出俯视图也不需要太大等真正要用到细节的时候再局部放大。用多线程流水线。一路线程收图像做畸变矫正另一路线程做remap和后续融合中间用双缓冲避免锁等待。这里不需要很复杂的并发编程简单的queue或者最新帧覆盖策略就有效。如果还嫌慢可以把cv2.remap放到OpenCV的UMat或者CUDA上跑GPU加速下的remap基本不占时间瓶颈会转移到图像采集和解码上。5.5 投影到“非地面平面”的扩展思路“gods-eye-view”不只限于地面。你在某些场景里可能希望看到垂直墙面的鸟瞰图或者车内座椅表面的俯视图原理其实一样只要你定义一个平面知道相机在这个平面坐标系下的外参就可以做同样的IPM变换。区别只是把“地面坐标系”换成“平面坐标系”。我后来在项目里顺带做了一个很实用的功能把车侧的墙面区域也投影出来用来检测擦挂风险。做法就是额外定义一面垂直于地面的假想“墙平面”把相机图像的相应区域投影上去再结合深度估算就可以判断车身和墙面的距离。这个扩展在自动泊车的近距感知里非常有用。6. 还能往哪个方向继续玩“gods-eye-view”这套流程本身看起来只是一个图像变换但它是很多高级功能的地基。我现在在项目里主要扩展了三个方向第一个方向是把俯视图喂给目标检测网络。因为俯视图中的物体尺度和位置是米制均匀的不需要像前视图那样做多尺度预测网络结构可以更小、更轻量。而且检测出的障碍物坐标可以直接转换到车身坐标系给到下游控制模块省掉了一大堆坐标变换。第二个方向是做轨迹预测和规划可视化。把历史轨迹、障碍物轨迹、规划路线全部投影到同一张俯视图上调试自动驾驶算法的时候简直不要太直观。你有问题直接在图上画线比看一摞坐标数组效率高多了。第三个方向是结合深度估计做3D占用网格。俯视图是2D的但它可以和单目深度估计结合把像素抬升到不同高度生成简易的3D占用体素。这个就是轻量级BEV感知的雏形了后面再上深度学习方案也顺理成章。如果你也想试试“gods-eye-view”我建议不要一上来就到处找现成的代码库跑通就算了那不叫会那叫“跑过”。真正动手标定一次相机、解一次外参、调一遍融合你对透视变换、坐标系的感受会完全不一样。遇到画面扭曲、拼接重影这种问题的时候别急着怀疑代码先从你标定板平不平、外参对不对开始排查——绝大多数翻车现场问题都出在看不起眼的那一步。
返回列表