map_tutorial
第 10 章:从三维到街景——采集流程与 Street View API
导航:返回目录
上一章:从 nadir 到三维
下一章:室内地图构建与 BIM 融合
1. 开篇段落:从“上帝视角”回归“人类视角”
在前几章中,我们构建了数字地球的骨架:卫星影像提供了宏观的地表覆盖,DEM 赋予了地形起伏,倾斜摄影模型重建了城市的立体轮廓。然而,这些数据都有一个共同的局限——它们都是俯视的。
街景(Street View) 是地图体系中唯一提供平视(Ego-centric) 体验的数据源。它填补了 GIS 数据与人类真实感知之间的“最后一公里”。在这一层级,我们不再关心“屋顶是什么颜色”,而是关心“商店招牌写了什么”、“路面是否有坑洼”以及“站在路口能否看到地标建筑”。
本章将揭开街景技术的黑盒。我们将从移动测量系统(MMS)的硬件采集讲起,剖析全景图的球面投影原理与切片金字塔结构,详细推导从地图坐标到全景视角的几何变换公式,并探讨街景背后的隐形数据——深度图(Depth Map)与全景拓扑图(Pano Graph)。
2. 核心论述
2.1 移动测量系统(MMS):不仅仅是照相机
街景采集车(或背包、手推车)本质上是一个移动测量系统(Mobile Mapping System, MMS)。它并不是简单地拍照片,而是在高速运动中同步记录空间位置与姿态。
2.1.1 传感器融合
一个标准的街景采集单元通常包含以下核心组件,它们通过微秒级的时间同步机制协同工作:
全景相机模组(The Rosette):
通常 5-8 个广角镜头组成,呈莲花状排列。
原理:所有镜头同时曝光,覆盖水平 $360^\circ$ 和垂直 $180^\circ$(除去车顶遮挡部分)。
关键指标:重叠率(Overlap)。相邻镜头的视野必须有足够的重叠,以便后续通过特征点匹配进行无缝拼接。
定位定姿系统(POS - GNSS + IMU):
GNSS:获取绝对经纬度。
IMU(惯性测量单元):高频记录车辆的加速度和角速度。
作用:在城市峡谷(高楼遮挡 GPS 信号)中,依靠 IMU 的“惯性推算”保持轨迹连续,并记录每一帧图像拍摄时的三轴姿态(Roll, Pitch, Yaw)。
激光雷达(LiDAR):
虽然街景看似是图像,但现代采集车都会搭载 LiDAR。
用途 1:构建粗糙的街道三维模型,用于图像拼接时的几何校正(防止近处物体拼接错位)。
用途 2:生成深度图(Depth Map),这是实现“全景测距”和“3D 转场动画”的基础。
Rule of Thumb (经验法则):
街景图像中的“北方”并不一定是图片的上方或正中心。原始图像是相对于车头方向拍摄的。必须结合 IMU 记录的偏航角(Yaw / Heading),在后处理中将图像“旋转”对齐到地理正北,才能在地图应用中正确使用。
2.2 数据结构:从球面到平面的数学映射
2.2.1 等距长方投影(Equirectangular Projection)
为了将球面的全景图存储为一张二维图片文件(如 JPEG),最通用的标准是等距长方投影。
映射逻辑:将经度映射为 X 轴,纬度映射为 Y 轴。
网格关系:
$x$ 轴范围:$-180^\circ \sim +180^\circ$
$y$ 轴范围:$-90^\circ \sim +90^\circ$
图片宽高比严格为 2:1。
ASCII 示意图:投影网格
(0,0) 图片左上角
+-----------------------------------------+ 纬度 +90 (极点被拉伸为一条线)
| / \ / \ |
| / \ / \ |
| / \ / \ |
|---|---------|-------------|---------|---| 纬度 0 (赤道,无变形)
| \ / \ / |
| \ / \ / |
| \ / \ / |
+-----------------------------------------+ 纬度 -90 (南极点被拉伸为一条线)
经度: -180 -90 0 +90 +180
2.2.2 瓦片金字塔(Panorama Tiles)
与卫星地图类似,高分辨率的街景(例如 14000 x 7000 像素)不会一次性加载。它同样采用了瓦片金字塔结构:
Zoom 0:一张低分辨率的缩略全景图。
Zoom 1:将全景图切分为 $2 \times 1$ 或 $4 \times 2$ 的网格。
Zoom N:用户查看局部细节时,仅加载视口范围内的特定瓦片。
注意:这里的“Zoom”是全景图内部的缩放级别,与地图底图的 Zoom Level 是两套独立的系统。
2.3 API 交互核心:几何计算与相机控制
在 Web 开发中(如使用 Google Street View API 或 Mapbox SDK),核心挑战在于如何控制“虚拟相机”的参数,使其精准指向我们想要展示的目标。
2.3.1 视场角 (Field of View, FOV)
FOV 决定了画面的“缩放程度”。
大 FOV (90° - 120°):广角效果,能看到更多环境,但边缘畸变严重,物体显得远。
小 FOV (10° - 30°):长焦效果,聚焦于特定建筑或标志,压缩空间感。
2.3.2 方位角 (Heading) 计算
为了让街景相机自动“盯着”某个 POI,我们需要计算从相机位置到目标位置的大圆航线方位角。
设定:
相机位置 $C (\lambda_1, \phi_1)$
目标位置 $T (\lambda_2, \phi_2)$
其中 $\lambda$ 为经度,$\phi$ 为纬度(单位:弧度)。
计算公式(Bearing Formula):
\[\theta = \operatorname{atan2}(y, x)\]
\(y = \sin(\lambda_2 - \lambda_1) \cdot \cos(\phi_2)\)
\(x = \cos(\phi_1) \cdot \sin(\phi_2) - \sin(\phi_1) \cdot \cos(\phi_2) \cdot \cos(\lambda_2 - \lambda_1)\)
最后将 $\theta$ 从弧度转换为角度,并归一化到 $0^\circ \sim 360^\circ$。
2.3.3 俯仰角 (Pitch) 计算
这是初学者容易忽略的一点。街景相机通常位于车顶(约 2.5米 - 3米高)。
如果要看地面(如斑马线),Pitch 应为负值。
如果要看高楼顶部,Pitch 应为正值。
估算公式:
假设目标物体的高度为 $H_{obj}$,相机高度为 $H_{cam}$,两点地面距离为 $D$。
\[\text{Pitch} \approx \arctan\left( \frac{H_{obj} - H_{cam}}{D} \right)\]
Rule of Thumb (参数策略):
在调用 API 展示某个 POI 时,不要仅仅传入 POI 的坐标。
先用 POI 坐标搜索最近的全景 ID (PanoID)。
获取该 PanoID 的真实坐标(这是相机位置)。
利用相机位置和POI 坐标计算 Heading 和 Pitch。
这样能确保用户看到的画面正对目标,而不是背对着目标看马路对面。
2.4 进阶:深度图(Depth Map)与全景拓扑
2.4.1 深度图:全景的“第三只眼”
Google Street View 等高级服务会在后台存储一张与全景图对应的深度图。这是一张灰度图或 Base64 编码的数组,每个像素的值代表该像素点距离相机的物理距离(米)。
应用场景 1:光标贴地。当你在街景中移动鼠标时,光标会随着建筑物表面变形(如贴在墙面上),这就是利用深度图计算出了鼠标射线与 3D 场景的交点。
应用场景 2:遮挡剔除。如果在街景中叠加 AR 导航箭头,利用深度图可以判断箭头是被建筑物遮挡还是浮在建筑物前面。
2.4.2 全景拓扑图 (Pano Graph)
街景不是孤立的点,而是一个有向图(Directed Graph)。
节点 (Node):每一个全景拍摄点(PanoID)。
边 (Edge):相邻全景点之间的连通关系。每条边包含连接方向(Heading)和说明(如“沿中山路向北”)。
当用户点击画面上的“前进箭头”时,程序实际上是在遍历这个图结构,寻找与当前视线方向(Heading)夹角最小的那条边,加载下一个节点的数据。
3. 本章小结
采集是基础:街景是多传感器(相机+GNSS+IMU+LiDAR)融合的产物,LiDAR 数据对于几何校正和深度感知至关重要。
投影是标准:等距长方投影(2:1) 是存储和交换的标准格式,但在渲染时通常会切片加载。
计算是关键:要实现从地图到街景的平滑跳转,必须掌握Heading(方位角) 和 Pitch(俯仰角) 的几何计算公式。
图结构:街景数据的组织形式是拓扑图,深度图赋予了图像三维属性,使得 AR 标注和测量成为可能。
4. 常见陷阱与错误 (Gotchas)
4.1 “Snapping”吸附)带来的位置漂移
问题:你请求坐标 (lat, lon) 的街景,API 返回了图像,但当你把这个图像的坐标反向打点到地图上时,发现它偏离了原坐标 50 米。
原因:街景车只能在路上跑。API 会将你的请求坐标“吸附”到最近的轨迹线上。
调试:在进行精确标注(如在此坐标处放一个虚拟广告牌)时,必须使用 API 返回的吸附后坐标(Snapping Coordinate) 作为基准,而不是你原始请求的坐标,否则广告牌会“飘”在半空中或插入地下。
4.2 季节与时间维度的混乱
问题:应用需要展示某店铺的现状,但街景显示该处还是工地。
原因:街景更新周期长(数月到数年)。
技巧:
检查 API 返回的 imageDate 字段。
在 UI 上显著标注“拍摄于 YYYY 年 MM 月”。
利用部分 API 提供的“时光机”功能(Time Machine),允许用户查历史影像,这在城市变迁分析中非常有价值。
4.3 室内全景的“黑洞”
问题:用户在街景中点击进入某商场,突然画面变黑或卡死。
原因:室外街景(由 Google/百度采集)与室内街景(通常由第三方商家上传)的坐标系或拼接质量往往存在差异。商家上传的全景图可能缺少地理参考(Geotag)或深度信息,导致查看器渲染失败。
调试:在代码中区分处理 StreetViewSource.OUTDOOR 和 StreetViewSource.DEFAULT,对于非官方数据源要有容错机制。
4.4 视场角 (FOV) 导致的比例失调
问题:为了看清远处的物体,将 FOV 设置得极小(如 10°)。
后果:用户稍微转动视角,画面就像坐过山车一样剧烈晃动(角速度被放大)。
建议:限制 FOV 的最小值,或者在缩小 FOV 时降低鼠标/触摸灵敏度。
导航:返回目录
上一章:从 nadir 到三维
下一章:室内地图构建与 BIM 融合