上海12.5m DEM高程数据与shp边界:ArcMap裁剪与坡度分析
简介:上海市12.5米分辨率DEM数据,配套行政边界矢量文件,构成一套完整的地理空间数据包,适合城市规划、环境研究、灾害评估等领域从业者与GIS学习者使用。包内包含数字高程模型栅格数据(tif)及辅助文件(tfw、ovr、xml等),以及上海市行政边界shp要素文件(含dbf属性表、prj投影信息等),可配合ArcGIS等平台直接加载分析。数据基于WGS84坐标系,兼容性与可比性良好。压缩包共15个文件,大小约48.05MB,文件类型涵盖tif、adf、dbf、shp等常见GIS格式,栅格与矢量结合,便于分层查看与空间叠加分析。该资源已有806人学习浏览,可用于提取坡度坡向、制作地形渲染、分析市域内高程分布特征,或结合边界进行分区统计与可视化表达,能有效支撑课题研究与项目实践。
1. 上海市DEM数字高程12.5m:配套边界shp文件,裁剪和制图至少省半小时
拿到DEM数据却对着行政边界犯愁,是地形分析里最常见的翻车现场。这份“上海市DEM数字高程12.5m”不只有一张12.5米格网的高程栅格,还带了一份上海市范围shp文件,等于把“数据”和“边界”配成一套。你不需要再到处找shp文件下载,也不需要手工描边界,在ArcMap里用面图层做掩膜提取,几分钟就能把全市DEM裁成自己研究的区。适合做淹没分析、坡度分级、建筑选址和规划展示的人,尤其是刚接触栅格裁剪的GIS初学者。它解决的是“范围不准、边界对不上、坐标系不明”这三个最耗时间的苦差事。
2. 先看懂这套资料:12.5m分辨率、坐标系与边界shp的匹配关系
2.1 12.5m分辨率不是垂直精度,这点必须分清
12.5m分辨率的本义是每个像元对应的地面采样间距是12.5米。落到上海市域,一张覆盖全市的12.5m DEM大约有2000多万个像元,文件体积不小。但要注意,这个数字描述的是水平网格密度,不是高程测量精度。把“12.5m分辨率”理解成“高程误差只有12.5厘米”,是我见过最多的误解。
上海平均海拔只有4米左右,地形极平,东南奉贤一带甚至有低于0米的圩区。但你仍能从12.5m DEM上看出黄浦江走向、外环高架路基和一些农田排灌沟渠的痕迹。我拿到数据后第一件事就是先看渲染效果,如果拉伸方式不对,整个上海会变成一片亮白,有人会误以为数据坏了,其实只是符号系统里的直方图没拉伸。
这种分辨率适合宏观地形趋势,不适合做单体建筑轮廓。如果你在陆家嘴或虹桥枢纽做分析,12.5m DEM里那些“凸起”往往是建筑屋顶、植被冠层,不是真实地面。雷达干涉获取的高程数据通常代表地表反射面,在城市里更接近DSM,看见楼顶高度不必惊讶。业内常提“DSM转DEM”,那是把地表物体剔除的一套流程,和这份数据自带的精度无关。拿这份数据做坡度、坡向、淹没量级评估,完全够用;拿它去做三维产权定界,就很勉强。
2.2 用gdalinfo和Python核验范围与坐标系
我收到数据的第一步不是直接拉进ArcMap,而是先跑gdalinfo。命令行里只看四行:Driver、Size、Coordinate System、Corner Coordinates。上海范围大致在经度120.85°到122.0°、纬度30.65°到31.9°之间。如果投影显示是经纬度,后续坡度计算会踩“一度不等于一米”的坑,必须先投影到平面坐标系再分析。
gdalinfo 上海市DEM_12.5m.tif输出里重点关注“Coordinate System is”和“Corner Coordinates”两段。如果空间参考写着GCS_WGS_1984,那它是经纬度坐标;如果写着WGS_1984_UTM_Zone_51N,线性单位才是米。很多从公开渠道下载的12.5m DEM都带着WGS84地理坐标系统,直接输入坡度工具会得到异常大的数值。
更稳妥的做法是用shp文件作为基准,把DEM重投影到和shp一致的坐标系。下面这段Python脚本是我常用的核验和裁剪方式:
from osgeo import gdal, ogr # 打开边界文件并读取投影 shp_ds = ogr.Open("上海市边界.shp") lyr = shp_ds.GetLayer() shp_srs = lyr.GetSpatialRef() print(shp_srs.ExportToWkt()) # 用边界范围裁剪DEM,目标坐标系取shp的坐标系 gdal.Warp("dem_clip.tif", "上海市DEM_12.5m.tif", cutlineDSName="上海市边界.shp", cropToCutline=True, dstSRS=shp_srs.ExportToWkt(), resampleAlg="bilinear", dstNodata=-9999) print("Clipping done")这里三个参数最容易被忽略。cropToCutline=True让输出栅格的范围完全贴合上海市边界,而不是保留矩形外框;dstSRS强制把结果投影到shp所在的坐标系,避免后续坐标单位不统一;resampleAlg="bilinear"用于DEM重采样,比最邻近法更平滑,不会出现明显的锯齿。
如果只是想快速确认范围和坐标系,也可以用Python读一下元数据:
from osgeo import gdal ds = gdal.Open("上海市DEM_12.5m.tif") print(ds.RasterXSize, ds.RasterYSize) print(ds.GetGeoTransform()) print(ds.GetProjection()) print(ds.GetRasterBand(1).GetNoDataValue())重点看GetProjection()返回的字符串里是否包含GCS还是PROJCS。如果包含PROJCS,且单位是米,后面做坡度和等高线就很顺手;如果是GCS,就先投影。GetNoDataValue()也要记下来,很多12.5m数据的无效背景值是-32767或0,不清理会让后续统计多出一堆错误极值。
2.3 边界shp文件的三重用途:裁剪、制图、统计掩膜
这份shp不只是用来“框一个范围”,它的作用至少有三层。第一层是裁剪,用面图层的精确边界去切DEM,避免把周边省市的数据包进来;第二层是制图,最后出坡度图或晕渲图时,shp边界作为行政区界线叠在最上层,图面才完整;第三层是统计,把shp作为分区统计的掩膜,可以快速算出上海市各个区县的平均高程、最大高差等指标。
我一般建议保留原始shp文件不动,另存一份mask_上海市区县.shp用于分析。原因很简单:原始文件可能带有区县字段,如果后续要做按区县分区统计,字段被破坏就麻烦了。shp文件不是单个文件,至少包含.shp、.shx、.dbf三个文件,还可能附有.prj、.sbn等。如果只复制了.shp后缀的文件,ArcMap是打不开的。
从行政边界到裁剪结果的完整检查路径应该是:先投影统一,再裁剪,然后做面积校验。面积校验的具体做法后面会说,但思路是:裁剪后的DEM有效像元数乘以像元面积,应该接近上海市域面积。如果差得太多,多半是投影或NoData出了问题。
3. 加载与裁剪:ArcMap中按掩膜提取和栅格裁剪的差别
3.1 加载数据先从属性里的“源”开始
打开ArcMap后,用“添加数据”把DEM和shp都加进去。我习惯先加载shp再加载DEM,这样图层顺序是DEM在上、边界在下,便于检查边界线和地形起伏是否套得准。不要急着做工具,先右键DEM图层,选“属性”,切到“源”选项卡,看以下三个信息:像元大小、NoData值、空间参考。
像元大小必须是12.5米或接近12.5米。如果看到0.000138这样的数值,说明栅格仍是经纬度坐标。这时处理步骤多一步:用“投影栅格”工具把DEM投影到shp所在平面坐标系,再继续裁剪。我这里特别强调,因为很多人就是省了这一步,裁剪出来的坡度值大得离谱,最后怀疑数据本身有问题。
如果DEM显示为一片亮白或黑漆漆,右键图层→符号系统→拉伸选项里把拉伸类型改成“百分比截断”,设置截断范围2%到98%。上海这种平坦地区,高程变化区间很窄,默认的直方图拉伸会把平坦区域拉成饱和色,看着像坏图,其实只是渲染问题。
3.2 按掩膜提取的完整操作与参数说明
按掩膜提取是ArcMap里针对“用面图层裁剪DEM栅格tif文件”最常用的工具。它在Spatial Analyst工具箱里,路径是Spatial Analyst Tools -> Extraction -> Extract by Mask。操作步骤不复杂,但每一步都有容易踩坑的地方:
- 输入栅格选择已经投影好的DEM,不要选原始经纬度数据。
- 输入掩膜数据选择“上海市边界.shp”。
- 输出栅格路径使用英文路径,写到磁盘而不是内存缓存,数据量大时写到内存会报错。
- 在“环境”设置里把“处理范围”选为“与掩膜相同”,把“栅格分析”的像元大小设为“与输入相同”。
- 点击确定后,等待工具执行完成,再用“缩放至图层”查看结果。
第4步里“与输入相同”的意思是:输出栅格的像元大小保持12.5米。如果这里选错了,比如被设成掩膜shp的默认像元大小1000米,那裁出来的结果会有一大块“马赛克”,看起来像模糊处理过,实际是重采样造成的分辨率丢失。我在实际项目里见过不止一次,最后的坡度图完全不能用。
执行完成后,先看属性里的像元大小,确认还是12.5,再往下做分析。掩膜提取的结果通常会在边界外出现一圈NoData,这是正常的,因为它是按面的真实几何形状切出来的。
3.3 栅格裁剪工具与掩膜提取的四个区别
ArcMap里还有一个“裁剪”工具,路径是Data Management Tools -> Raster -> Raster Processing -> Clip,很多人拿不准到底用哪个。两者都可以用面图层做裁剪,但细节差别很大,我整理了一张表:
| 对比维度 | 裁剪工具 | 按掩膜提取 |
|---|---|---|
| 工具箱位置 | 数据管理工具 | 空间分析工具 |
| 输出范围 | 可输出面边界形状,也可输出外接矩形 | 始终与掩膜形状一致 |
| 掩膜类型 | 仅支持要素类和栅格范围 | 支持要素类、栅格,栅格掩膜优先级更高 |
| 对NoData的处理 | 矩形裁剪时保留外部NoData像元 | 掩膜外的像元直接变为NoData |
| 性能 | 大数据量更快 | 面边界复杂时计算更慢 |
如果你只是“切一块矩形范围出来”,两个工具结果差不多。但如果你是“切出上海市行政区边界”,按掩膜提取会更直接,因为它对每个像元做掩膜判断,输出范围精确贴合边界。而裁剪工具如果勾选了“使用输入要素裁剪几何”,也能得到不规则形状,两者在最终渲染图上差异很小。
真正的区别在于掩膜类型。按掩膜提取的掩膜可以是栅格,裁剪工具不行。如果你以后要从一张已分类的土地利用栅格里提取某个类别的DEM区域,那只能用按掩膜提取,先把类别栅格转成掩膜栅格,再做提取。这里不要混淆。
3.4 QGIS里同样逻辑的对应操作
如果你不用ArcMap,QGIS里也有对应的做法。菜单路径是Raster -> Extraction -> Clip Raster by Mask Layer。对话框里四个关键选项:输入图层选DEM,掩膜图层选shp,裁剪范围选“掩膜图层”,输出分辨率不勾选“覆盖”,让它保持原分辨率。还有一个选项是“为输出栅格创建可选的VRT”,一般不勾选。
QGIS的这个工具和ArcGIS的按掩膜提取更接近,会在裁剪后把范围外设成NoData。如果遇到裁剪后结果显示整个图层都空,通常是因为shp的坐标系和DEM不一致,在“重投影图层”后重试。逻辑和ArcMap完全一样,只是名字不同。
4. 从DEM到成型产品:等高线提取、坡度分析和DSM转DEM的边界
4.1 等高线提取:等高距怎么设才不出锯齿
裁剪完的DEM可以继续提取等高线。上海这种平缓地区,等高距设置非常讲究。设成10米,整个上海可能只能抽出几条线,图面空荡荡;设成1米,又会暴露12.5m数据本身的噪声,出现大量细碎小圈。我一般会给上海用5米等高距作为中间产品,再抽一个25米等高距用于制图简化。
在ArcMap里,工具路径是Spatial Analyst Tools -> Surface Analysis -> Contour。输入栅格选裁剪后的DEM,输出要素选一个保存路径,等高线间距填5,起始等高线可以不填。如果数据单位是米,Z因子填1;如果这时发现等高线数值异常,比如城市平地突然出现几百米高差,那一定是没有先投影。
等高线提取完成后,常见问题是锯齿严重。锯齿来源于DEM栅格的阶梯边界,特别是在河道和道路处。解决办法不是改等高线工具参数,而是先对DEM做一步平滑,比如用“焦点统计”取3×3窗口平均值,再把平滑结果输入等高线工具。这样等值线会顺滑很多,代价是稍微损失一点细节。对于上海这种本来就平的城市,损失这点儿细节完全值得。
4.2 坡度与坡向分析:Z因子和单位不要想当然
坡度工具同样在Spatial Analyst Tools -> Surface Analysis -> Slope。输入DEM,输出单位选“度”,Z因子填1。这里最关键的就是Z因子,它只在XY单位与Z单位不一致时才需要调整。比如XY是米,Z是米,Z因子就是1;如果XY是经纬度,Z是米,那Z因子大约是111320,但这个值随纬度变化,上海需要用约111000。
实际操作中,我建议不要在经纬度坐标系下算坡度,因为ArcMap的坡度工具在经纬度下会对Z因子做近似处理,结果不如投影坐标系下稳定。先把DEM投影到平面坐标系,再算坡度,数值可解释性更强。上海大多数地区的坡度集中在0到3度之间,如果结果里满屏是10度、20度,基本可以判定投影出了问题。
坡向工具和坡度放在一起,参数更少。对上海这种地势平坦的地方,坡向往往受噪声影响很大,因为高程差异太小,稍微有一点噪声,坡向就会乱跳。所以我在城市场景里很少直接看坡向,更多是配合山体阴影做晕渲效果。山体阴影工具的方位角设315度,高度角设45度,出来的立体感比较自然。
4.3 DSM和DEM不要混用,12.5m数据更接近哪一类
前面提到12.5m的雷达高程数据在城市里更接近DSM,这一点做分析前必须确认。DSM是地物表面模型,包含屋顶、树冠;DEM是纯地面模型,去掉了这些。如果拿DSM直接做淹没分析,建筑位置的高程会比实际地面高,水漫不过去,模拟结果失真。
ArcGIS里没有一键“DSM转DEM”的单独工具,常见做法是用中点滤波或形态学运算。比如用“焦点统计”取窗口内的最小值,窗口大小可以设成15×15或21×21,这样能把独立建筑屋顶削掉,但也会抹掉一些真实的轻微起伏。另一种做法是设置最大屋顶尺寸,然后对DEM做开运算。这个方法需要试参数,没有标准答案。
我自己的习惯是:如果不是严格的水利项目,先用原始12.5m高程数据做宏观坡度分析,不着急做DSM去噪。若必须做城市内涝模拟,就配合建筑轮廓shp,把建筑覆盖区域的栅格值替换为周边地面高程,然后用中值滤波做一次平滑。失真会比直接开运算小很多。这里特别提一句,因为很多从网上下载的12.5m高程数据标着DEM,实际属性却包含大量地表物体,不加处理直接算径流路径容易翻车。
5. 避坑:上海市DEM实践里最常见的五个翻车瞬间
5.1 现象:裁剪后整个图层全黑,压缩直方图也不管用
现象:按掩膜提取完成后,图像变成一片黑色,只有零星亮斑。原因:大概率是原始DEM没有正确设置NoData,背景值-32767或0被ArcMap判定为真实高程,在拉伸渲染时把整体颜色压成了黑色。解决:先右键属性→源,查看NoData值;如果没设置,可以用“复制栅格”工具重建文件,在NoData值栏填-32767。也可以在环境设置里把“NoData值”统一设为一个确定值,再重新裁剪。
5.2 现象:上海出现大量“负高程坑洼”和巨大黑洞
现象:打开DEM后,整个市区很多像元是-32767或-9999,统计最小值低得离谱,山体阴影图里到处是黑色深坑。原因:这些区域是原始数据在陆地范围之外的填充值,没有转换成NoData就参与计算。解决:先识别无效值的具体数值,然后用“栅格计算器”把等于该值的像元赋值为NoData。公式是SetNull("dem" == -32767, "dem")。处理后再做裁剪,后续统计面积和最小高程才准。
5.3 现象:添加shp后图层飞到非洲或者北极
现象:边界shp加载后,ArcMap显示范围是整个世界,缩小后shp跑到完全不对的位置。原因:shp文件缺少.prj投影文件,ArcMap默认把它当作WGS1984经纬度,而坐标实际可能是WGS84 Web Mercator或CGCS2000带号坐标,导致位置漂移。解决:打开文件目录确认是否有.prj。如果没有,用ArcToolbox里的“定义投影”工具,选择正确的坐标系。上海地区常见的是CGCS2000 3度高斯投影CM 120E,如果你的shp是经纬度坐标,则定义成GCS_WGS_1984即可,不要盲目套UTM。
5.4 现象:执行“按掩膜提取”报错,提示无法从shapefile创建掩膜
现象:工具运行到一半失败,错误码通常是010240或者提示“Failed to create raster from the mask”。原因:shp里有多部件几何、自相交或悬挂边,转栅格时失败;也可能是临时目录权限不够,或者路径中有中文。解决:先用“修复几何”工具清理shp,再在环境设置里把临时工作空间改成纯英文目录,比如D:/temp。如果还不行,把shp用“要素转栅格”转成12.5m栅格掩膜,再作为掩膜输入。这个方案最稳。
5.5 现象:河道全部变成平地,淹没模拟水流乱跑
现象:用这份12.5m高程数据做水流路径分析,河流位置完全看不出下切,排水方向乱成一团。原因:12.5m雷达数据在生成过程中会把狭窄水体平滑掉,上海的中小河道只有几米到十几米宽,像元尺寸已经接近河道宽度,插值后水面高程和周边地面几乎一致。解决:不要只用原始DEM做城市排水分析。给河网数据做“河道烧录”,把河网矢量转栅格,在河道像元上减去一个经验值,比如0.5米到1米,再把结果加到DEM上。ArcMap里操作是先做“欧氏距离”得到缓冲,再用“栅格计算器”减掉固定值,最后“镶嵌”回原DEM。这样河道就有明确的相对低洼形态。
6. 进阶:把上海市DEM快速做成一张可直接汇报的坡度分级图
6.1 重分类:按上海的地形特点定断点
拿到裁剪后的坡度栅格,不要直接拿连续色带去出图,领导看不明白。先做重分类。一般分类可以用0-2度、2-6度、6-15度、15-25度、25度以上。但上海绝大多数区域都在2度以内,这个分档对上海不适用。我建议改成0-1度、1-2度、2-4度、4-8度、8度以上,这样能区分出中心城区和河口边滩的差别。
重分类工具在Spatial Analyst Tools -> Reclass -> Reclassify,分类方法选“手动”,把断点填进去。输出栅格的类别值直接填0、1、2、3、4。填类别值时注意,NoData保持NoData,不要给它分配类别。否则在面积统计里会冒出一大块未知区域。
6.2 面积统计验证和制图导出
分级完成后,用“栅格唯一值”工具或“面积制表”统计每个类别的像元数。每个像元面积是12.5×12.5=156.25平方米,把像元数乘以156.25再除以1,000,000,得到的平方公里数应该和上海市域面积接近。上海市面积大约是6340平方公里,如果统计结果是7400甚至9000,说明NoData没有清理干净,或者裁剪范围包含了周边岛屿。这时回去查第5章里的NoData设置。
制图导出的技巧有两点。第一,比例尺不宜过大,上海全市图放到1比20万到1比50万就够了,否则等高线和坡度图会糊在一起。第二,边界shp要放在所有栅格图层的上面,设置一个浅色描边,不要用深色粗边,不然会遮住地形细节。图例要把分级断点写成“0-1°”“1-2°”这样直接可读的文字,而不是“类别1”“类别2”。
从那以后,我每次拿到新的城市DEM都会强制走一遍gdalinfo投影核验、NoData清理、裁剪后的面积校验这三个动作,在上海的项目里基本再没翻过车。希望帮到你。
本文还有配套的精品资源,点击获取