news 2026/9/8 1:33:50

Mapillary街道级序列数据集:构建跨区域视觉定位与SLAM评测的完整指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Mapillary街道级序列数据集:构建跨区域视觉定位与SLAM评测的完整指南

简介:Mapillary街道级序列(MSLS)是面向长期位置识别的大规模街道级图像数据集,涵盖160万张图像,可为计算机视觉研究者提供外观变化下的训练与评测基准。压缩包共20个文件,以9个Python脚本为主,涵盖数据加载器、评估脚本和模型训练逻辑,另含4个CSV预测结果样例、3个Markdown说明、1个Jupyter Notebook演示及配置文件等,整体仅2.21MB,轻量便于快速上手。目前已有664人学习使用。数据集按序列组织,便于评估跨时间、跨场景的外观鲁棒性。资源中内置PyTorch数据加载器,支持数据库/查询图像评估与三元组训练两种模式;独立的评估脚本可直接读取文本预测并输出指标,配合示例CSV可复现论文中基于ResNet50骨干与广义均值层的基线结果,适合刚接触位置识别的读者快速搭建实验流程,也可作为基础代码拓展新的训练策略。 去年我在跑跨区域视觉定位实验时,卡在一个非常现实的问题上:KITTI 跑熟了就那么几条固定路线,nuScenes 的传感器套件贵得离谱,Oxford RobotCar 虽然序列长但同样被限定在单一城市和固定场景。想验证算法在“真实世界到底行不行”,手上却没有一套既免费、又覆盖多区域、还带完整连续帧信息的数据集。后来我把目标转向 Mapillary——这个众包街景平台汇集了全球大量贡献者用手机、行车记录仪和全景相机拍下的海量图像,而且每条拍摄轨迹天然就是一个序列。围绕它我做了一套名为 mapillary_sls(Mapillary Street-Level Sequence,枫叶街道级序列数据集)的整理管线,把零散的众包图像变成了可以直接喂给视觉定位、SLAM 和地点识别任务的序列数据。这篇文章把我从踩坑到跑通的完整过程写出来,包括数据源摸底、筛选链路、对齐清洗和实测效果,给准备自己做数据集的同学一条能直接参考的路线。

1. 为什么偏要折腾一套街道级序列数据集

1.1 现有基准数据集在序列任务上的三个尴尬

先说痛点。做视觉定位或者序列匹配这类任务,理想数据集至少得满足三个条件:一是覆盖足够多样化的街道路网,不是来回几条环路;二是每段轨迹必须有严格的连续帧关系,帧与帧之间的位姿变化是可知的;三是数据获取成本不能高到普通实验室承受不起。

但市面上的数据集总有短板。KITTI 和 Cityscapes 覆盖面窄、路线固定,长期用来做评测很容易出现“在训练集上调参”的假象。Oxford RobotCar 确实提供了长达一年的重复轨迹采集,但传感器套件和车辆成本摆在那里,普通人不可能复刻。nuScenes 更不用说了,毫米波雷达加激光雷达加多相机整套下来,不是一般团队能碰的。更要命的是,这些数据集的时间跨度和天气变化基本是预设好的,一旦你的算法要应对“真实世界里毫无规律的光照和季节”,泛化能力根本测不出来。

1.2 Mapillary 这条众包路径的独特杠杆

Mapillary 和以上数据集最大的区别是数据来源:它不靠专用采集车,而是靠全球无数贡献者日常拍摄积累。有人在车里装行车记录仪,有人拿手机边走边拍,还有人用 GoPro 类运动相机扫街。平台会把同一条轨迹的图像聚合成一个序列,时间戳、GPS 轨迹、朝向信息、相机参数等元数据一应俱全。截至我整理数据的阶段,平台上的图像规模已经达到十亿级,覆盖的城市数量远超任何单一采集项目。

这个规模意味着什么?意味着你不用再守着某一条固定路线去验证算法,而是可以按区域、城市甚至国家去切分训练集和测试集,真正做到跨场景评估。对于做视觉地点识别(VPR)和视觉重定位的团队来说,这种数据源几乎是免费的富矿。我在构建 mapillary_sls 之前先跑了一批小样,随手挑了三座不同风格的城市,序列的街道类型、建筑立面、植被密度和光照条件差异非常明显,这比以往数据集里“换条街换个建筑”的弱变化强太多了。

1.3 命名含义与数据集的定位

数据集代号叫“枫叶”,没有太复杂的含义。我一开始只是觉得这片叶子的脉络形象很适合描述“一条条轨迹像叶脉一样延伸”的序列结构,后来沿用下来。mapillary_sls 的定位不是单纯把 Mapillary 的图片打包成一个静态图像集,而是把原始图像库加工成一套带轨迹、带时序、带位姿关系的可用序列数据。换句话说,它的价值不在单帧图像本身,而在帧与帧之间的连续性。

这个定位决定了后续所有处理动作的出发点:凡是破坏连续性的数据,哪怕单帧质量再好也要丢弃;凡是能让序列关系更稳定的信息,哪怕需要额外计算量也要尽量保留。

2. Mapillary 数据源摸底:众包采集的机遇和麻烦

2.1 一个序列到底长什么样

在动手写脚本之前,我建议你先去 Mapillary 的 API 文档里弄清楚数据结构的底层逻辑。简单来说,Mapillary 会为每一次连续拍摄生成一个sequence_id,这个 ID 下面挂着一串图像,每张图像都带有captured_at时间戳、经纬度坐标、朝向角compass_angle,部分图像还包含相机内参和是否全景的标记。

序列的长度差异非常大。有人开车连续拍了二十分钟,一个序列里可能有大几百帧;有人只是步行穿过一条街,序列只有二三十帧。所以拿到原始序列后,第一件事就是摸底统计:序列帧数分布、轨迹总长分布、GPS 有效点比例、时间戳完整性。我把首批拉取的 10 万帧数据做了统计,发现约三成序列的有效轨迹长度不足 30 米,还有一成左右存在时间戳空值。这些统计结果直接决定了后面的筛选阈值该怎么定。

2.2 众包设备的参差不齐是双刃剑

众包采集最大的优势是多样性,最大的坑也是多样性。有的贡献者用专业全景相机,内参和姿态数据非常规范;有的贡献者就是手机随手拍,EXIF 信息里可能只有经纬度和时间,连镜头焦距都不全。后者在构建序列时麻烦很大,尤其是做视觉几何计算时,相机内参缺失会直接导致重投影和三角化出问题。

我的做法是分两级处理:优先保留有完整相机参数的图像,这部分用于几何相关的任务;内参缺失的序列也不直接扔掉,而是统一用针孔模型加估计的水平视场角做粗略标定,用于对相机精度要求不高的任务(比如基于特征的视觉地点识别)。实测下来,这种分级保留策略让最终数据集的可用帧数量增加了约四成。

2.3 许可以及隐私问题必须提前处理

Mapillary 上的图像数据遵循开放地图类许可协议,使用前要仔细阅读平台的授权条款,确认是否符合自己的用途。这里特别提醒一点:如果你的数据集后续要开源或者用于商业项目,许可问题是绕不开的法律关卡,不是在代码里加个引用就万事大吉。我在整理 mapillary_sls 时专门保留了一份 README,逐条记录了数据来源和授权说明。

隐私方面,Mapillary 平台本身已经对车牌和人脸做了自动模糊处理,这部分工作不需要我们重复做。但从实际拉取的数据来看,平台的处理偶尔会有遗漏,尤其是角度比较奇怪的车牌。如果你要把数据集公开,建议加一道自动检测和手动检查的流程。这不是技术问题,但一旦出事比任何技术问题都麻烦。

3. 从海量图库里筛出可用轨迹:完整筛选链路

3.1 格网采样先划定范围

Mapillary 全球数据量太大,不可能一股脑全部拉下来处理。我的做法是用格网采样划定目标区域:把地图按经纬度切成 (0.01° \times 0.01°) 的格子(大概一公里见方),然后按城市或区域选取目标格网,在格网内请求序列列表。

这一步看似简单,但格网大小直接决定了后续数据分布。格子太大,市中心和郊区的轨迹混在一起,很难控制场景多样性;格子太小,单个格网内的有效序列太少,请求次数爆炸。实测下来,一公里见方对城区街道数据比较合适,既能保证一个格网内有足够的序列,又能通过选择不相邻的格网显著提升场景差异。

3.2 轨迹连续性检验:把断裂的序列切出来

Mapillary 的序列虽然天然连续,但我在实际使用中发现两个常见问题:一是拍摄者中途停车或设备休眠,导致同一序列内出现长时间的时间间隔;二是上传时丢帧,物理上连续的轨迹在数据上却少了一段。

我用两个指标做连续性检验。第一是时间间隔,相邻两帧时间戳之差超过十秒就视为断点,从断点处把序列切成两段独立子序列;第二是空间跳变,相邻两帧 GPS 距离除以时间差得到的瞬时速度如果超过 80km/h,说明要么 GPS 漂移要么轨迹确实断了。这样处理之后,一个原始序列往往能拆出两个甚至三个干净的子序列。宁可让序列变短,也不能让序列内部出现不可信的位姿变化。

3.3 模糊帧和重复帧过滤:质量兜底

序列筛选不能只看轨迹几何,图像质量同样关键。众包拍摄里常见的模糊帧主要来自快速转动手机、车辆颠簸和夜间长曝光。我用拉普拉斯算子的方差来做模糊检测:先把图像归一化到统一分辨率,再计算灰度图的拉普拉斯方差,低于阈值就判定为模糊。具体阈值需要根据你的图像分辨率调整,我这边在 512 宽度的归一化尺度下取的是 80,低于这个值的帧基本是肉眼可感知的模糊。

重复帧的问题主要出现在低速行驶或等红绿灯场景,车辆不动,但系统仍然以固定频率出图,导致连续十几帧几乎完全一致。这个坑用感知哈希就能解决:对每帧图像计算 dHash,再和前一帧比较汉明距离,距离小于 10 就视为重复帧,从序列中剔除。要注意的是,重复帧剔除后一定会产生新的时间间隔,所以要把这一道工序放在连续性检验之前,剔除后再跑一遍断点切分。

3.4 序列去冗余:保证时空采样均匀

经过前几步筛选之后,序列基本连续可用了,但还有一个问题:有些路段被不同贡献者反复拍摄,而另一些路段几乎没有覆盖。这种不均匀会严重影响训练和评测的公平性。我采用按空间去冗余的策略:把目标区域内的轨迹投影到二维格网上,每个格网内最多保留数条轨迹,优先保留轨迹长度较长、时间戳跨度较大、图像分辨率较高的序列。

这一步做完,数据集的“地图覆盖均匀度”会有肉眼可见的提升。后来我在做跨区域检索实验时,明显感觉到训练集和测试集之间不再因为区域分布不均而产生虚假的性能波动。

4. 目录结构、时间戳与坐标系对齐

4.1 一期数据集的目录设计

数据筛选完之后,最重要的事情就是设计一套清晰、可扩展的目录结构。mapillary_sls 一期版本的目录组织如下:

mapillary_sls/ README.md data/ seq_0001/ images/ 000000.jpg 000001.jpg ... poses.txt timestamps.txt calibration.json seq_0002/ ... splits/ train.txt val.txt test.txt

这里有几个细节值得说明。首先,序列 ID 我重新进行了连续编号,不再沿用 Mapillary 原始的字符串 ID,避免后续脚本处理时需要处理长字符串。其次,每个序列独立保存poses.txttimestamps.txt两个文本文件,前者是每帧的位姿,后者是对应的采集时间,这样训练时可以直接逐行读取,不需要解析 JSON。

calibration.json单独存放相机内参的另一个原因是,同一序列内可能出现不同设备拍摄的混合情况,内参并不唯一,这种情况下我会在文件里列出多个 camera_id 对应的参数,并在poses.txt里增加一列指明每帧使用的相机。

4.2 GPS 坐标到局部坐标系的转换

Mapillary 提供的是 WGS84 经纬度坐标,直接拿来做视觉几何计算非常不方便。我使用 UTM 投影把经纬度转换为平面坐标,然后以每个序列的第一帧位置为原点建立局部坐标系。这样每个序列内部的位姿就变成了一个独立的局部坐标,便于做视觉定位和 SLAM 的输入。

转换本身用pyproj库就能实现,几行代码的事。但有一个坑要注意:同一序列跨越 UTM 分带边界时,直接投影会导致坐标跳变。这种情况虽然少见,但一旦出现,序列末尾的几十帧坐标会整体偏移。我加了一道检测:序列内 UTM 坐标的 x 方向跨度过大或者出现明显不连续跳变时,就标记为异常序列,人工进一步确认。

4.3 时间戳对齐与 GPS 平滑

时间戳对齐是序列任务里最容易翻车的环节。Mapillary 的元数据里带有captured_at毫秒时间戳,但有一个不太起眼的坑:部分图像文件自身的 EXIF 拍摄时间和元数据里的时间不一致,相差从几秒到几分钟都有可能。

我在处理管线里加入了一层交叉校验。每下载一张图像,就读取它的 EXIF 时间,和元数据时间戳做差。差值超过一秒的图像数量占整个序列的比例过高时,说明这个序列的元数据不可靠,直接弃用;只有少量帧不一致时,以元数据时间为准,但在timestamps.txt里做合理插值补齐。

GPS 平滑方面,众包采集的 GPS 在城市峡谷里有明显的多径效应,轨迹会出现锯齿状抖动甚至瞬移。我在筛选阶段用速度阈值剔除了瞬移帧,但对剩余的锯齿抖动,用滑动窗口的中值滤波把轨迹修平滑。注意这里用中值滤波而不是均值滤波,均值滤波会把尖锐的真实转弯也抹掉,中值滤波对孤立的离群点更有效,同时保留几何特征。

5. 在真实任务上跑出来的效果

5.1 视觉地点识别:序列约束带来的增益

数据集的终极检验是放进真实任务里跑。我先把 mapillary_sls 切成城市级训练集和测试集,然后跑了一个目前比较经典的视觉地点识别模型 NetVLAD,基础配置保持论文原样,只把输入换成本数据集的图像序列。

单帧检索的结果说实话不算惊艳,跨季节和跨光照场景下 top-1 检索精度明显下滑,这符合预期。但当我加上序列约束后,效果立刻不一样了:用相邻两帧的 top-10 候选做投票,top-1 准确率比单帧直接提升了不少。原因很好理解,单帧图像在大光照变化下视觉特征不稳定,但连续帧之间存在明显的地理约束,投票机制把错误帧筛掉了。

这也说明一个更底层的问题:mapillary_sls 的价值不仅仅在于“多”,而在于它保留了真实的连续关系,让序列级的算法有机会发挥。如果你做的是单帧图像检索,用这套数据也能跑,但真正吃透它红利的一定是序列级方法。

5.2 视觉重定位:初始 GPS 噪声的真实挑战

在视觉重定位任务上,我用了一个传统的 2D-3D 匹配管线:给定一张查询图像,先用全局描述子检索出候选参考帧,然后做特征匹配和 PnP 求解。真实场景里查询帧的初始位置来自 GPS,误差少则三五米,多则十几米。mapillary_sls 里的众包 GPS 数据正好复现了这种真实噪声。

跑下来的体会是,GPS 噪声较大时单帧重定位的失败率比较明显,但一旦把连续三帧的 PnP 结果做 bundle 优化,成功率提升显著。这说明在众包数据上,序列间的几何一致性比单帧特征质量更能兜底。

5.3 SLAM 里程计评估:传感器噪声更接近量产场景

我还把部分序列喂给了单目 ORB-SLAM3 做里程计评估。和 KITTI 上丝滑的表现不同,这套数据集上的跟踪丢失明显更多,主要原因是图像分辨率不一致、运动速度变化大、光照条件恶劣。乍看是劣势,但换个角度想,这正是量产级视觉 SLAM 的真实工作环境。

对于做鲁棒 SLAM 的团队来说,mapillary_sls 的这批噪声反而比精心标定的数据集更有评测价值。如果你的系统在这种数据集上能保持较低的丢失率,在真实产品里的表现大概率更有保障。

6. 文档里不会写的事故现场

6.1 时间戳跳变与相机内参缺失的连锁反应

第一个让我折腾了一个周末的坑是时间戳跳变。某个序列用筛选脚本检测时一切正常,但送入 SLAM 系统后轨迹突然跳了一大截。排查了半天才发现,这个序列的元数据里有一帧的captured_at比前后帧晚了整整四分钟,肉眼检查时完全看不出来,因为它没有导致轨迹断裂,只是时间轴上出现了一个孤立异常值。

这种孤立异常用速度阈值是查不出来的,因为速度计算用的是距离除以时间差,时间被放大后速度反而变得“正常”了。我后来在时间戳处理里加了一步:把相邻时间差做排序,发现某个时间差超过该序列中位数的数倍时,就把它标记为异常帧并剔除以一帧为单位,而不是把整个序列切断。这个教训是:任何指标在用于筛选之前,都要先想一想它会不会被另一个异常值“中和”掉。

6.2 大批量下载时的断线与续传

Mapillary 的图像下载并不复杂,但数据量一大必然遇到网络中断和限流。一开始我用单线程循环下载,结果跑到一半断开,已经下载的文件不会自动跳过,重新跑一遍又要浪费几个小时。

后来我写了一个带断点续传的脚本,核心逻辑很简单:下载前先检查本地文件是否存在且大小非零,如果存在就直接跳过;每下载一个序列就更新一个进度文件,重启后从进度文件恢复。不要小看这个粗糙的方案,它节省的时间远超写脚本的成本。另外一个更隐蔽的问题是,有些图片请求返回的是重定向链接,直接保存重定向响应会得到 HTML 而不是图片,这里一定要检查响应头和文件魔数。

6.3 城市峡谷 GPS 漂移的诡异表现

城市里高楼密集区域,GPS 漂移的形态比教科书描述的复杂得多。有一个序列明明是在一条直路上行驶,但轨迹图上出现了两三米宽的锯齿形抖动,看起来像蛇一样在路中间扭动。中值滤波对这种抖动有一定抑制作用,但滤波窗口不能开太大,否则会把道路转弯处的几何特征抹平。

我最后的折中方案是两步走:先用速度阈值剔除明显的瞬移点,再用窗口大小为七的中值滤波平滑残余抖动。窗口七是在几个序列上实测后的取法,太短没效果,太长转弯处会出现明显“切割感”。这种调参经验很难从文档里学到,只能靠一个序列一个序列地看效果。

6.4 不要迷信覆盖量

最后一条经验是心态层面的:不要见了 Mapillary 的十亿级图像规模就兴奋,以为自己能建一个覆盖全球的超级数据集。实际处理下来,真正能通过连续性检验、质量过滤、去重和许可确认的数据,不到原始数据量的零头。更现实的做法是锁定几个目标城市,把每个城市的序列质量做扎实。我一度试图同时处理二十个城市的数据,结果每个城市都只做了七八成,还得回头补工。后来老老实实一次只做三个城市,每个都完整跑完评测再切下一批,反而整体进度更快。

这个数据集到现在已经迭代了好几版,后续我打算把多季节重复访问的序列单独切出来,做一套针对跨季节鲁棒性的评测集。如果你正在为视觉定位或地点识别任务缺数据发愁,Mapillary 这套路线值得试一次,别被前期的清洗工作吓退,那些坑趟平之后,你就会发现众包数据的大规模性和真实性,是实验室采集完全给不了的。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/8 1:30:35

Mac上使用Homebrew安装与管理pnpm的完整指南

1. Mac 安装 Homebrew 完整指南Homebrew 是 macOS 上最受欢迎的包管理器,它让安装、更新和管理软件变得异常简单。作为一名长期使用 Mac 的开发人员,我几乎每天都会用到 brew 命令。下面分享我在不同网络环境下安装 Homebrew 的经验,包括国内…

作者头像 李华
网站建设 2026/9/8 1:28:40

标签打印机二次开发包对接实战:从指令协议到C#调用完整指南

简介:2200E标签打印机二次开发包V2.072面向需要集成标签打印功能的软件开发人员,提供整套DLL动态库、API接口、示例工程与帮助文档,帮助快速实现标签设计、打印参数配置及二维码/DataMatrix码输出。包内共133个文件,以DLL、EXE、B…

作者头像 李华
网站建设 2026/9/8 1:27:47

Python环境搭建全指南:从零配置解释器、pip与VSCode

我见过太多零基础的人,学Python的第一天就放弃了。不是因为语法看不懂,也不是因为逻辑绕不过来,而是卡在环境搭建上——下载完安装包、双击、下一步、下一步,满怀期待地打开终端敲下一行python,结果屏幕甩回来一句“不…

作者头像 李华
网站建设 2026/9/8 1:26:16

金融荐股服务时效性分析与优化策略

1. 现象观察:金融荐股服务的时效性困境最近在跟踪几家主流证券咨询机构的服务时,发现一个有趣的现象:和众汇富的研究报告质量尚可,但荐股时点总是比市场反应慢上一拍。他们的每日研究手记确实"量大管饱",动辄…

作者头像 李华
网站建设 2026/9/8 1:25:11

STM32CubeMX+LWIP UDP客户端实战:从CubeMX配置到代码调试全解析

简介:面向STM32嵌入式开发者的LWIP联网实验资源,基于STM32CubeMX与STM32CubeIDE环境,实现UDP客户端功能。资源记录了作者反复调试才跑通的完整过程,核心是一个可供参考的回显程序:PC端先建立UDP服务器,开发…

作者头像 李华