2. 空间数据类型:矢量、栅格与点云

做空间数据科学,首先得搞清楚手里拿的是什么类型的数据。我刚开始接触这个领域时,也经常混淆。

你想想看,手机上的地图App显示的路网,跟卫星拍下来的照片,本质上是完全不同的东西。前者是一堆点和线,后者是像素矩阵。今天我们就把这三种核心数据类型掰开揉碎了讲清楚。

2.1 矢量数据:点、线、面的世界

矢量数据,说白了就是用坐标点来描述地理对象。一个点就是一串坐标,一条线就是多个点连起来,一个面就是闭合的线围成的区域。这是人类最直觉的空间表达方式。

我曾经在交通流量项目中,用矢量数据存储了全市上万个路口的位置。每个路口就是一个点,每条道路就是一条线。最头疼的事情是,这些数据来自不同部门,坐标系统完全不同——嗯,这个问题我们后面章节会专门讲。

矢量数据的核心优势:精确、存储小、支持复杂的几何运算。缺点是对连续变化的自然现象(如温度、高程)表达困难。

2.2 栅格数据:从像素看世界

栅格数据就是把空间划分为规则的网格单元,每个单元存一个值。最常见的例子就是卫星影像——一张照片由数百万个像素组成。

我个人习惯把栅格数据理解为“空间中的矩阵”。每个格网有自己的位置和属性值。栅格特别适合表达连续现象:地表温度、降水量、植被覆盖度。

栅格数据的核心参数有几个:

  • 分辨率:每个像素代表的地面实际大小。10米分辨率意味着一个像素对应10米×10米的地面。
  • 波段:多光谱影像包含多个波段,如红、绿、蓝、近红外等。
  • 位深:每个像素存储精度,8位可存储0-255值,16位可存储0-65535值。
我曾经在处理DEM数据时,没注意位深设置,直接按8位读入,结果所有高程值都缩到了0-255之间,整个地形完全失真。所以,读取栅格数据前,务必检查位深参数。

2.3 点云数据:三维空间中的海量点

点云数据是一堆三维坐标点的集合,每个点通常还有附加属性,如反射强度、颜色信息。激光雷达扫描出来的就是点云。

记得我第一次接触点云数据时,打开一个. las文件,好家伙,整整一亿个点。我的笔记本直接卡死。后来我才学会用分块读取和空间索引来处理它。

点云数据的特性很明显:

  • 海量数据:单个点云文件轻松上亿点,处理时内存占用巨大。
  • 三维表达:天然带有X,Y,Z坐标,能精确还原物体三维结构。
  • 属性丰富:除了坐标,还有强度、回波次数、分类标记等。
  • 不规则分布:点的密度不均匀,同一区域可能有多个点重叠。

2.4 三种数据类型的对比

维度 矢量数据 栅格数据 点云数据
核心特征 点/线/面几何对象 规则网格像素矩阵 三维坐标点集合
常见格式 Shapefile,GeoJSON,GeoPackage GeoTIFF,IMG,NetCDF LAS,LAZ,PLY
典型应用 路网、行政区划、POI 卫星影像、高程模型、气候数据 建筑物三维建模、森林资源调查
优点 精度高,存储小 适合分析,数学运算方便 三维信息完整,细节丰富
缺点 连续表达困难 文件大,缩放后有锯齿 数据量大,处理复杂

2.5 数据类型之间的关系

这三种数据类型不是孤立的。它们之间可以互相转换,每个转换都有特定的应用场景。

# 矢量转栅格示例:将路网转为道路密度栅格
import geopandas as gpd
import rasterio
from rasterio.features import rasterize

roads = gpd.read_file("roads.shp")
out_meta = {"driver": "GTiff", "height": 1000, "width": 1000,
            "transform": from_origin(-180, 90, 0.1, 0.1), "crs": "EPSG:4326"}

road_raster = rasterize(
    [(geom, 1) for geom in roads.geometry],
    out_shape=(1000, 1000),
    transform=out_meta["transform"],
    fill=0
)

with rasterio.open("road_density.tif", "w", **out_meta) as dst:
    dst.write(road_raster, 1)
在实际项目中,常用转换场景包括:
- 矢量→栅格:生成密度图、区域统计
- 点云→栅格:DEM生成、强度影像生成
- 矢量→点云:三维建筑模型简化
- 栅格→矢量:分割结果矢量化、边界提取

我建议每一个做空间数据的人,都要养成识别数据类型的习惯。

# 快速检查数据类型的Python片段
import geopandas as gpd
import rasterio
import laspy

def check_data_type(filepath):
    """检查空间数据类型"""
    if filepath.endswith(('.shp', '.geojson', '.gpkg')):
        gdf = gpd.read_file(filepath)
        print(f"矢量数据 - 要素数: {len(gdf)}")
        print(f"几何类型: {gdf.geometry.type.unique()}")
        
    elif filepath.endswith(('.tif', '.tiff', '.img')):
        with rasterio.open(filepath) as src:
            print(f"栅格数据 - 尺寸: {src.width}x{src.height}")
            print(f"波段数: {src.count}, 位深: {src.dtypes}")
            
    elif filepath.endswith(('.las', '.laz')):
        with laspy.open(filepath) as las:
            print(f"点云数据 - 点数: {las.header.point_count}")
            print(f"点格式: {las.header.point_format_id}")

# 用法示例
check_data_type("roads.shp")
空间数据类型及其关系 矢量数据 栅格数据 点云数据 点 线 面 波段 分辨率 位深 XYZ坐标 强度值 回波次数 常见转换 矢量 ↔ 栅格 (密度图) 点云 ↔ 栅格 (DEM) 矢量 ↔ 点云 (三维建模) 应用场景 城市路网分析 (矢量) 遥感变化监测 (栅格) 三维城市建模 (点云)

2.6 选择什么数据类型?

我经常被问到:

  • 描述离散对象:选矢量。比如道路、建筑物、行政区划。
  • 描述连续表面:选栅格。比如数字高程模型、气象数据。
  • 需要三维精细结构:选点云。比如树木形态、矿山扫描。
  • 需要频繁的空间叠加分析:选栅格。栅格运算比矢量快得多。
  • 需要精确的拓扑关系:选矢量。点云和栅格都不擅长表达拓扑。
还有一个关键点:数据来源决定数据类型。GPS轨迹是矢量,遥感影像天然是栅格,激光雷达结果就是点云。强行转换通常会有信息损失,转换前要想清楚。

2.7 避坑指南:数据读写的坑

我曾经吃过大亏。在一个项目中,我需要处理点云数据,结果用矢量数据的读取方式去读点云文件——直接把文件读崩了。下面列出几个常见坑:

坐标系统不一致: 不同数据源的坐标系统可能不同。矢量可能是WGS84,栅格可能是UTM投影坐标系。混合使用前必须统一坐标系。

数据范围过大: 点云动不动好几亿点。直接全部读内存,32GB都不一定够。要用分块读取策略。

栅格位深误判: 很多TIFF文件包含内部压缩。直接用普通图片库读,字节对齐会错。一定要用专业地理空间库如rasterio或GDAL。

好了,这就是空间数据类型的全貌。记住核心的一句话:矢量表达离散,栅格表达连续,点云表达三维。理清了这层关系,后续的空间特征工程你才游刃有余。