简介:覆盖湖北省宜昌市全域及周边部分区域,这套30米分辨率数字高程模型(DEM)数据包附带宜昌市行政边界Shapefile,适合GIS初学者与专业人士用于地形分析、环境模拟和地图制图。压缩包共12个文件,总大小约63.67MB,核心包含宜昌市dem.tif高程栅格、宜昌市范围.shp矢量边界,并配套prj投影文件、tfw世界文件、xml元数据及sbn/sbx空间索引,可被ArcGIS、QGIS等软件直接加载,兼顾快速预览与坐标配准。数据同时提供dbf属性文件与XML说明,便于核对地理参考和属性字段。目前已有825人学习下载,该数据经过实际应用验证,可直接用于坡度计算、流域划分、可视性和淹没分析等教学或科研场景,为城市规划、环境研究和灾害风险评估提供可靠的高精度地形底图。
1. 宜昌市30米DEM数据:拿到手先别急着出图
宜昌的地形不简单:西部山区沟谷交错,中部丘陵过渡,东边才是沿江平原。做地形分析最耗时间的环节,往往不是算法本身,而是数据准备。这份宜昌市DEM数字高程数据30m(含本市级范围shp文件)压缩包,把全市30米分辨率DEM栅格和本市级行政范围SHP文件放在一起,省去了拼接分幅、自己画行政边界这一步。30米分辨率在市级尺度上看坡度、坡向、山体阴影够用,文件体积也适中,ArcMap打开不卡。适合GIS从业者、测绘相关专业学生,以及正在做宜昌市域地形研究但被数据预处理卡住的人。拿到手后别急着直接拉伸渲染,先做三件事:确认坐标系、确认裁剪范围、确认有效高程值。
2. DEM数据选型与宜昌市数据构成:30米分辨率、SHP面层与坐标系的三个判断
2.1 30米分辨率对宜昌山区地形的适用边界
先算一笔账。30米分辨率意味着一个像元对应地面上约900平方米。宜昌西部山区的冲沟、陡坎,在30米像元里几乎都会被平滑掉;但长江河谷、主要支流、山体走向这种百米级地形特征还能保留下来。所以这份数据最适合的场景是市级尺度的栅格分析:土地利用的坡度分级、山洪淹没范围的初步圈定、城市开发的适建性评价。如果拿到村一级,或者要给某一条具体线路做土方估算,30米是明显不够的,至少要到10米甚至5米以下。
我见过一些新手拿30米DEM直接做小流域汇水分析,结果集水面积和实测对不上,问题不在地貌,而在分辨率。一个30米像元的误差,放到坡度算法里会被放大成好几度的偏差。反过来,如果一上来就追求5米、2米高程数据,成本和时间都会成倍增加,而且对全市域范围来说,数据处理慢到让人失去耐心。
顺便补充一个现实选择:现在用BigEMap这类工具可以下载到5米精度高程,但那是商业在线数据源,下载量受权限和网络限制。对于宜昌全市域范围的预研分析,30米DEM是成本和精度的平衡点。
| 分析场景 | 建议分辨率 | 典型用途 |
|---|---|---|
| 宜昌市域/县域宏观分析 | 30m | 坡度分级、山体阴影、淹没模拟初判 |
| 乡镇/小流域分析 | 10m-12.5m | 汇水分析、灾评、生态敏感性 |
| 线路/场地级设计 | 1m-2m | 土方量、边坡、工程可行性 |
2.2 数据包里的双层结构:DEM栅格与本市级SHP的配合关系
这个压缩包的核心是两部分:一个DEM栅格TIFF文件,一个宜昌市本市级范围的SHP面文件。SHP不是用来做属性关联的,它的唯一使命是当裁剪掩膜,把DEM从大范围数据里切到宜昌市行政边界内。
打开压缩包后建议先列一下目录结构。常见做法是用Python快速看一眼栅格和矢量各自的信息:
import arcpy arcpy.env.workspace = r"D:\yichang_dem" print(arcpy.ListRasters()) print(arcpy.ListFeatureClasses())逻辑很简单:确认当前目录里有哪些栅格和要素类。列出之后,再检查SHP的空间范围和字段:
desc = arcpy.Describe("yichang_city.shp") print("范围:", desc.extent) fields = arcpy.ListFields("yichang_city.shp") for f in fields: print(f.name, f.type)这段代码会打印SHP的XMin、YMin、XMax、YMax和字段列表。我一般会先记住四个范围值,后面裁完DEM再对比一次。SHP通常带字段,比如地级市名称或行政区划代码,但这里用不上,裁剪只认几何,不认属性。
2.3 坐标系统一:CGCS2000在ArcMap中的识别与转换
拿到数据后第一个坑往往不是裁剪,而是坐标系。DEM可能来自不同数据源,栅格本身可能没有投影信息,只有经纬度;SHP可能是CGCS2000高斯投影,也可能是WGS84。宜昌的经纬度大致在110°15′E到112°04′E、29°56′N到31°34′N之间,这类区域用UTM 49N或者CGCS2000 3度分带都合适。
我在处理这类数据时的习惯是:先右键图层看属性,源标签里看空间参考。如果DEM显示的是GCS_WGS_1984或GCS_CGCS_2000这样的地理坐标系,就得先投影,再裁剪。否则后续算坡度时会被经纬度坐标的尺度问题带偏。
sr_proj = arcpy.SpatialReference("WGS 1984 UTM Zone 49N") arcpy.ProjectRaster_management( "yichang_dem_orig.tif", "yichang_dem_utm49.tif", sr_proj, "BILINEAR" )参数解释:第一参数是输入栅格,第二是输出路径,第三是目标投影坐标系,第四是重采样方式。DEM是连续表面数据,重采样选BILINEAR或CUBIC,不要选NEAREST,否则会在地形上产生阶梯状断层。
有一种情况要区分:如果栅格显示已经有投影坐标系,但SHP却没有.prj文件,ArcMap会直接弹警告说缺少空间参考信息。这时候不要用Project工具强行转换,而应该先用Define Projection把SHP的坐标系定义成和DEM一致,再投影。定义和投影是两个完全不同的操作,前者只是给数据一个身份标签,后者才是真正改变坐标数值。
提示:裁剪前花两分钟做坐标系检查,比裁剪后发现图对不上再返工划算得多。
3. ArcMap裁剪DEM的两种路线:按掩膜提取与面裁剪的结果差异
3.1 按掩膜提取(Extract by Mask)的操作路径与参数
ArcMap里最常用的是Spatial Analyst工具下的Extract by Mask,对应热搜词里那句“依靠面图层掩码提取”。操作路径是ArcToolbox - Spatial Analyst Tools - Extraction - Extract by Mask。
工具界面里只有三个关键参数:输入栅格选DEM,输入栅格或要素掩膜数据选宜昌市SHP,输出栅格给一个路径。这里有个容易忽略的点:环境设置里的“捕捉栅格”。如果环境里没有指定,输出栅格的像元对齐方式默认跟随输入DEM,也就是说裁剪结果不会因为SHP边界偏移而重建网格,这是好事,保证了后续分析的一致性。
用ArcPy的命令长这样:
from arcpy.sa import * dem = "yichang_dem_utm49.tif" mask = "yichang_city.shp" out = ExtractByMask(dem, mask) out.save("yichang_dem_mask.tif")逻辑是:遍历SHP范围内每个DEM像元,像元中心点落在面内的保留,落在面外的置为NoData。所以裁剪边界不会是绝对平滑的行政边界线,而是由像元中心点决定的锯齿边界。这是正常行为,不是数据错误。若想边界更贴合SHP,可以先把SHP向外或向内做微小的Buffer,但这会改变分析范围,要谨慎。
3.2 用SHP面图层直接裁剪(Clip)的设定与边界条件
另一条路线是Data Management工具下的Clip。很多用户习惯点这个,因为名字直观。但Clip有个关键开关:Use Input Features for Clipping Geometry。勾选时,输出按SHP的实际几何裁剪;不勾选时,输出只是SHP总外接矩形的范围,周围会留下大量NoData区域。
arcpy.Clip_management( "yichang_dem_utm49.tif", "#", "yichang_dem_clip.tif", "yichang_city.shp", "0", "ClippingGeometry", "NO_MAINTAIN_EXTENT" )参数逐个说:第二参数rectangle传#表示不手动指定外接矩形,完全交给SHP;第四参数是裁剪要素;第五参数nodata_value传0,表示把原来无效值写成0,实际使用时可以传空字符串让它保留原有NoData;第六参数ClippingGeometry是关键,不写它或写成NONE,输出就是外接矩形;第七参数控制是否保持原栅格范围,我一般用NO_MAINTAIN_EXTENT,让输出范围贴合裁剪结果。
从性能和结果上比,Clip通常比Extract by Mask快,文件体积也更小,因为它直接按几何取像元,不需要重新计算掩膜内部关系。但Clip处理边缘像元的规则与Extract by Mask相近,都是按像元中心点判断,所以边界差别不大。
3.3 两种方式的实际差异:边缘像元、NoData与文件体积
不少初学者会问:掩膜提取和面裁剪到底有啥区别?用一张表可以讲清楚。
| 维度 | 按掩膜提取 | 面裁剪(勾选要素几何) | 面裁剪(不勾选) |
|---|---|---|---|
| 输出形状 | 与SHP几何一致 | 与SHP几何一致 | SHP外接矩形 |
| SHP范围外 | 全部NoData | 取决于NoData设置 | 保留NoData或0 |
| 边缘像元 | 像元中心判断 | 像元中心判断 | 矩形边界截断 |
| 速度 | 较慢 | 较快 | 最快 |
| 典型用途 | 面积统计、后续栅格分析 | 快速出图、文件瘦身 | 临时查看 |
实际项目里,我处理这份宜昌市DEM时更倾向于用Extract by Mask,因为它对面积的统计更干净。而如果只是想和图斑叠个底图,用Clip更快。
无论选哪条,都要注意一个暗坑:SHP里如果存在多个面要素,比如本市级范围SHP包含主城区、飞地、岛屿多个面,两种工具都会按所有面的并集处理。如果数据包里SHP还附带市级以下细分面,裁剪时不会自动按细分区县分别输出,必须用Split by Attributes或循环迭代。
4. DEM裁剪避坑与排查:五个最常见翻车现场
4.1 现象:裁出来的DEM大半个屏幕是黑色,NoData占比极高
原因:SHP范围超出了DEM有效数据范围,或者DEM数据本身在边界处有无效值,掩膜提取后无效区域被原样保留成了NoData。这个现象在分幅拼接的DEM里非常常见,因为每幅图边缘都有拼接缝。
解决:先对比SHP范围与DEM范围,如果两者差异很大,说明SHP不是从DEM上切下来的,需要换范围更贴合的数据源。如果只是边缘一圈NoData,可以在环境设置里打开“范围”并选择SHP,把处理范围锁定。对剩余NoData区域,可以用栅格计算器里的Con函数填充相邻值,但要注意这会人为修改地形数据,除非必要,不建议做。
out_nodata = Con(IsNull("yichang_dem_clip.tif"), 0, "yichang_dem_clip.tif")Con函数的逻辑是:第一个参数是条件,第二个是条件成立时的值,第三个是条件不成立时的值。这里把NoData像元填成0,能让表面看起来完整,但对坡度分析极不友好,0米高程会和周边真实高程形成假陡坎。所以这个操作只适合出图预览,不适合定量计算。
4.2 现象:DEM在ArcMap里渲染成一整片刺眼的彩色马赛克
原因:符号化方式用了分类渲染,默认分5类,把高程值切成几个区间,山区地形细节全被抹平了。这是新手最容易犯的错,不是数据问题,是显示问题。
解决:在图层面板里把符号系统改成“拉伸”,类型选“标准偏差”或“最值”,再配一个适合高程的色带。宜昌这种山地地形,我习惯把拉伸类型选为“最值”,色带用从深绿到棕再到白的渐变。拉伸显示的细节远比分类渲染丰富。如果还觉得不够,叠加一层山体阴影作为透明底图,把DEM主图透明度调成50%左右,地形立体感马上出来。
4.3 现象:SHP和DEM在ArcMap里显示位置错开,一个在东一个在西
原因:没有对齐坐标系。最常见的是SHP有.prj文件但DEM没有,或者两个坐标系基准面不一致。宜昌范围内WGS84与CGCS2000的差值在平面上看只有几十厘米到一米量级,但如果一个是投影坐标一个是地理坐标,画出来就是十万八千里。
解决:先分别看两个图层的空间参考。把SHP投影到和DEM相同的坐标系,或者反过来。如果SHP缺少.prj,用Define Projection指定,不要用Project。方向错了,数据就废了。
4.4 现象:高程值比真实地面普遍高或低几十米
原因:DEM生产时采用的高程基准和当地常用高程基准不一致。国内常见的DEM有基于EGM96大地水准面的,也有基于1985国家高程基准的,两者在某些山区会差十几米到几十米。对地形形态分析比如坡度、坡向,这个整体偏移不影响结果;但如果你要和高程控制点比对,或者计算水位淹没范围,就必须校正。
解决:找宜昌市内几个已知高程点,统计DEM提取值与实测值的差值。如果差值比较恒定,在栅格计算器里直接加一个常数就行。
4.5 现象:ArcMap在加载或裁剪DEM时直接闪退
原因:ArcMap默认是32位进程,单个栅格过大时内存不够用。30米分辨率的全市范围栅格本不该这么大,但如果没有建金字塔,加载时会尝试把整个栅格读入内存,很容易爆。
解决:加载前先在目录里给TIFF生成金字塔,或者在ArcToolbox里用Build Pyramids工具扫一遍。还有一招是把TIFF转成CRF格式,CRF对栅格运算的支持更好,读取也更快。
arcpy.BuildPyramids_management("yichang_dem_utm49.tif", "PYRAMIDS", "", "BILINEAR")参数说明:第二个参数PYRAMIDS表示创建金字塔,第三、第四参数控制压缩方式和重采样方法。BILINEAR保证缩小显示时地形平滑。
5. 把DEM变成实用地形产品:山体阴影、等高线与坡度一次生成
5.1 山体阴影(Hillshade)的参数与显示效果
山体阴影是DEM最直观的地形可视化方式。工具默认的方位角是315度,也就是阳光从西北方向照过来;高度角45度。宜昌西部山区沟谷多,为了突出峡谷细节,我通常会把高度角降到30度到35度之间。高度角越低,阴影越长,地形越立体,但太低了会丢失沟谷底部的细节。
hillshade = Hillshade("yichang_dem_clip.tif", 315, 35, 1) hillshade.save("yichang_hillshade.tif")参数解释:315是太阳方位角,35是太阳高度角,最后的1是Z因子,也就是垂直方向缩放系数。Z因子不是随意填的——当DEM坐标单位和高程单位都是米时,Z因子为1;如果坐标系是经纬度,Z因子要填约0.000009,但这就是治标不治本,正确做法是先转投影坐标系再做分析。
我给宜昌市区做过一个地形制图,把山体阴影透明化处理,压在坡度图下面,效果比纯色渲染好很多。这个叠加顺序很关键:山体阴影放上层,透明度调到60%到70%,下面的高程或坡度图就能保持色彩信息又有立体感。
5.2 等高线生成:间隔选择与平滑处理
从DEM生成等高线,在ArcToolbox里对应Contour工具。间隔怎么选取决于展示尺度:市级总体规划图我通常用50米间隔,县级或重点片区用20米,河谷平坝区域用10米。宜昌市区从江边高程约50米到周边山区1000米以上,20米间隔生成的等高线数量已经相当可观。
contour = Contour( "yichang_dem_clip.tif", "yichang_contour_20m.shp", 20, 0 )参数解析:输入栅格为DEM,输出是线要素类,20是等高线间隔,0是起始等高线高程。输出线要素的高程字段会自动命名为CONTOUR。
如果等高线毛刺太多,不要急着用Generalize工具把线平滑到面目全非,那是自欺欺人。30米DEM本身就有随机误差,毛刺是真实反映。想减少毛刺,可以先对DEM做一次3×3的Focal Statistics低通滤波,把高频噪声压下去再生成等高线。滤波必然损失真实细节,鱼与熊掌要自己权衡。
5.3 坡度分析与宜昌复杂地形的适配
坡度工具有两个单位:度(DEGREE)和百分比(PERCENT)。宜昌西部山区坡度陡,坡面很多超过25度,用度展示直观;但如果做水土流失评价,标准阈值通常用百分比,比如15%、25%、35%。这个细节很多人不看,直接用了默认的度,结果和标准对不上。
slope = Slope("yichang_dem_clip.tif", "DEGREE", 1) slope.save("yichang_slope_deg.tif")参数说明:DEGREE表示输出坡度单位为度,1依然是Z因子。生成之后按经验阈值做重分类:0到5度为平地,5到15度为缓坡,15到25度为中等坡,25到35度为陡坡,大于35度为极陡坡。宜昌山区在35度以上的区域不在少数,特别是三峡沿岸。
最后提醒一句:坡度分析对DEM噪声高度敏感。如果最终坡度图上有明显条带或方块效应,先回头检查DEM原始数据是不是有拼接痕迹,而不是换更复杂的算法。
6. 裁完DEM之后:用像元数验证数据完整性的一个习惯
数据裁剪完不是立刻做分析,先算一笔账。把有效像元数乘以像元面积,得到的结果应该和SHP面积接近。这个过程我每次都会走一遍,花不了两分钟,但能避免灾难性的返工。
desc = arcpy.Describe("yichang_dem_clip.tif") cell = desc.meanCellWidth total = int(arcpy.GetRasterProperties_management( "yichang_dem_clip.tif", "CELL_COUNT" ).getOutput(0)) nodata = int(arcpy.GetRasterProperties_management( "yichang_dem_clip.tif", "NODATA_CELL_COUNT" ).getOutput(0)) area_km2 = (total - nodata) * cell * cell / 1e6 print("有效面积约:", round(area_km2, 1), "km²")这段代码先从栅格属性里拿像元尺寸,再拿总像元数和NoData像元数,两者相减就是有效像元数,乘以像元面积换算成平方公里。值得注意:meanCellWidth只有在投影坐标系下才是直接用米表示的像元宽度,如果是经纬度坐标,这个值会是度,算出来的面积就没有意义了。
然后取SHP的SHAPE_AREA字段做对比:
with arcpy.da.SearchCursor("yichang_city.shp", ["SHAPE_AREA"]) as cursor: for row in cursor: shp_area_km2 = row[0] / 1e6 print("SHP面积:", round(shp_area_km2, 1), "km²")相对误差在3%以内说明裁剪结果可信。边界像元的中心点取舍会让面积有小幅偏差,这是正常的。但如果误差超过3%,就要回头查SHP范围、DEM范围、投影是否统一这几件事。
这个习惯是我在给三峡库区周边做山地灾害分析时被逼出来的。当时裁完的DEM在等高线图上少了一条完整山脊线,数据表面看着正常,等算到汇水面积才发现偏差有8%。从那以后,我每裁一个DEM,都会强制走一遍这个像元数验证流程。数据是别人处理的,但最后为结果负责的是自己。希望这个验证流程也能帮到你。
本文还有配套的精品资源,点击获取