简介资源包为洞庭湖流域30米分辨率数字高程模型DEM数据面向GIS学习者、科研人员及水利环保从业者适用于水文分析、洪水模拟、土地利用规划等宏观地形研究场景。包内共6个文件核心为tif格式栅格高程数据附带ovr金字塔文件用于快速显示dbf属性表、tfw世界文件、xml元数据及cpg编码文件为配套支撑整体压缩包约347.9MB文件结构清晰完整。已有448人学习/下载。该数据可直接在ArcGIS、QGIS等软件中加载利用坡度提取、流向分析、流域划分等功能探究洞庭湖周边地形起伏特征及其对汇水过程的影响为水资源调度、洪涝风险评估和生态保护提供基础地理数据支撑。同时也可作为区域DEM应用的教学示例适合需要实际地形数据开展科研项目或课程设计的地学相关人士。 你拿到的这份洞庭湖流域DEM数据.zip解压后如果只用来渲染山体阴影那等于把一本水文地形图当成了壁纸。DEM是数字高程模型的栅格数据每个像元存一个地面高程值看着只是一张灰度图但在水利、地理信息这些行当里它是做流域河网提取、淹没范围初判、库容估算、地质灾害分析的最小底图。这篇笔记把从拿到压缩包到产出可用成果的流程拆开讲先做数据体检再处理坐标系和拼接裁剪然后用pysheds提取河网最后把常用场景里的翻车点逐个排掉。2. 从zip到能分析的高程底图先检查元数据再处理坐标系与拼接裁剪2.1 先体检用gdalinfo看位深、NoData和坐标系统数据解压之后的第一件事不是丢进QGIS拉伸颜色而是用gdalinfo看一眼这个栅格到底在用什么坐标系、存的是什么类型的数值。很多初学者会忽略这一步直接拿着经纬度的WGS84栅格去做坡度和流向计算结果算出来的河网方向一塌糊涂还以为填洼参数没调好。gdalinfo 洞庭湖DEM.tif重点看输出里的三行Driver、Size、Coordinate System和NoData Value。Driver告诉你这是不是标准GeoTIFFCoordinate System如果显示GCS_WGS_1984说明是经纬度地理坐标系不能直接做水文计算NoData Value一般是-9999、-32768或0填洼和河网提取之前必须让工具认得这个值否则会把空洞当成真实地形。位深也要看一眼Type那行会写Byte、Int16或Float32。SRTM、ALOS这类公开DEM通常用Int16存整米高程处理起来没问题如果遇到Byte型说明数据可能已经做过量化分级直接用会丢失大量地形细节。遇到这种情况我会先怀疑数据源而不是急着算水文。还有一种麻烦是文件里同时带.tfw、.ovr和.xml.ovr是金字塔文件删了还会自动重建.tfw是坐标参考信息.xml是元数据处理时保留它们对结果没有影响不用管。2.2 分幅数据怎么处理gdalbuildvrt快速拼接再统一裁剪如果解压出来的是几十个分幅tif各自覆盖洞庭湖流域的一小块第一步是把它们拼成一个完整栅格。我一般先用gdalbuildvrt生成虚拟栅格这一步不产生真实数据拷贝速度极快确认范围无误后再转成正式tif。VRT是个文本文件记录各分幅的路径和位置关系修改起来非常方便适合先看范围再动手。gdalbuildvrt -o 洞庭湖.vrt 分幅目录/*.tif gdal_translate -co COMPRESSDEFLATE -co TILEDYES 洞庭湖.vrt 洞庭湖全流域.tif用gdal_translate把VRT落成实体tif时我习惯加COMPRESSDEFLATE和TILEDYES。压缩可以减少磁盘占用瓦片化让后续读取指定区域时更快尤其当数据范围覆盖整个洞庭湖流域时这两项能明显改善处理体验。拼完之后用gdalinfo再确认一次范围看Origin和Pixel Size是否合理如果像元尺寸显示成类似0.00027777778这样的度那说明还是经纬度单位后续投影的时候要注意重采样。如果手头已经有流域边界shp可以顺手做一次裁剪。用gdal.Warp比先拼全图再裁更省事它能直接在一个命令里完成拼接、重投影和裁剪后面的内容会细说投影参数。2.3 为什么洞庭湖流域要投影到UTM而不是直接用经纬度经纬度坐标系的单位是度1度经度的实地距离在低纬度地区和高纬度地区完全不一样坡度、坡向、流向这些依赖距离和角度的计算必须用平面坐标。洞庭湖流域主体在东经111度到114度之间北纬28度到30度左右跨UTM 49N和50N两个分带主流做法是投影到UTM 49N也就是EPSG:32649覆盖湖南大部分地区。用gdal.Warp可以一步完成投影和裁剪。gdalwarp -t_srs EPSG:32649 -r cubic -tr 30 30 -cutline 流域边界.shp \ -crop_to_cutline -of GTiff \ 洞庭湖全流域.tif 洞庭湖UTM49.tif-tr 30 30把像元重采样成30米见方和SRTM 30米原始分辨率保持一致-r cubic用三次卷积重采样比最邻近法平滑比双线性法更保边缘适合地形连续表面。正射影像或分类图用最邻近法才对DEM必须用插值类算法否则山峰会被抹成方块。砍到流域边界时-crop_to_cutline直接按shp形状裁出不规则区域而不是裁成外接矩形。裁完之后在QGIS里叠加shp检查一次确认边界没有明显缝隙。到这里这份洞庭湖流域DEM数据zip才算变成可用的底图下一步可以进入水文分析的流程。3. 提取洞庭湖河网填洼、流向与累积量一条龙3.1 填洼的两个关键参数最大填洼深度与缓冲像元原始DEM里存在两类影响水流方向的高程异常一类是真实地形里的封闭洼地另一类是SRTM在湖泊、水库、陡坡峡谷里的噪点或空洞。填洼很难自动区分这两类所以大部分工具提供最大填洼深度这个参数限制每个洼地最多被填多深。洞庭湖湖区地形极其平缓湖面高程一般在20到40米之间湖盆里的微起伏很多是传感器噪声填深限制设得太小水流会顺着噪点画出混乱的细线设得太大又会把真实堤岸抹平。另一个被忽略的参数是缓冲像元。计算流向时如果DEM边缘正好切在山脊或河岸上边缘外没有数据程序会把水硬生生引向边界。给流域边界向外扩一定宽度再计算之后把边界外的结果裁掉能避免这种伪河网。扩展宽度我习惯取50到100个像元也就是1.5到3公里对30米分辨率DEM来说足够消除边界效应。from osgeo import gdal import numpy as np src_ds gdal.Open(洞庭湖UTM49.tif) band src_ds.GetRasterBand(1) dem_original band.ReadAsArray() dem_original[dem_original -9999] np.nan读入后用NaN代替NoData是为了让填洼工具自动忽略空洞而不是把空洞高程当成真实地形填平。这一步在pysheds里也适用很多奇怪的计算结果都源于NoData没有被正确识别。3.2 用pysheds把流向和累积量算出来pysheds是目前处理水文分析里比较顺手的Python库底层Cython实现跑30米分辨率的全流域数据不会等太久。它的流程是固定的填洼、算流向、算累积量、设阈值提河网。每一步都返回一个二维数组中间结果可以随时存成tif检查。from pysheds.grid import Grid grid Grid.from_raster(洞庭湖UTM49.tif) dem grid.read_raster(洞庭湖UTM49.tif) # 填洼限制最大填深避免把堤岸抹平 flooded_dem grid.fill_depressions(dem, max_depth10) # D8流向dirmap是八个方向的位掩码 dirmap (1, 2, 4, 8, 16, 32, 64, 128) flow_dir grid.flowdir(flooded_dem, dirmapdirmap) # 累积量 accum grid.accumulation(flow_dir, dirmapdirmap)fill_depressions的max_depth10意思是单个洼地的填深不超过10米这是针对湖区平缓地形的经验值山区流域可以放大到30米甚至更大。flowdir得到的流向数组用1到128的幂值编码D8方向每个像元指向8邻域中坡度最陡的方向。accumulation返回的是每个像元上游汇入的像元数不是面积但乘以像元面积就能得到集水面积。如果某片区域明显是湖面但累积量出现细长的高值线先别急着调阈值回到填洼参数重新想。湖面在真实世界里是水平面DEM里的湖面却有微小起伏水流会沿这些微起伏画出一条假的“湖心河”。处理办法是手工把湖面高程置平后面第6章讲局部修正时会提到具体做法。3.3 河网阈值怎么定从集水面积反推像元数累积量数组里的值代表汇入该像元的地表水流路径数要得到河网就得设阈值累积量大于等于阈值的像元算河道小于阈值的算坡面产流。阈值太小河网密得像鱼刺阈值太大源头位置会向中下游收缩好多小河全丢了。准确的做法是结合实际水文站控制断面面积来定但快速取用可以先按这一条阈值像元数等于目标源头集水面积除以单个像元面积。洞庭湖流域内湘江、资水、沅江、澧水四大河流的源头集水面积差异很大支流源头集水面积可以取3到10平方公里。30米分辨率的像元面积是900平方米那么3平方公里对应3333个像元。实际操作时取两到三个阈值分别生成河网叠加到遥感影像或地形阴影图上对照看哪个跟实际河道贴合最好。import numpy as np threshold int(3000000 / (30 * 30)) # 3平方公里对应的像元数 river_mask accum threshold output np.where(river_mask, 1, 0) # 把河网mask落盘成tif方便在QGIS里对照验证这里用的river_mask是布尔数组1代表河道。落到磁盘时建议同时保存一份累积量栅格这样不用重算就能换阈值再生一张河网。河网生成后如果想划分出各支流的子流域常见做法是在河网节点的交汇点选择一个出口用grid.catchment函数生成该出口的上游集水区再在QGIS里把多个出口的集水区剪出来效果和商业软件的流域盆地图差不多。4. 从DEM到工程决策坡度、库容与淹没模拟的几个实用场景4.1 坡度和坡向算地质灾害风险底图的注意事项坡度是DEM最直接的应用地表径流速度、土壤侵蚀强度、塌方隐患判别都看它。在GDAL里算坡度前有一个检查项容易被忽略投影坐标系DEM的像元尺寸在两个方向应该一致或接近如果x方向和y方向像元尺寸不同坡度计算软件多数会按像元对角线边长做参考结果系统性偏大或偏小。洞庭湖流域这类经过gdalwarp重采样后的数据像元尺寸已经变成规则的30米乘30米直接用即可。from osgeo import gdal ds gdal.Open(洞庭湖UTM49.tif) slope_ds gdal.DEMProcessing(坡度.tif, ds, slope, algHorn, slope_formatdegree)DEMProcessing是GDAL内置的高程衍生算法入口slope_formatdegree输出度数制坡度适合工程出图percent输出百分比坡度适合水土流失方程。算法默认是Horn它考虑邻域8个像元比只考虑东、南两个像元的简单算法抗噪声能力强。坡向用同一入口改aspect就可以输出的0到360度方向是下坡方向和气象上习惯的上风方向容易搞混出报告时要写清楚。4.2 水位-库容曲线用DEM像元面积叠加高程区间水库或蓄洪区工程里经常需要水位和库容的关系也就是水位每上升一米能装多少水。这个可以从DEM快速估算把高程按照每米一个区间分段统计每一段的面积乘以厚度1米就是该区间的体积增量累积求和就得到水位库容曲线。相比实测水下地形DEM库容在低水位段会偏大因为DEM看不到水面以下的地形湖底被当成了水面高程。elevations dem_original[~np.isnan(dem_original)] water_levels np.arange(20, 40, 1) volume [] for wl in water_levels: flooded_area np.sum(elevations wl) * 30 * 30 volume.append(flooded_area)循环里每一次算的是到当前水位的累计面积不是增量。累计面积乘以米数再累加得到的是水位容积曲线的前半段。真正的库容曲线应该按水位分段做增量求和也就是相邻水位的面积平均值乘以1米这里直接用累计面积做近似高水位段误差还在可接受范围内。想精细就用scipy.integrate.trapezoid对水位面积曲线积分效果一样。4.3 静态淹没范围低于水位线的像元不是全部真相防洪评估里最常被问的问题是这个位置淹不淹。很多第一次接触DEM的人会把“低于水位高程的像元全部标成淹没区”当成答案这在坡地流域还行在洞庭湖平原湖区会明显高估。原因是湖区有堤防、垸区、公路路基这些微地形在DEM里可能只有一两米的起伏但足以挡住水低于水位线的像元如果和河湖水面没有连通实际并不会进水。正确的快速做法是先设定一个出水口或河道水位面然后在DEM上做连通性分析只把从河道逐像元漫出去、且高程低于水位的区域算作淹没。用QGIS的r.lake模块或者pysheds的catchment思路都能做区别在于前者是给一个进水点后者是给一个出口点。静态淹没图只能用来做初筛正式方案还是要交给二维水动力模型去算但DEM给的这张底图能帮你在项目启动阶段快速圈定重点范围。5. 洞庭湖DEM数据处理的5个高频翻车点现象与解法5.1 湖区填洼后出现大片平地河网像树枝平躺现象河网提取结果在湖区出现大量平行短线和环状线河网密度明显比上游山区高明明是一片平湖却画出无数条“河”。原因不是填洼没填平而是湖面DEM有微幅噪声填洼又把洼地全抹平了水流方向几乎由浮点误差决定累积量随机分布后超过阈值的地方就密密麻麻。解决先用流域边界内的实测水面高程数据把湖面像元统一赋成一个常数值再做填洼和流向计算如果拿不到实测高程就用分区统计把湖面区域的DEM置平。5.2 裁剪边缘出现放射状直线河网贴着边界拐弯现象河网图上的河道在流域边界处突然变成垂直边界的直线或者所有河道在边缘汇聚。原因直接用流域边界shp切DEM后切掉的区域在流向计算时被当成“挡墙”落在边缘的像元指向边界外就没有出口程序把水流强制导向相邻像元形成沿边界的假河道。解决裁剪DEM时向外缓冲至少50个像元算完河网再把边界外的栅格裁掉或者提前把掩膜范围扩展到整个外接矩形别让边界贴着流域线。5.3 坡度值高得离谱山体像被压扁现象同一个山区算出来的坡度大面积超过60度甚至接近90度和实地认知明显不符。原因DEM用了未经投影的经纬度坐标系东西向像元宽度在纬度30度附近只有约96米南北向是111米坡度计算器按几何距离算自然失真越往北偏差越大。解决回到第2章补做gdalwarp -t_srs EPSG:32649确认Pixel Size显示的单位是米再重跑DEMProcessing。这类错通常不是工具坏了是数据坐标系没到位。5.4 NoData空洞把湖底变成0米库容曲线突然跳变现象水位-库容曲线在某一区间出现折线跳变面积突然增加几千平方公里淹没模拟里某个湖区边缘出现大块蓝色但地面高程远高于水位。原因SRTM在湖面区域经常出现回波空洞NoData值如果没被正确识别成NaN工具会把NoData当真实的0米高程参与运算等于凭空挖出一个大坑。解决读数据后先强制给NoData赋值成NaN处理完检查空洞是否被插值填补如果空洞面积太大用周围高程做克立金插值补洞别依赖填洼工具顺手填平。5.5 用默认参数重采样后湖面面积比实测大一圈现象把原始30米DEM重采样成90米后湖面边界往外扩了半公里面积统计显著变大。原因重采样默认用最邻近法时湖岸像元被保留用双线性或三次卷积时水陆边界像元会插值出一个过渡带低于水位阈值的部分就全被划成水面。解决重采样加分带处理只对陆地像元插值水面像元保持NaN或常数要保留湖面边界精度就干脆不重采样直接沿用原始像元的湖陆分类结果。这个坑在面积量算和淹没模拟里影响最隐蔽因为成果图看起来比实际更“平滑”。6. 进阶用手持GPS和高程基准点校验DEM再做局部修正处理洞庭湖流域这类地势极平、水网密布的区域时我最看重的一步是用实测高程点校验DEM。SRTM在陆地上整体精度不错但湖区周边人为改造强烈坑塘、堤坝、公路路基频繁变动而这些恰恰是水文分析里最敏感的区域。收集测区内水准点、手持GPS打点或已有工程勘察点和DEM像元值一一对比算平均误差和RMSE如果偏差超过一米就要考虑对局部区域做修正。# 实测点文件格式经度、纬度、高程 import pandas as pd from osgeo import gdal points pd.read_csv(实测点.txt, sep,) ds gdal.Open(洞庭湖UTM49.tif) for i, row in points.iterrows(): # 把经纬度投影到UTM再按像元坐标取高程 x, y transform_to_utm(row[lon], row[lat]) result gdal_ogr_get_elevation(ds, x, y)这只是一段示意逻辑具体步骤是实测点先投影到EPSG:32649gdal读取像元值后与实测高程相减。修正时不要在全局用平移法统一加减那样会把山体误差也带走只针对湖面区域和河网沿线做局部置平或插值。比如湖面高程已知为一个统计值就把湖面像元批量赋成这个值确保流向计算和淹没模拟不在地形微幅噪声上翻车。这套“先体检再投影后计算最后验证”的流程我现在拿到任何DEM数据包都会先走一遍哪怕只花十分钟查坐标和NoData也比算完一版错误河网再回头查数据靠谱得多。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?