当前位置: 首页 > news >正文

self-supervised-depth-completion数据管道全解析:KITTI数据集结构、相机标定与16位深度PNG读取

self-supervised-depth-completion数据管道全解析:KITTI数据集结构、相机标定与16位深度PNG读取

【免费下载链接】self-supervised-depth-completionICRA 2019 "Self-supervised Sparse-to-Dense: Self-supervised Depth Completion from LiDAR and Monocular Camera"项目地址: https://gitcode.com/gh_mirrors/se/self-supervised-depth-completion

self-supervised-depth-completion 是 MIT 团队发表于 ICRA 2019 的自监督深度补全(Self-supervised Sparse-to-Dense)项目的 PyTorch 官方实现:只用稀疏 LiDAR 点云加单目相机图像,无需稠密深度标注,就能训练出密集深度图。而这一切的地基,就是它的数据管道——本文带你完整读懂 KITTI 数据集结构、相机标定文件的用法,以及最容易踩坑的16 位深度 PNG 读取技巧,帮你快速上手这套深度补全训练流程。

一、项目与代码获取:一分钟了解背景 🚀

这套代码在仅使用 KITTI 数据集的情况下完成了深度补全训练,没有用 Cityscapes 等其他驾驶数据集做预训练。核心模块分工如下:

模块文件职责
数据集加载dataloaders/kitti_loader.pyKITTI 数据读取、路径组织、图像/深度解码
相机标定dataloaders/calib_cam_to_cam.txtKITTI 标定原始文件,解析出内参矩阵
数据变换dataloaders/transforms.py裁剪、翻转、色彩抖动等增强
位姿估计dataloaders/pose_estimator.pySIFT 特征匹配 + PnP 求解相机位姿
训练入口main.py命令行参数、损失组合、训练主循环

如需本地复现,可直接克隆仓库:

git clone https://gitcode.com/gh_mirrors/se/self-supervised-depth-completion

二、KITTI 数据集结构:深度补全的“原料库” 📂

数据准备分两步:先从 KITTI 官网下载 Depth Completion 评测基准(含 Velodyne 稀疏深度与半稠密标注),再运行仓库自带的脚本抽取对应帧的 RGB 图像:

./download/rgb_train_downloader.sh # 抽取训练集 RGB ./download/rgb_val_downloader.sh # 抽取验证集 RGB

两个脚本的工作逻辑非常巧妙:从 KITTI 原始云端下载*_sync.zip压缩包,解压后只保留image_02/image_03(灰度相机)目录,删掉立体相机image_00image_01、激光雷达点云和 IMU 文件以节省空间,最终存入../data/data_rgb。训练与验证序列在脚本里通过注释开关显式指定,保证了训练/验证严格不重叠。

整理后的完整目录结构如下:

. ├── self-supervised-depth-completion # 代码主目录 ├── data | ├── data_depth_annotated # 半稠密真值(标注) | | ├── train | | ├── val | ├── data_depth_velodyne # 稀疏 LiDAR 深度(投影到相机图像) | | ├── train | | ├── val | ├── depth_selection # 评测用选帧 | | ├── test_depth_completion_anonymous | | ├── test_depth_prediction_anonymous | | └── val_selection_cropped | └── data_rgb # 下载脚本抽取的 RGB 图像 | | ├── train | | └── val └── results # 训练输出

代码中通过 glob 模式把三类文件对齐(见dataloaders/kitti_loader.pyget_paths_and_transform):

  • 稀疏深度:data_depth_velodyne/{train,val}/*_sync/proj_depth/velodyne_raw/image_0[2,3]/*.png
  • 稠密真值:data_depth_annotated/{train,val}/*_sync/proj_depth/groundtruth/image_0[2,3]/*.png
  • RGB 图像:按同样目录约定从data_rgb映射生成

其中image_0[2,3]这个写法表示同时支持灰度相机的 02/03 两个子目录;0[2,3]也是为什么image_00/image_01可以安全删除的原因。数据加载器还会做长度一致性校验,任何一类文件缺失都会直接抛出明确的RuntimeError,方便你定位是漏下载了哪一类数据。

三、相机标定解析:从 calib 文件到内参矩阵 📐

自监督训练中的光度损失(photometric loss)依赖精确的相机内参,而内参来自dataloaders/calib_cam_to_cam.txt——这是 KITTI 2011-09-26 校准日的原始标定文件。

dataloaders/kitti_loader.pyload_calib()(第 18–39 行)只取文件中P_rect_02一行:

P_rect_02: 721.5377 0 609.5593 44.85728 0 721.5377 172.8540 2.163791 ...

这是 3×4 的投影矩阵P = K [R|t],取左上 3×3 就是内参矩阵 K:焦距fx = fy ≈ 721.54,主点cx ≈ 609.56cy ≈ 172.85

容易忽略的细节:KITTI 原图尺寸为 1242×375,而训练时要做中心裁剪到 1216×352,裁剪会移动光心(但焦距不变),所以代码对手动做了补偿:

  • K[0,2] -= 13:宽度两侧各裁 13 像素(1242 → 1216)
  • K[1,2] -= 11.5:高度两侧各裁 11.5 像素(375 → 352)

这个补偿值必须和BottomCrop的输出尺寸oheight, owidth = 352, 1216严格对应,改输出尺寸时记得同步修改。main.py中用同一份load_calib()构造Intrinsics(owidth, oheight, fu, fv, cu, cv),供inverse_warp.py做多尺度逆投影。

四、16 位深度 PNG 读取:为什么深度值要除以 256 🔍

这是整个数据管道里最容易出错的一步。KITTI 的深度图是 16 位(uint16)PNG,存储约定为:

像素值 = 深度(米)× 256,即 1 米 = 256 个计数

读取逻辑在kitti_loader.pydepth_read()(第 148–163 行),核心只有三句:

depth_png = np.array(img_file, dtype=int) # 按整数读,避免精度丢失 assert np.max(depth_png) > 255 # 校验:确认是 16bit 而非 8bit depth = depth_png.astype(np.float) / 256. # 计数 → 米

要点归纳:

  1. 先断言最大值 > 255:如果文件被某些看图软件转存成 8 位 PNG,断言会直接失败,提醒你文件已损坏。
  2. 除以 256 而不是 255:KITTI 的 16 位深度用的是"米 × 256"编码,与图像亮度归一化(/255)不同,两者千万别混。
  3. 零值 = 无测量depth == 0的像素表示 LiDAR 没有打到点,后续损失计算中会用mask = (d < 1e-3)把这些位置剔除,只在有真值的像素上算监督。
  4. 读取后通过np.expand_dims(depth, -1)补上通道维,变成(H, W, 1)以便和 RGB 的(H, W, 3)走同一套变换管线。

与之对应的rgb_read()则按uint8读取,保持在 [0, 255] 整数范围。

五、数据增强:BottomCrop、随机翻转与色彩抖动 🎛️

增强逻辑在train_transform()中组合完成,不同 split 使用不同策略:

变换训练集验证集(full)评测(select/test)
BottomCrop((352, 1216))✅ 垂直取底 + 水平居中❌ 原尺寸
水平随机翻转(概率 0.5)
色彩抖动(亮度/对比度/饱和度 ±--jitter,默认 0.1)✅ 仅作用于 RGB

几个值得注意的设计:

  • 几何变换对 RGB、稀疏深度、真值同步生效,保证像素严格对齐;翻转时 RGB 与深度一起np.fliplr,不会出现错位。
  • 色彩抖动只加在 RGB 上,这正是光度自监督训练想要的:让网络学会忽略光照变化。
  • 裁剪放在图像底部:驾驶场景中地面占据画面下半部分,保留底部能让深度密集区尽量留在视野内。
  • dataloaders/transforms.py是 torchvision 变换风格的定制版(Compose/ToTensor等),把(H, W, C)转成(C, H, W)的张量。

六、自监督关键一步:邻帧采样与 PnP 位姿估计 🧭

训练模式中只要包含photo(光度损失),main.py就会置args.use_pose = True,此时数据管道额外做两件事:

  1. 随机抓邻帧get_rgb_near()从当前帧号 ±3 内随机挑一个存在的近邻帧作为rgb_near,供逆投影做光度对齐。
  2. 无 GT 位姿估计dataloaders/pose_estimator.pyget_pose_pnp()用 SIFT 特征匹配两帧灰度图,再借助当前帧稀疏深度把匹配点反投影为 3D 点(convert_2d_to_3d),最后用cv2.solvePnPRansac解出旋转/平移。为缓解稀疏点覆盖不足,会先对深度图做 4×4 膨胀。

健壮性设计:若 PnP 失败或平移量小于0.1米(说明两帧几乎没动,光度约束无意义),数据加载器会退化为"邻帧 = 当前帧、零位移、单位旋转",保证训练不中断。这套机制让自监督训练完全绕开了 KITTI 的 odometry GT。

七、接入训练:main.py 中的数据流 ⚙️

main.pyKittiDepth('train', args)KittiDepth('val', args)构建数据集,再包进DataLoader(默认 4 个 worker、pin_memory=True)。命令行用--input选择输入组合(d/rgb/rgbd/g/gd),--train-mode选择监督方式:

python main.py --train-mode dense -b 1 --input rgbd # 半稠密标注监督 python main.py --train-mode sparse+photo # 纯自监督 python main.py --evaluate [checkpoint-path] --val select

每个样本最终是一个字典,按需包含rgbd(稀疏深度)、gt(稠密真值)、g(灰度)、r_mat/t_vec(位姿)、rgb_near等键,训练循环里再按--train-mode组合三种损失:深度监督损失(MaskedMSELoss)+ 加权光度损失 + 平滑损失,权重由args.w1/w2控制。

八、常见报错排查清单 ✅

按数据管道出问题的频率排序:

  1. np.max(depth_png)=255, path=...断言失败→ 深度 PNG 被转成了 8 位,请重新从 KITTI 原始包提取,勿经修图软件。
  2. Found 0 images under ...--data-folder(默认../data)下缺少data_depth_velodynedata_depth_annotated,或没跑下载脚本。
  3. Requested sparse depth but none was found--inputd但稀疏深度目录为空,检查是否误删了velodyne_raw
  4. Requested rgb images but none was founddata_rgb未生成,运行download/rgb_train_downloader.shdownload/rgb_val_downloader.sh
  5. Produced different sizes for datasets→ 三类文件数量对不上,通常是部分序列下载失败,重新跑对应下载脚本。
  6. 光度损失异常大/训练不稳→ 检查输出尺寸是否为 352×1216,标定补偿(13 / 11.5 像素)必须与裁剪尺寸匹配。

总结

self-supervised-depth-completion 的数据管道可以用一句话概括:用 glob 对齐"稀疏深度—稠密真值—RGB"三类文件,用P_rect_02内参加裁剪补偿标定相机,用"×256"编码读取 16 位深度 PNG,再用几何/色彩增强与 PnP 邻帧位姿估计,把 KITTI 原始数据喂给光度自监督训练。读懂dataloaders/kitti_loader.py一个文件,基本就掌握了 80% 的数据细节;剩下 20% 在dataloaders/transforms.pydataloaders/pose_estimator.py中。建议对照本文的报错清单逐项检查你的数据目录,跑通训练通常只隔一层窗户纸。

【免费下载链接】self-supervised-depth-completionICRA 2019 "Self-supervised Sparse-to-Dense: Self-supervised Depth Completion from LiDAR and Monocular Camera"项目地址: https://gitcode.com/gh_mirrors/se/self-supervised-depth-completion

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

http://www.cnnetsun.cn/news/4176797.html

相关文章:

  • New API高可用背后的秘密:渠道重试与故障自动禁用机制深度解析
  • FreeRTOS运行一次后卡死
  • 如何给ScrollingStackViewController定制弹性动画:覆盖animate与scrollAnimate闭包的完整指南
  • 炉石HsMod插件:60+功能管换肤、战棋MMR和挂机,Windows 5分钟装好
  • Ditto核心原理(三):motion_stitch缝合网络如何让数字人自然眨眼与表情过渡
  • foreach的隐藏代价:用RoslynClrHeapAllocationAnalyzer揪出引用类型枚举器分配
  • MiroFish群体智能引擎如何快速部署:Docker一键部署与源码安装怎么选
  • 如何把安卓手机投到电脑并直接控制:scrcpy 三步上手
  • 猫抓扩展:网页视频音频一键提取的完整上手指南
  • 深入理解D3.js中的数字格式化工具d3-format
  • 让Claude Scholar从强论文中挖掘知识:paper-miner与kaggle-miner Agent实战
  • SUID3NUM源码解析:一个700行Python脚本如何实现SUID自动提权
  • IP-Adapter-FaceID 人脸一致性出图实战:一张照片到多风格人像
  • iOS悬浮窗通话怎么做?react-native-agora画中画(PiP)完整实现指南
  • Scout-App偏好设置全解析:托盘驻留、声音提醒与桌面通知的3分钟快速配置指南
  • dingo 数据质量评估:给 LLM 训练数据做体检
  • 如何10分钟快速部署Sunshine:从零开始的游戏串流完整指南
  • 如何用LLaMA-Factory微调MiniCPM-o-2_6:全模态模型领域适配完整教程
  • ol-plot 入门使用指南:三步把标绘工具接到 OpenLayers 地图上
  • 浏览器里改暗黑破坏神2存档:用 d2s-editor 快速调属性、导物品的完整指南
  • TrollInstallerX 安装 TrollStore 完整教程:4 步装好,iOS 14.0-16.6.1 通用
  • 快捷键失灵了?3 分钟用 Hotkey Detective 揪出偷走全局热键的进程
  • 3 步跑通 Beyond Compare 5 密钥生成:BCompare_Keygen 零基础上手指南
  • LiteRT-LM视觉能力实战:多模态LLM在树莓派上识别图像完整指南
  • Windows苹果驱动安装完整指南:1分钟让iPhone USB网络共享跑起来
  • 抖音去水印下载完整指南:一条命令保存单个视频或整站主页
  • miqu-1-70b量化版本终极选择指南:q2_K、q4_k_m、q5_K_M三大档深度对比
  • ExplorerPatcher 任务栏属性窗口无法打开:4 层排查阶梯,一文搞定
  • OpenCore Legacy Patcher:老 Mac 升级最新 macOS Sequoia 的完整方法
  • AIMNet2-rxn 局限性与完整解决方案:突破 H/C/N/O 元素限制的化学反应模拟策略