做室内三维视觉、机器人导航和具身智能这几年,Matterport3D 是一个绕不开的名字。很多刚入行的朋友来问我,说想跑个室内场景理解的 baseline,第一反应就是拿这个数据集来试,结果卡在了第一步:数据到底怎么申请、怎么下载、下载之后里面那些文件又都是干嘛的。这篇文章我就把自己实际下载、使用时踩过的坑和沉淀下来的经验完整写一遍,从数据集本身的构成到下载脚本的每一个参数,都尽量讲透,目标是让一个从没接触过 MP3D 的人也能照着操作,顺利把数据跑起来。
Matterport3D 本质上是一套由真实室内场景扫描得到的 3D 重建数据集,它不只是给你一堆照片,而是给了你一个相对完整的室内场景数字孪生:有彩色图像、深度图像、相机位姿、纹理网格模型,还有像素级和模型级的三维语义标注。如果你要做视觉导航、RGB-D 语义分割、三维目标检测、场景理解或者最近特别热的具身智能仿真,这个数据集都是很常见的训练和评测基准。下面我从头到尾拆开讲。
1. 先把 Matterport3D 的价值说清楚
1.1 它不是普通的“室内图片集”
很多人刚接触时会有一个误区,以为这数据集就是一堆室内照片加标签。其实不是。Matterport3D 的每一个场景,都是用专业的 Matterport Pro 3D 相机在真实建筑里扫描出来的,扫描之后算法会把这些照片和深度数据重建为一个完整的三维网格模型。所以你拿到的不是一个平面视角,而是一个可以在任何位置、任何角度观察的室内空间。
为什么这一点重要?因为你的下游任务如果是“让机器人在房间里走”,那纯 2D 图片训练出来的模型很难迁移到真实世界。MP3D 里每张图像都有对应的相机内参、外参、深度值和三维空间结构,你能复现出“相机在这个位置能看到什么”的完整物理过程。这也是它在视觉导航任务里被 Habitat、AI2-THOR 这些仿真平台广泛使用的原因。
如果你之前只跑过 COCO、VOC 这类自然图像数据集,第一次打开 MP3D 会有点不习惯:它更像是一组带完整相机轨迹和三维几何的“场景”,而不是一张张独立的图。你需要用相机位姿把图像串起来理解,很多算法(比如 NeRF 类的三维重建方法、视觉 SLAM 评估)都能直接在这上面做实验。
1.2 90 个场景、近二十万张图像,到底是个什么量级
MP3D 官方公开的数据是 90 个室内建筑场景,共计约 10800 个全景图,再从中切出约 194400 张 RGB-D 图像。这里说的“RGB-D”是指同一视角下同时有彩色图和深度图,深度图的每个像素值代表相机到物体的距离,单位通常是毫米。虽然放到今天看,这个数据量跟互联网规模的图文数据集没法比,但它的价值在于每张图都带着真实三维几何和精确位姿,这是纯图片数据集很难提供的。
这 90 个场景涵盖了很多空间类型:公寓、住宅、教堂、办公室、会议室、楼梯间等等,每个场景的命名是一串随机哈希字符,比如 17DRP5sb8fy、5LpN3gDmH7P 这种。它不像 ImageNet 那样有整齐的类别组织,你需要通过配套的 house 文件来理解每个场景里有什么房间、房间之间怎么连接、相机在哪些位置采集过数据。
这也就引出它的一个特点:这个数据集的“粒度”是场景,不是单张样本。你下载一个场景,得到的是这个场景里所有相机位姿下的图像、深度和对应的三维模型。训练的时候,一般需要把场景分成 train / val / test 三部分,官方也提供了标准的划分方式,方便大家跑出来的结果能互相比较。
1.3 它到底解决了什么问题
我们做室内视觉任务,最头疼的问题就是真实数据和真实标注不好获取。你真拿一台带深度传感器的设备去扫办公室,光设备门槛就挡住了很多人,更不用说还需要把每一帧图像里的沙发、桌子、墙壁逐像素标出来——这个成本高到离谱。Matterport3D 相当于把这些脏活累活都替你做了,而且做得比较完整。
具体来说,它同时支持这么几类任务:一个是 2D 语义分割,在每张 RGB-D 图像上做像素级分类;一个是 3D 语义分割,直接在网格模型的每个顶点或每个面片上做分类;还有三维目标检测和实例分割,在场景里定位每一个物体;再往上是视觉导航、SLAM(同步定位与建图)、场景理解、布局估计等等。这也是为什么它被引用了那么多次,很多论文在实验部分都会用 MP3D 验证自己的泛化能力。
2. 数据里面到底装着什么
2.1 下载之后你会看到的目录结构
我第一次下载完,解压之后看到几十个子文件夹,心里是有点懵的。后来摸清楚了,每个场景的目录结构大体上是这样:
17DRP5sb8fy/ ├── camera_parameters/ ├── color/ ├── depth/ ├── house.json ├── house.seg.json ├── matterport_metadata/ ├── mesh/ ├── region_segment/ ├── semantic/ ├── instance/ └── undistorted/这里我列的是一份比较常见且完整的场景目录。实际下载时,你可以通过下载脚本的--type参数只挑自己需要的类别下载,不用每次都全量拉下来。这算是一个官方设计得很贴心的点,后面下载环节我会详细说。
其中color/和depth/是最直观的,一个放彩色图,一个放深度图。camera_parameters/里是每张图对应的相机内参、外参、位姿等数据,格式一般是 json 或者 conf 文件。mesh/里放的是这个场景的三维网格模型,格式是 OBJ,可以用 MeshLab、Blender 这类工具打开。house.json是整个场景的结构描述,包括房间划分、物体实例、相机轨迹等,是理解场景的一把钥匙。
2.2 彩色图、深度图和相机参数的具体含义
color/目录下是原始采集图像,undistorted/里存放的是畸变矫正后的图像。为什么会有两套?因为原始相机镜头存在畸变,直接拿来训练或者做三维重建,如果不做矫正,投影关系会对不上。官方贴心地提供了矫正版本。不过在使用习惯上,我接触到的不少开源代码直接使用的是undistorted版本,因为处理起来不用再额外调用去畸变流程。
depth/和undistorted/depth/对应存放深度图。深度图一般是 16 位 PNG,像素值直接代表距离,单位通常为毫米,这个“单位”很关键。有人下载完直接当成 0~255 的单通道灰度图去显示,结果一片黑,就是没有把单位换算对。换算也很简单:深度值除以 1000 就得到以米为单位的距离。做训练数据预处理时,还需要对深度图做有效性检查,因为传感器在某些透明物体、镜面或者远处表面会生成无效深度值,一般会用 0 表示。
camera_parameters/里的信息要稍微花点心思。每一张图对应一组相机参数,通常包括分辨率、内参矩阵(焦距、主点)、外参矩阵(相机在世界坐标系下的位置和朝向)。很多开源代码读取 MP3D 数据时会自己写一套 parser,你如果只用现成框架,也许不用手动去解析这些文件,但理解它们还是很重要,因为不管是做三维投影、生成俯视图还是训练导航策略,最终都要落到相机位姿上。
2.3 标注体系:从房间到物体,细到什么程度
MP3D 的标注是它的一大卖点。每个场景的house.json里记录了从大到小的层级信息:首先是整个场景的空间范围,然后划分出一个个 region,也就是房间区域;每个房间里再标出其中的物体,包括类别、三维包围盒、二维多边形轮廓等。原始标注的语义类别约 21 类,包含墙体、地板、门、窗、沙发、床、桌子、椅子、电器这些室内常见的物体类别。实际使用时,不同任务可能还会做标签映射,比如把“冰箱”“烤箱”“微波炉”合并成“厨房电器”类。
在做三维语义分割时,你通常需要用到region_segment/、semantic/和instance/这些目录,它们分别存放区域划分、语义分割结果和实例分割结果。注意这些标注可能是同时挂到 2D 图像和 3D 网格上的,你需要根据任务选择对应的读取方式。比如你要做 2D 语义分割,通常会以color/下图像编号为索引,把semantic/下同编号的像素级标签图作为 ground truth;你要做 3D 分割,则需要把标签映射到mesh/的顶点或面片上。
这里还必须提一下house.seg.json。这个文件把“点云/网格分割”和“语义标签”关联起来,记录每个三维分割区域的类别。如果你的项目要做三维实例分割,这个文件基本就是核心标注。顺便提醒一句,这些 json 文件都比较大,结构嵌套也很深,建议用 jq 工具或者写个小脚本先浏览一下,别直接用文本编辑器硬开,容易卡死。
3. 完整下载流程:从申请到跑通脚本
3.1 申请权限前必须知道的事
Matterport3D 不是一个完全开放随便下的数据集。官方要求你先填写申请表格,说明机构、用途,并同意它的条款,条款核心就是“非商业用途、仅限研究”。一般用学校或者研究机构的邮箱申请会比较容易过审。我当时用的单位邮箱,填完表格大概等了两个工作日就收到了回复,回复邮件里会附上一串下载密钥。
这里有几个容易被忽略的细节,我直接列出来:
- 申请页面和下载脚本在官方的 GitHub 仓库里有详细说明,仓库名就叫 Matterport3D。申请链接就是从这个仓库的 README 里进入的。
- 申请时填写的姓名和邮箱,最好和之后下载脚本、发表论文时署名的信息一致,不对应也可能通过,但没必要给自己找麻烦。
- 密钥一定要收好,它相当于你下载数据的凭证。官方协议里明确不允许二次分发数据,如果你把数据传给别人被发现了,可能影响整个实验室的后续申请。
- 有些场景数据因为采集自私人住宅,申请时可能会有额外的访问限制,这在官方提供的场景列表里面会标注。
填完表格之后,剩下的就是等待。如果长期没收到邮件,先去垃圾箱里找一圈,有时候自动回复和下载密钥会被邮件服务器误判为垃圾邮件。实在不行,等一周后再申请一次,但不要反复刷,别把你的申请当成自动化攻击。
3.2 一步不落地跑通下载脚本
拿到下载密钥之后,接下来就是用官方脚本下载。第一步,把官方仓库克隆到本地:
git clone https://github.com/niessner/Matterport3D cd Matterport3D仓库里有两个下载脚本,分别是download_mp3d.py和download_mp3d_metadata.py,前者负责下载主要数据,后者负责下载元数据。脚本是用 Python 写的,依赖的第三方库不多,实测在 Python 3 环境里也能跑,不过官方 README 写的是 Python 2,所以如果你用的机器是 Python 3 且遇到奇怪的报错,优先检查编码和依赖版本。
基本用法是这样的:
python download_mp3d.py -o /path/to/output -p "你的下载密钥" -i 17DRP5sb8fy参数说明:
-o:指定输出目录,下载好的场景文件夹会放在这个目录下。-p:申请通过后邮件里给的下载密钥。-i:场景 ID,可以只指定一个场景,也可以用逗号分隔指定多个。
还有个很常用的参数是--type,它可以控制下载哪些数据类别。打个比方,你只是跑 2D 语义分割,那只需要color、depth、semantic、instance这些就够了,没必要把沉重的mesh也拉下来。你可以这样拼:
python download_mp3d.py -o ./mp3d -p "你的下载密钥" -i 17DRP5sb8fy --type color,undistorted,depth,undistorted_depth,semantic,instance,segment,region,camera_parameters如果你的目的是做三维重建或者视觉导航,那需要把mesh也加上。这里注意,不同版本脚本支持的 type 名称可能有点差异,比如有的是undistorted_depth,有的是undistorted/depth。我建议你在下载之前先跑一遍不带-i的脚本或者看下仓库 README,确认参数名是否正确。
全量的 MP3D 数据相当庞大,我印象里整个数据集解压后的体积是 TB 级别。这不是开玩笑。如果你的磁盘不够大,强烈建议先只下载一个场景。一个场景全类型下来大概几十 GB,只下 RGB-D 和相机参数会小很多,大概几 GB 到十几 GB。先拿一个场景跑通全流程,确认数据格式没问题,再决定要不要下全量。这个习惯能帮你省下大量时间和磁盘空间。
3.3 硬盘、速度和断点续传的预算建议
先说结论:如果你计划跑完整 MP3D 上的实验,一块 4TB 的机械硬盘是最低配置,固态硬盘容量太紧张的话就别硬撑了。我们实验室当时主要下 RGB-D 图、相机参数、语义标注和部分网格,就用了接近 1TB 的空间。如果你还想把每个场景的 mesh 和全景图都拉下来,那几乎是把整个数据集完整下载下来,对网络和硬盘都是不小的考验。
下载速度方面,MP3D 的文件托管在官方服务器上,没有国内镜像,速度完全取决于你到对方服务器的链路质量。不同时段、不同网络表现差异很大,有快有慢,下了几天都正常。官方脚本本身支持断点续传,如果你手动中断了下载,重新跑一遍相同命令一般会接着下,但你最好观察一下日志输出,确认它是“跳过已存在文件”而不是“重新下载”。
我建议你在正式开始全量下载前先做一个小测试:用一个场景跑一段下载脚本,看看速度和稳定性。如果老是中途断连,可以分多次指定不同场景慢慢下,这样即便失败也只需要重下某个场景。下载过程中要时刻留意磁盘剩余空间,别把系统盘塞满。正因为文件多、体积大,下载完成之后还要花时间校验和整理,这一块我在后面会详细讲。
4. 高频问题排查与避坑心得
4.1 申请和下载阶段最容易踩的坑
申请阶段最常遇到的问题就是迟迟收不到密钥。除了检查垃圾箱、确认邮箱正确,我还遇到过有的机构邮箱把外部邮件默认拒收的情况,这种情况只能换一个邮箱申请。如果你用 QQ 邮箱、163 邮箱这类个人邮箱,过审概率也不是说一定不行,但为了减少麻烦,建议优先用学校或研究单位的邮箱。
下载阶段第一个坑是密钥带了多余的空格或者换行。有时候从邮件里复制密钥,会把前面的Bearer或者末尾的换行一起复制进去,脚本就会验证失败。建议把密钥放到一个文本文件里,读取时用 strip 去掉首尾空白,或者在命令行里仔细检查一下粘贴内容。
第二个坑是场景 ID 写错。MP3D 的场景 ID 都是一长串大小写混合的哈希,手输很容易出错,大小写还敏感。最稳妥的办法是从官方提供的场景列表文件里直接复制,不要手敲。还有就是确认你申请时选择的场景跟你要下载的场景是否一致——如果某个场景的数据需要额外授权,你在命令行里指定了它,脚本会在日志里提示无权访问。
第三个坑是磁盘空间误判。有些文件类型你以为很小,其实很大。比如mesh目录里的纹理网格文件,一个场景动辄几个 GB 甚至更大;matterport_metadata里存的是扫描设备的原始元数据,有时候比图像还占空间。建议用du -sh随时查看场景目录大小,心里有个谱。
4.2 下载完成后的数据校验清单
你辛辛苦苦把几百 GB 下载完,结果解压、训练时才发现文件损坏,那才是最崩溃的时刻。所以下载完成后,我强烈建议你做一遍简单校验,下面是我自己习惯用的步骤:
- 查看目录结构是否完整,对照 README 里的文件清单,确认
color/、depth/、camera_parameters/、house.json这些核心文件都在。 - 用
find命令找出大小为 0 的文件:
find /path/to/mp3d -type f -size 0如果有输出,说明有文件没下完整,需要重下。 3. 抽查几张深度图是否能正常打开,确认不是全黑或者全白。可以用 Python 的 Pillow 库读一下:
from PIL import Image img = Image.open("depth/000000.png") print(img.size, img.mode)正常应该输出(1024, 1280)左右的分辨率,模式是I;16这类 16 位深度模式。 4. 如果下载了 mesh,用 MeshLab 或者 trimesh 加载一下 OBJ 文件,确认网格模型可以正常打开,材质和纹理文件路径没有丢失。
这里再提醒一句:原始项目托管环境中,部分场景可能存在少量标注瑕疵,比如某个物体没有语义标签、深度图空洞偏多等。做实验之前,可以先去官方 GitHub 的 issue 和项目主页看看有没有已知问题列表,省得自己瞎猜。
4.3 后续使用和二次开发的几个建议
数据下载好之后,接下来就是怎么用了。很多人会直接开始写 dataloader,但 MP3D 的数据组织方式是“场景中心”的,不太好像 COCO 那样简单地返回 image-label pair。我建议你写一个轻量级的场景级索引工具,核心是读取house.json,把每个相机位姿、图像路径、深度路径、标注路径对应起来,然后按需生成训练样本。这一步做完,后面再怎么跑实验都顺手。
如果你的主要方向是导航或者具身智能,可以考虑不自己啃原始数据,而是直接用 Habitat 这类平台。Habitat 背后就用到了 MP3D 的场景,它帮你把加载、渲染、物理交互都封装好了。但底层原理还是那些:读网格、放置 agent、给定相机位姿渲染 RGB-D。你自己能解析 MP3D,对理解这些平台的工作方式很有帮助。
还有一个容易忽略的问题:MP3D 的网格模型是基于真实扫描的,可能包含很多扫描噪声,比如边缘不完整、小物体粘连、玻璃区域出现空洞等。做仿真训练时,如果你直接拿原始 mesh 做碰撞检测,agent 可能会卡在一些奇怪的位置。这时候可以对 mesh 做简化、清理和碰撞体生成。很多开源项目里也提供了现成的处理脚本,但你要明白为什么要做这一步,不然出了问题只会被报错搞得一头雾水。
我在实际使用中发现,第一轮跑通的人都有一个共同特征:不会一上来就追求“全量”。先把一个场景的数据下载、解析、可视化跑通,再扩展到更多场景,这是最稳妥的路径。MP3D 的学习曲线其实是有点陡的,但你把house.json的结构和图像、深度、位姿这四类核心数据之间的关系理清楚之后,后面再用其他三维数据集,基本都能触类旁通。最后再分享一个小技巧:下载到本地后,可以为每个场景准备一个README.txt,记录下载时间、数据版本、用途、当时用的下载命令。别嫌麻烦,等你在三个月后要复现某个实验时,这些记录能省下大量回忆时间。