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

第3章:矢量与栅格数据模型

3.1 引言:为什么既需要“矢量”也需要“栅格”?

在实际的地理问题中,我们经常会遇到类似的困惑:用点线面描述河流与道路很直观,但对于植被覆盖、降雨强度、地形高程这些“连续变化”的信息,点线面却显得“颗粒太粗”。因此,GIS 形成了两种互补的数据模型:矢量(点/线/面)与栅格(规则像元网格)。本章通过问题引入与代码示例,讲清两者的分工、优势与局限,以及在同一工作流中如何相互转化与协同使用。

3.2 先修要求

  • 基础 Python(with、函数、包管理)
  • 基础 GIS 概念(坐标系、投影、空间参考)
  • 简单的地理数据认识(例如 Shapefile、GeoJSON、TIFF)

3.3 核心概念与原理说明

  • 矢量模型(Vector):用点/线/面表达离散对象,适合道路网、行政区、河流要素等;属性结构清晰,拓扑可维护;空间精度高,但表达连续表面能力有限。
  • 栅格模型(Raster):规则网格像元表达连续现象(每个像元一个数值)。适合地形高程、遥感影像、降雨温度等;易做卷积、重采样、邻域分析;但边界“锯齿”且存储体量往往较大。
  • 坐标参考与投影:两类数据必须共享一致的坐标参考与投影,才能正确叠加与分析。常见误区是“叠在一起但不重合”,多源于坐标系不一致或未正确重投影。
  • 拓扑约束:矢量在叠置分析前应确保几何合法(无自交、无重复环等),否则会导致面积错误或分析异常。
  • 分辨率与像元大小:栅格的像元大小决定空间细节与存储成本;过粗会丢失信息,过细则成本过高。分辨率选择要服务于问题尺度。
  • 模型协同:常见工作流是“矢量区域筛选 → 栅格统计/卷积 → 输出区域统计表”。掌握两者互操作是工程落地的关键。
矢量行政区
叠加裁剪
栅格影像/DEM
栅格统计/卷积
区域级指标汇总

3.4 知识点与学习目标

  • 认识矢量与栅格的适用场景与差异
  • 掌握基本读写:geopandas 读写矢量,rasterio 读写栅格
  • 学会基本空间分析:缓冲、叠置、栅格统计、重采样
  • 掌握坐标系一致性与重投影的要点
  • 能在一个任务中混合使用两种模型完成目标

3.5 内容讲解与示例(文章式展开)

选择合适的数据模型:从问题出发

当你的问题关注“对象的几何边界与关系”(如道路连通、行政区比较、河网结构),矢量更直观;当你的问题关注“空间连续分布的强度或状态”(如温度、降雨、植被),栅格更契合。一个常见错误是“强行用矢量表达连续现象”,导致分析复杂度陡增。

读写与坐标系一致性

在工程实践中,第一步往往是把数据正确读入与统一坐标参考:

# 代码片段:读取矢量与栅格并统一坐标系
import geopandas as gpd
import rasterio
from rasterio.warp import calculate_default_transform, reproject, Resampling# 读取矢量行政区
gdf = gpd.read_file("data/admin_boundary.geojson")
# 读取栅格
src = rasterio.open("data/ndvi.tif")# 将矢量重投影到栅格的坐标系(保持栅格原真值)
# 注意:矢量的 crs 属性可能为 None,需要手动指定或查阅数据文档
gdf = gdf.to_crs(src.crs)
print(gdf.crs)
print(src.crs)

经验要点:如果叠加后不重合,先检查两者 crs 是否一致,再检查是否存在坐标轴顺序问题(经纬度 vs 纬经度)。

矢量分析:缓冲、叠置与拓扑修复

矢量分析常见步骤是先修复几何,再做缓冲或叠置:

# 几何合法化,避免自交、多边形裂缝导致面积/叠置异常
gdf["geometry"] = gdf.buffer(0)# 对关键设施点位做缓冲区(例如 1000m 影响半径)
facilities = gpd.read_file("data/facilities.geojson").to_crs(src.crs)
buffer_1km = facilities.buffer(1000)# 叠置:求行政区内的设施缓冲覆盖区(intersection)
cover_in_admin = gpd.overlay(gpd.GeoDataFrame(geometry=buffer_1km, crs=src.crs),gdf,how="intersection"
)
# 输出用于后续统计
cover_in_admin.to_file("outputs/cover_in_admin.geojson", driver="GeoJSON")

工程提示:buffer(0) 并非万能,但能快速修复常见自交问题;复杂拓扑应使用专门工具(如 PostGIS 拓扑或 shapely 高级操作)。

栅格分析:裁剪、统计与重采样

当我们只关心行政区内的栅格信息时,应先裁剪再统计,以减少计算量并保证结果“在区域之内”:

import numpy as np
import rasterio.mask# 使用行政区边界对 NDVI 栅格裁剪
shapes = [geom for geom in gdf.geometry]
clipped_image, clipped_transform = rasterio.mask.mask(src, shapes, crop=True)
ndvi = clipped_image[0]# 统计:忽略 nodata,计算均值与百分位
nodata = src.nodata if src.nodata is not None else np.nan
ndvi = np.where(ndvi == nodata, np.nan, ndvi)
mean_ndvi = np.nanmean(ndvi)
p90_ndvi = np.nanpercentile(ndvi, 90)
print("mean=", mean_ndvi, "p90=", p90_ndvi)# 重采样:将 NDVI 重采样到更粗分辨率以加速下游分析
dst_crs = src.crs
transform, width, height = calculate_default_transform(src.crs, dst_crs, src.width, src.height, *src.bounds
)
dst_profile = src.profile.copy()
dst_profile.update({"transform": transform, "width": width, "height": height})dst_data = np.empty((src.count, height, width), dtype=src.dtypes[0])
for i in range(src.count):reproject(source=rasterio.band(src, i + 1),destination=dst_data[i],src_transform=src.transform,src_crs=src.crs,dst_transform=transform,dst_crs=dst_crs,resampling=Resampling.bilinear,)
# 保存重采样结果
with rasterio.open("outputs/ndvi_resampled.tif", "w", **dst_profile) as dst:dst.write(dst_data)

实践经验:统计前一定要正确处理 nodata,否则均值与百分位会被无效像元污染。重采样方法需根据数据类型选择:分类栅格常用最近邻,连续栅格常用双线性或立方卷积。

模型协同:区域-栅格汇总表

很多业务需要“在每个行政区计算一个栅格指标”,这就需要把栅格统计结果回写到矢量属性表:

import pandas as pdstats = []
for idx, row in gdf.iterrows():geo = [row.geometry]img, _ = rasterio.mask.mask(src, geo, crop=True)arr = img[0].astype(float)nodata = src.nodata if src.nodata is not None else np.nanarr = np.where(arr == nodata, np.nan, arr)stats.append({"admin_id": row.get("id", idx),"mean_ndvi": np.nanmean(arr),"p90_ndvi": np.nanpercentile(arr, 90)})df = pd.DataFrame(stats)
# 合并回矢量属性
gdf = gdf.merge(df, left_on=gdf.index, right_on=df.index, how="left")
gdf.to_file("outputs/admin_ndvi.geojson", driver="GeoJSON")

这样,一个既含有边界几何又含有统计指标的矢量数据就准备好了,下游可以直接用于制图或指标分类。

常见误区与排障思路(对应 3.8)

  • 叠加不重合:检查 crs、是否经纬度顺序错误;必要时显式重投影。
  • 面积/结果异常:排查矢量几何是否非法(自交、洞不闭合),使用 buffer(0) 尝试修复。
  • 统计偏差:确保 nodata 被正确处理;分类栅格不要用双线性重采样。
  • 性能问题:先裁剪再统计;按行政区分块处理;合理选择分辨率。

工程建议:数据组织与版本化

  • 保持 data/(原始)与 outputs/(中间/结果)分离,避免覆盖原始数据。
  • 在文件名中编码坐标系与分辨率信息(如 ndvi_wgs84_10m.tif)。
  • 记录处理流水线(脚本名、参数、时间),便于复现与追踪。

3.6 实践任务(可运行代码)

  • 任务一:将行政区与 NDVI 栅格对齐并输出区域均值与 P90 指标
  • 任务二:为设施点生成 1km 缓冲并与行政区叠置,计算覆盖面积比例
  • 任务三:将 NDVI 重采样到更粗分辨率并比较统计差异

参考脚本:gis_examples/modules/01_basics/vector_raster_demo.py

代码要点摘录:

# 读取矢量与栅格 → 坐标系对齐 → 栅格裁剪 → 统计 → 合并属性
# 脚本中包含必要的异常检查与注释,便于直接运行与修改

3.6.1 道路矢量转栅格热度与区域评分(端到端)

为方便在城市尺度表达道路通行状况,常将道路矢量转成“格网热度栅格”,随后按行政区统计并生成评分表:

# scripts/ch3/vector_to_raster_road_heat.py
import os
import numpy as np
import geopandas as gpd
import rasterio
from rasterio.transform import from_origin
from rasterio.features import rasterize
import rasterio.maskdef roads_to_heat(roads_path, cell_m=100, out_tif='outputs/ch3_road_heat.tif'):roads = gpd.read_file(roads_path).to_crs('EPSG:3857')minx, miny, maxx, maxy = roads.total_boundswidth = int((maxx - minx) // cell_m) + 1height = int((maxy - miny) // cell_m) + 1transform = from_origin(minx, maxy, cell_m, cell_m)# 线要素栅格化:占用叠加(简单近似,可替换为长度加权)shapes = [(geom, 1) for geom in roads.geometry if geom is not None]heat = rasterize(shapes, out_shape=(height, width), transform=transform, all_touched=True,merge_alg=rasterio.enums.MergeAlg.add).astype(np.float32)# 平滑近邻:作为“道路密度”直觉的简化实现from scipy.signal import convolve2dkernel = np.array([[1,1,1],[1,2,1],[1,1,1]], dtype=np.float32)heat_smooth = convolve2d(heat, kernel, mode='same', boundary='symm')profile = {'driver':'GTiff','dtype':'float32','count':1,'width':width,'height':height,'crs':'EPSG:3857','transform':transform}os.makedirs(os.path.dirname(out_tif), exist_ok=True)with rasterio.open(out_tif, 'w', **profile) as dst:dst.write(heat_smooth, 1)return out_tifdef score_accessibility(admin_path, heat_tif, out_csv='outputs/ch3_admin_accessibility.csv'):import pandas as pdgdf = gpd.read_file(admin_path).to_crs('EPSG:3857')with rasterio.open(heat_tif) as src:rows = []for idx, row in gdf.iterrows():img, _ = rasterio.mask.mask(src, [row.geometry], crop=True)arr = img[0]mean_heat = float(np.nanmean(arr))p90_heat = float(np.nanpercentile(arr, 90))score = 0.6*mean_heat + 0.4*p90_heatrows.append({'admin_id': row.get('id', idx), 'mean_heat': mean_heat, 'p90_heat': p90_heat, 'score': score})import pandas as pddf = pd.DataFrame(rows)os.makedirs(os.path.dirname(out_csv), exist_ok=True)df.to_csv(out_csv, index=False)return out_csvif __name__ == '__main__':roads = 'data/roads.geojson'admin = 'data/admin_boundary.geojson'tif = roads_to_heat(roads, cell_m=100)csv = score_accessibility(admin, tif)print('Saved', tif, csv)

运行:

  • python scripts/ch3/vector_to_raster_road_heat.py
  • 输出:outputs/ch3_road_heat.tif, outputs/ch3_admin_accessibility.csv
道路矢量
栅格化/卷积
道路热度栅格
行政区矢量
按区裁剪栅格
区域通行评分表

参数与调优建议:

  • cell_m 设定网格大小;城市常见 50–200m,兼顾细节与计算量。
  • 若需长度/等级加权,可对线要素按属性赋值后栅格化;或分段按长度权重。
  • 平滑核仅作演示,工程中可替换为核密度估计/距离衰减以更符合交通直觉。

排障:

  • 热度为零/道路未烧录:检查 all_touched、坐标系一致性与道路几何合法性。
  • 行政区裁剪异常:检查几何并尝试 buffer(0) 修复;必要时简化几何提高鲁棒性。

3.7 输出与评估标准

  • 统计结果完整:每个行政区都有 mean_ndvip90_ndvi
  • 可复现:脚本能在新环境中按 README 步骤跑通
  • 质量控制:坐标系一致、无明显几何错误、nodata 处理正确
  • 表达清晰:输出文件命名规范、指标含义明确

3.8 常见错误与排障

  • 错误:CRS mismatch → 解决:统一 to_crs 或对栅格重投影
  • 错误:TopologyException → 解决:buffer(0) 或修复几何
  • 错误:统计含 nodata → 解决:在统计前替换或屏蔽
  • 错误:重采样方法不当 → 解决:按数据类型选择最近邻/双线性等

3.9 延伸阅读与资源

  • 文档:geopandasrasterioshapely 官方指南
  • 实践:PostGIS 栅格扩展、GDAL 工具链
  • 案例:土地覆盖分类、区域生态指数计算

3.10 本章总结

本章从问题引入出发,系统阐释了矢量与栅格两种互补的数据模型及其协同方式。关键在于:让几何表达离散对象,让像元表达连续现象;通过坐标系一致、拓扑合法与合适的重采样策略,把两者在同一工作流中无缝拼接。实践部分给出裁剪-统计-合并的标准范式,便于在行政区尺度生成栅格摘要指标,为后续制图与决策提供坚实基础。

http://www.dtcms.com/a/593010.html

相关文章:

  • java 面试问题
  • Elasticsearch-3--什么是Lucene?
  • 01-SQL 语句的关键字顺序
  • 树莓派Raspberry Pi 5的汉化
  • 小红书推荐系统(牛客)
  • 做网站的猫腻网站的链接结构怎么做
  • 【强化学习】DQN 算法
  • 大模型-详解 Vision Transformer (ViT) (2
  • 学习react第一天
  • 2025年电子会计档案管理软件深度介绍及厂商推荐
  • io_uring 避坑指南
  • (附源码)基于Spring boot的校园志愿服务管理系统的设计与实现
  • deepseek回答 如何用deepseek训练出一个我的思路
  • 3ds Max材质高清参数设置:10分钟提升渲染真实感
  • MyBatis 插件
  • 甘肃省城乡住房建设厅网站首页微商软件自助商城
  • 一文掌握,kanass安装与配置
  • C# ASP.NET MVC 数据验证实战:View 层双保险(Html.ValidationMessageFor + jQuery Validate)
  • 工信部 网站 邮箱内容管理系统做网站
  • arcgis用累计值进行分级
  • 生理学实验系统 生理学实验系统软件 集成化生物信号采集与处理系统生物信号采集处理系统 生理机能实验处理系统
  • 环境变量与程序地址空间
  • Node.js的主要应用场景和简单例子
  • 做视频解析网站是犯法的么360优化大师
  • 大网站cn域名淘宝店铺装修模板免费下载
  • VBA即用型代码手册:利用函数保存为PDF文件UseFunctionSaveAsPDF
  • JPA 的说明和使用
  • MyBatis使用LocalDateTime会报错
  • web网页开发,在线财务管理系统,基于Idea,html,css,jQuery,java,ssm,mysql。
  • 2025汉化idea创建JSP项目