简介:这份云南省30米分辨率DEM数据面向地理信息、测绘、环境研究与城市规划等领域的从业者和学习者,提供覆盖全省的高程地形基础数据,可用于洪水风险评估、地质灾害分析、地形地貌研究及交通线路设计等场景。压缩包共10个文件,约1MB,以GeoTIFF栅格影像为核心,辅以shp、shx、dbf、prj等Shapefile组件界定云南省行政边界,另有tfw坐标参数、xml元数据及sbx、sbn空间索引文件,基于ASTER GDEM V3版本,采用WGS84坐标系,便于在QGIS、ArcGIS等软件中直接加载与空间分析。目前已有1057人学习下载。数据分辨率高、地理配准完整,读者可据此开展地形可视化、坡度坡向提取、流域分析等实操,并结合边界文件快速裁剪出研究区范围,是区域地形研究与环境建模的实用底图资料。
1. 云南省DEM(30米分辨率):从一块“数字地形底座”说起
如果你接过云南的公路选线、光伏选址、水土保持或者无人机航线规划,大概率绕不开一个东西:云南省DEM(30米分辨率)。DEM 是数字高程模型,30 米指的是格网间距,也就是每个格子代表地面约 30×30 米的平均高程。云南地形从滇西北海拔 6000 米级的雪山到滇南不足百米的河谷,高差极大,用一份 30 米 DEM 把全省地形“铺”进 GIS 里,是很多空间分析的第一步。它解决的是“地面到底多高、坡往哪边倒、水往哪里流”这类基础问题,适合做流域分析、坡度坡向、通视、淹没模拟的从业者。但拿到数据只是开始,真正让人翻车的是投影、拼接、空值和无高程区,下面按我实际干过的顺序讲清楚。
2. 云南省DEM(30米分辨率)的获取与数据源选型:先搞清你手里是什么
2.1 30 米分辨率在云南意味着什么
30 米格网,换算到地面就是每个像元覆盖约 900 平方米。对云南这种山高谷深的地方,这个尺度能看出大的山脊、河谷和坝子,但看不出单条冲沟或陡坎。常见做法是把它当作区域级分析底图,而不是工程级设计依据。如果你要做的是村级土地整治或单点边坡稳定,30 米会明显偏粗,得考虑更高分辨率或实测点云。
数据源上,国内常用的是地理空间数据云、资源环境科学数据中心等平台提供的 ASTER GDEM、SRTM 或国产高程产品。不同来源在云南的表现差异不小:ASTER GDEM 在滇西北高山区容易出现条带噪声和“坑”,SRTM 在植被茂密区高程偏植被冠层,国产产品在部分区域做了融合。选型时先看你的分析目标——做水文分析优先选经过洼地填充处理的版本,做可视域分析优先选噪声小的版本。
2.2 下载与整理:按图幅还是按行政区
云南跨多个 1:25 万图幅,直接按行政区裁剪最省事,但要注意边界处的高程连续性。我一般先下载覆盖云南的原始分幅数据,再在 GIS 里按省界掩膜提取。下面是一个用 Python 和 rasterio 做批量裁剪的示例,假设你已经把分幅 DEM 放在raw_dem/目录下,省界矢量是yunnan_boundary.shp。
import rasterio from rasterio.mask import mask import geopandas as gpd import os # 读取云南省界矢量 boundary = gpd.read_file("yunnan_boundary.shp") # 确保矢量与 DEM 坐标系一致,常见 DEM 为 EPSG:4326 boundary = boundary.to_crs("EPSG:4326") geoms = [geom for geom in boundary.geometry] input_dir = "raw_dem" output_path = "yunnan_dem_30m.tif" # 先找到第一幅作为参考,后续统一拼接 dem_files = [os.path.join(input_dir, f) for f in os.listdir(input_dir) if f.endswith(".tif")] # 这里只演示单幅裁剪逻辑,多幅需先合并再裁剪 with rasterio.open(dem_files[0]) as src: out_image, out_transform = mask(src, geoms, crop=True) out_meta = src.meta.copy() out_meta.update({ "height": out_image.shape[1], "width": out_image.shape[2], "transform": out_transform, "compress": "lzw" }) with rasterio.open(output_path, "w", **out_meta) as dest: dest.write(out_image)这段代码的核心是mask函数,它按矢量范围裁剪栅格,crop=True保证输出范围紧贴矢量边界。参数上,out_meta继承了源数据的坐标系和数据类型,compress="lzw"能显著减小文件体积。注意:如果分幅数据有重叠,直接逐幅裁剪再拼接会出现接边误差,正确顺序是先做镶嵌再裁剪,或者用rasterio.merge合并后再统一掩膜。
2.3 坐标系与投影:别让“位置对不上”毁掉后续分析
云南全省跨度大,地理坐标系(EPSG:4326)下 30 米格网在东西方向的实际地面距离会随纬度变化。做面积、坡度、距离量算时,必须投影到适合云南的投影坐标系。常见选择是 UTM 分区,云南主要落在 UTM 47N 和 48N,或者用 Albers 等积投影做全省统计。我一般做全省坡度分析时用 Albers,做局部工程分析时用对应 UTM 带。
投影转换可以用 GDAL 命令行,也可以用 Python 的rasterio.warp。下面这条命令把地理坐标的 DEM 转成 UTM 47N:
gdalwarp -s_srs EPSG:4326 -t_srs EPSG:32647 -r bilinear -tr 30 30 -of GTiff yunnan_dem_30m.tif yunnan_dem_utm47.tif-r bilinear是重采样方法,高程连续数据用双线性比最近邻更平滑;-tr 30 30指定输出分辨率 30 米。注意:如果源数据本身是地理坐标,重采样到投影坐标时格网大小会略有变化,这是正常的,但不要反复投影,每转一次都会引入一次重采样误差。
3. 用云南省DEM(30米分辨率)做坡度坡向与水文分析:参数怎么设才不玄学
3.1 坡度坡向计算:3 个必调参数
坡度坡向是 DEM 最基础的应用。在 ArcGIS 里用 Spatial Analyst 的 Slope/Aspect,在 QGIS 里用 Raster terrain analysis,在 Python 里用richdem或gdaldem。不管用什么工具,有三个参数直接决定结果可信度:Z 因子、边缘算法、单位。
Z 因子是高程单位与平面单位的换算系数。如果 DEM 是投影坐标且高程是米,Z 因子设 1;如果是地理坐标,必须设成约 111320 乘以纬度余弦的倒数,否则坡度会严重失真。边缘算法决定边界像元怎么处理,常见有 Horn 和 Zevenbergen-Thorne,Horn 更平滑,适合区域分析。单位选度还是百分比,看你的后续用途,做水土保持常用度,做工程边坡常用百分比。
# 用 gdaldem 计算坡度,输出为度 gdaldem slope yunnan_dem_utm47.tif slope_degree.tif -p -s 1.0 -alg Horn # 计算坡向 gdaldem aspect yunnan_dem_utm47.tif aspect.tif -alg Horn-p表示输出百分比,去掉则输出度;-s 1.0就是 Z 因子;-alg Horn指定算法。跑完后一定要抽查几个已知陡坡和缓坡区域,如果整片区域坡度都接近 0 或 90,八成是 Z 因子或投影出了问题。
3.2 水文分析:填洼、流向、流量累积的连锁反应
用 DEM 做水文分析,标准流程是填洼、计算流向、计算流量累积、提取河网。云南喀斯特地貌多,天然洼地多,填洼阈值设不好会把真实洼地填平,也会把该保留的岩溶漏斗抹掉。我一般先用richdem做一次洼地检测,看看洼地数量和深度分布,再决定填洼阈值。
import richdem as rd dem = rd.LoadGDAL("yunnan_dem_utm47.tif") # 检测洼地 depressions = rd.DepressionHierarchy(dem, rd.TerrainAttribute(dem, attrib='depression')) # 填洼,使用混合算法 dem_filled = rd.FillDepressions(dem, epsilon=True, in_place=False) # 计算流向,使用 D8 算法 flow_dir = rd.FlowDirection(dem_filled, method='D8') # 计算流量累积 flow_acc = rd.FlowAccumulation(flow_dir, method='D8') rd.SaveGDAL("flow_acc.tif", flow_acc)epsilon=True表示在填洼时加入微小坡度,避免形成平坦区域导致流向无法确定。D8 算法简单稳定,适合区域河网提取,但在平坦区容易产生平行流线,这是正常现象。流量累积阈值决定河网密度,云南山区一般设 1000 到 5000 个像元,具体看你要提取的河流级别。阈值越小河网越密,但也会把坡面流误判为河道。
3.3 用云南省DEM(30米分辨率)做流域分割与子流域统计
流域分割是在流量累积基础上,指定出水口后向上游追溯汇水区。在 Python 里可以用pysheds或whitebox。下面用whitebox的命令行做一次流域提取:
# 先填洼 whitebox_tools -r=FillDepressions -v --wd="." -i="yunnan_dem_utm47.tif" -o="dem_filled.tif" # 计算 D8 流向 whitebox_tools -r=D8Pointer -v --wd="." -i="dem_filled.tif" -o="flow_dir.tif" # 计算流量累积 whitebox_tools -r=D8FlowAccumulation -v --wd="." -i="flow_dir.tif" -o="flow_acc.tif" # 提取河网,阈值 2000 whitebox_tools -r=ExtractStreams -v --wd="." -i="flow_acc.tif" -o="streams.tif" --threshold=2000 # 按河网分割子流域 whitebox_tools -r=Basins -v --wd="." -i="flow_dir.tif" -o="basins.tif"这套流程里,threshold是唯一需要反复试的参数。我的习惯是先跑 2000,叠加影像看河网是否和实际沟谷吻合,再上下调整。子流域分割结果可以直接用来做统计,比如每个子流域的平均坡度、高程、植被指数,这对水土保持规划很有用。
4. 云南省DEM(30米分辨率)避坑与排查:5 条血泪经验
4.1 现象:拼接后出现明显接边错位,山脊线断开
原因:不同图幅的 DEM 来源或版本不一致,高程基准有差异,或者拼接时没有做重叠区匀色。解决:优先使用同一来源、同一版本的分幅数据;如果必须混用,在重叠区做直方图匹配或线性回归校正,再拼接。拼接后用山脊线叠加检查,错位超过一个像元就要返工。
4.2 现象:坡度计算结果整片偏小,缓坡变平地
原因:Z 因子没设对,尤其是地理坐标下直接算坡度。解决:确认 DEM 坐标系,地理坐标必须设 Z 因子为1/(111320*cos(lat)),投影坐标设 1。算完后抽查一个已知 30 度左右的坡面,误差超过 2 度就要检查。
4.3 现象:水文分析提取的河网在坝区消失或乱窜
原因:坝区地势平坦,D8 算法在平坦区无法确定唯一流向,导致流线平行或中断。解决:填洼时加 epsilon 微坡度,或者改用 D-infinity 算法。坝区河网可以叠加实际水系矢量做校正,不要完全依赖自动提取。
4.4 现象:DEM 出现大片空值或异常负值
原因:原始数据在云覆盖区、水体或边界处无有效高程,或者数据下载不完整。解决:用gdalinfo -stats查看统计值,空值用相邻像元插值或参考更高精度数据填补。异常负值通常是数据错误,直接设为 NoData 后重算。
4.5 现象:投影转换后面积和距离对不上
原因:投影选择不当,或者转换时没有正确设置源坐标系。解决:云南全省统计用 Albers 等积投影,局部工程用 UTM。转换前用gdalsrsinfo确认源数据坐标系,不要凭经验猜。转换后量算一条已知长度的公路或河流,误差超过 1% 就要查。
5. 把云南省DEM(30米分辨率)用出进阶价值:从地形因子到场景化分析
30 米 DEM 本身只是高程矩阵,真正值钱的是它衍生出的地形因子和场景模型。我常用的进阶玩法有三个:地形起伏度、地形湿度指数和太阳辐射模拟。地形起伏度用窗口分析法,在 3×3 到 11×11 窗口内算高程极差,能快速识别山脊和河谷。地形湿度指数是 ln(a/tanβ),a 是汇水面积,β 是坡度,用来判断土壤水分空间分布,对农业和生态选址很有用。太阳辐射模拟考虑纬度、坡向、坡度和地形遮蔽,对光伏选址和建筑日照分析是刚需。
下面是一个用 Python 计算地形起伏度的示例:
import numpy as np import rasterio from scipy.ndimage import generic_filter with rasterio.open("yunnan_dem_utm47.tif") as src: dem = src.read(1) profile = src.profile # 定义窗口函数,计算极差 def relief(window): return np.max(window) - np.min(window) # 用 5×5 窗口计算起伏度 relief_map = generic_filter(dem, relief, size=5) profile.update(dtype=rasterio.float32, compress="lzw") with rasterio.open("relief_5x5.tif", "w", **profile) as dst: dst.write(relief_map.astype(rasterio.float32), 1)size=5对应约 150 米窗口,适合识别中尺度地形。窗口越大起伏度越平滑,但会掩盖小地形。算完后用已知陡坡区和坝区对比,陡坡区起伏度应该明显高于坝区。
太阳辐射模拟可以用pysolar或 GRASS GIS 的r.sun。我一般用 GRASS 做全省模拟,按月份输出辐射量,再叠加土地利用数据筛选可用地块。这一步的计算量不小,建议先分县跑,再合并结果。
最后说一个我自己的习惯:每次拿到一份新的 DEM,先做三件事——看统计值、看投影、看空值分布。这三件事花不了十分钟,但能避免后面几天的返工。云南省DEM(30米分辨率)是个好底座,但底座稳不稳,取决于你有没有认真对待它的坐标系和空值。希望帮到你。
本文还有配套的精品资源,点击获取