重庆市30米DEM数据包结构解读与GDAL/QGIS处理实践
2026/9/11 1:52:18 网站建设 项目流程

简介:面向GIS学习者、测绘与城市规划从业者的重庆市数字高程模型数据包,包含30米分辨率的DEM栅格数据,覆盖重庆市主城及周边区域,同时附带行政边界矢量文件,适用于地形分析、教学实验、环境研究与制图。压缩包共12个文件,以TIFF格式的高程主文件为主,配套完整的Shapefile边界系列文件(.shp、.dbf、.prj、.sbn、.shx、.sbx等),另有.tfw定位文件、.ovr金字塔与.xml元数据辅助文件,整体367.04MB,可直接在ArcGIS、QGIS等软件中加载使用。资源已有2510人学习下载。借助DEM与边界数据,使用者无需额外采集即可展开坡度坡向、可视域、流域提取等分析,边界文件还能用于精确裁剪与投影配准,是快速上手区域地形研究与GIS实践的实用素材。

1. 为什么这份30米DEM压缩包值得拆开看

拿到“重庆市dem数字高程tif数据(含市范围shp文件).zip”,多数人的第一反应是双击解压,然后把所有文件拖进GIS窗口。如果没搞清楚扩展名,结果经常是DEM显示成黑乎乎的矩形,或者范围shp偏移了几公里,于是开始怀疑数据发错了。其实这个压缩包是结构很规范的GIS基础素材:30米分辨率的DEM栅格、重庆市范围矢量及其投影文件、金字塔、索引和元数据全都在。DEM的覆盖范围有意留了边,躺在大矩形里,边界需要再用shp裁剪;新手可以用它同时练习栅格与矢量叠加,熟手则可以直接拿来做批量裁剪、坡度和分区统计。先把每个文件是干什么的说清楚,再动手才算真正会用。

2. 压缩包拆解:DEM栅格与Shapefile配套文件的角色分工

这份zip不是一个单独的tif,而是“一主三辅”的完整数据组。稍有不注意,删掉一个看起来多余的文件,数据可能就打不开了。下面按栅格、矢量、索引三个层面拆开看。

2.1 先分清谁是数据本体

主文件是“重庆市DEM.tif”。TIFF本身是图像容器,在GIS语境下通常是GeoTIFF,即把地理参考、像元尺寸、坐标系等元数据写在文件内部。tif里每个像元保存一个高程数值,所谓30米高精度,指的是每个像元在地面上对应约30米乘30米的范围;当数据是经纬度坐标时,像元宽度会出现在0.00027度到0.00028度之间,换算成长度约30米上下。举个例子,0.0002777度乘以111公里,大约是30.8米。所以仅凭tif的像素大小,就能判断它是不是30米产品。另一个容易被忽略的点是:这个tif的范围是一个矩形,矩形里包含重庆市界以外的区域。想只用边界内的部分,就要借助shp做裁剪,而不是直接在ArcMap里放大。

2.2 旁边那些小文件:tfw、prj、ovr、aux.xml

在zip里,还有“重庆市DEM.tfw”“重庆市DEM.tif.ovr”“重庆市DEM.tif.aux.xml”这些同名前缀文件。它们不是重复备份,作用完全不同:

扩展名角色常见缺失后果
tfwWorld File,记录像元尺寸、旋转参数和左上角坐标的纯文本部分软件无法定位
tif.ovr / ovr栅格金字塔,预生成的多分辨率版本缩放时卡顿,但可重新生成
tif.aux.xmlGDAL生成的辅助文件,存统计与疑似NoData信息重新构建,耗时增加
prj矢量/栅格坐标系统的WKT文本描述无法正确投影,坐标错位
sbn/sbxArcGIS的shapefile空间索引一般可忽略,可重建
shp.xml元数据文档,包括来源、字段说明缺失不影响打开
shxshapefile的几何索引必须与shp同时保存
dbf属性表缺失后shp几何可用但属性丢失

tfw文件是一个6行文本,存的是仿射变换系数。前两行分别给出x方向像元宽度、y方向像元高度,第三四行是旋转参数,第五六行是左上角坐标。不要指望在tfw里读出一整条边界折线,它只负责“把这一个像素放在地球表面哪个坐标”。如果tif本身已经是GeoTIFF,tfw的作用是提供一套外部坐标作为备选;当GeoTIFF内部坐标与tfw不一致时,某些软件优先使用tfw,这可能是数据偏移的来源之一。

ovr文件更直接,它就是给显示加速用的。没有它,大型tif在QGIS里每次缩放都会重新读取全分辨率,内存被吃满后只能看到一格一格刷新。它一般由gdaladdo生成,可以删除后重建,不影响原始像元值。

2.3 用命令行先看“底细”

拿到数据后,我不急着双击解压,而是先用命令行把信息打出来。这样可以避免图形界面下坐标完全不可见的问题:

unzip "重庆市dem数字高程tif数据(含市范围shp文件).zip" -d cq_dem cd cq_dem ls -lh gdalinfo 重庆市DEM.tif

ls -lh能看出哪几个文件占空间最大——通常“重庆市DEM.tif”是绝对主力,ovr文件其次。gdalinfo会输出类似下面的信息(具体数值取决于实际文件):

Driver: GTiff/GeoTIFF Files: 重庆市DEM.tif Size is 10240, 7680 Coordinate System is: PROJCRS["CGCS2000 / 3-degree Gauss-Kruger zone 35", ...] Pixel Size = (30.000000000000000, -30.000000000000000) Metadata: AREA_OR_POINT=Area Image Structure Metadata: INTERLEAVE=BAND Corner Coordinates: Upper Left ( 500000.000, 3260000.000) ...

注意看两个地方:一是Coordinate System is后括号里的EPSG或PROJCRS名称,二是Pixel Size。如果像元尺寸是30, -30,说明这是投影坐标下的30米数据;如果是0.0002777...则是经纬度地理坐标下的近似30米。这两者的后续坡度计算、距离量测逻辑完全不同,务必先确认。如果本机还没有GDAL,装好gdal工具后再跑这段命令,比在ArcGIS里翻属性页要直观。

2.4 矢量侧:shp、dbf、shx、sbn、sbx、xml

“重庆市范围.shp”这一组是标准的Esri Shapefile的多个伴生文件总和。shp本身只保存几何体,属性数据要在同名dbf里,几何索引在shx里。sbn和sbx是ArcGIS可选的二进制空间索引,不是通用规范;如果你把文件从ArcGIS拷贝到QGIS服务器时,只保留shp、shx、dbf、prj四个就够。反过来说,如果在Windows文件管理器里直接右键删除“看起来很冗余”的shx,下次加载shp时可能无法读取几何。zip里的“重庆市范围.prj”保存的是边界的坐标系描述,它决定了范围边界能不能和DEM对齐。shp.xml是元数据,很多平台生成的xml里包含数据版权、采集时间和属性说明,值得用文本编辑器打开看一眼再决定是否丢弃。

2.5 外部tfw与内部GeoTIFF:以谁为准

GDAL的规则是:tif内部没有地理参考时,会尝试找同名tfw;tif内部有GeoTIFF头时,默认读取内部头,但部分桌面软件可配置优先使用tfw。如果两套坐标信息都在且不一致,数据就会出现偏移。怎么验证?用一个地理坐标点,比如重庆某桥的已知经纬度,放到QGIS里看tif对应位置是否在该坐标附近。或者用gdaltransform把tfw里的仿射参数转换后手动比对。一般做法是:保留一套权威坐标,删除冲突的辅助文件,避免软件端“三心二意”。

3. 栅格与矢量同框:在QGIS里检查坐标系、范围与高程分布

前面是静态文件分析,这部分进入动态加载。在QGIS或ArcGIS中,DEM和shp叠加后如果位置完全不贴合,多半不是数据错,而是坐标系没对齐或没被正确读取。按下面的步骤检查,比直接看图片要靠谱。

3.1 打开顺序与图层顺序的讲究

先拖入“重庆市范围.shp”,再拖入“重庆市DEM.tif”。这个顺序不是为了好看,而是让矢量边界显示在栅格上层,这样能立刻判断DEM覆盖范围是否包含了整个shp,以及边界外是否有明显的无数据黑边。如果顺序反了,栅格可能盖住边界,你只能看到一张灰度图。在高DPI屏幕上,QGIS默认拉伸方式可能是单波段灰度,看起来对比度很低。把DEM渲染为“Hillshade”或“PseudoColor”能得到更直观的立体感,但那是显示设置,不影响数据本身。

3.2 状态栏、图层属性与Python三个入口

状态栏右下角会实时显示鼠标位置坐标,把它和边界线拐角坐标对比,能快速发现是否因重投影造成偏移。图层属性里的“信息(Information)”标签页能看到CRS、像元大小和图层范围;更多时候,我喜欢直接在Python控制台里写一行,把所有关键信息一次打出来:

raster = QgsProject.instance().mapLayersByName('重庆市DEM')[0] vector = QgsProject.instance().mapLayersByName('重庆市范围')[0] print("栅格CRS:", raster.crs().authid()) print("矢量CRS:", vector.crs().authid()) print("栅格范围:", raster.extent()) print("矢量范围:", vector.extent())

如果栅格和矢量的CRS不一样,QGIS会在显示时做动态重投影,但只是“看起来对齐”,原始文件并没有改变。后续裁剪或坡度计算时,建议先将两者统一到同一个坐标系,避免程序内部反复重投影带来精度损失。输出的extent是一个矩形,如果矢量范围比栅格范围大很多,则说明DEM并未完全覆盖目标区域,需要再找其他数据补边。

3.3 用Identify和直方图检查NoData与高程值分布

选择“识别(Identify)”工具,在DEM上点击任意位置,会弹出该像元的高程值。若点击在重庆市范围之外出现一个非常大的负数,比如-9999或-32768,说明那里是无数据区域,需要把NoData值记下来。再用gdalinfo -stats检查整幅数据:

gdalinfo -stats 重庆市DEM.tif

输出末尾会有MinimumMaximumMeanStdDev等统计项。高程最小值和最大值差距如果达到一千米以上,说明重庆从河谷到山顶的高差很大,后续做拉伸渲染时不要把极值都算进色彩映射;在QGIS里使用“累积计数截止(Cumulative cut)”把2%到98%作为映射范围,能避免大部分区域灰成一片。如果统计结果中Minimum等于NoData值,说明边界外的黑色没有正确识别,应该在“栅格”菜单里重新设置NoData后再做分析。

3.4 用山体阴影验证地形细节是否完整

可以快速渲染一幅山体阴影来检查DEM是否存在条带或细碎噪声:

gdaldem hillshade 重庆市DEM.tif cq_hillshade.tif -az 315 -alt 45 -z 1.2

-az 315设置光源来自西北方向,-alt 45设置光源高度角45度,-z 1.2是垂直比例因子。重庆地块起伏大,z因子的作用是把微小高差放大,让用户在屏幕上看到更多细节。如果输出的hillshade里出现规则的条纹,通常说明数据经过了重采样或原分辨率不足;如果一片平滑像白板,则可能是NoData被误当成0参与渲染。在QGIS里把原DEM放在底部、hillshade放在顶部并设置半透明,能同时看到数字与立体效果。

3.5 统一坐标系的时机:分析前做,不做的后果

当DEM的坐标系是CGCS2000,而shp是WGS84时,两者差异一般只有几十厘米到米级,肉眼无法发现,但在提取剖面、计算坡长时会累积误差。建议在开始分析前把DEM重投影到统一坐标:

gdalwarp -t_srs EPSG:4490 -r bilinear 重庆市DEM.tif cq_4490.tif

EPSG:4490是CGCS2000地理坐标系,和WGS84相差不大但仍是两个不同的参考框架。-r bilinear指定双线性重采样,适合高程栅格;如果是分类栅格,则应该用近邻法。这里特别说明:重投影会改变像元值,双线性重采样会平滑局部细节;如果只是为了显示对齐,可以不重投影,但一旦进入坡度、流域分析,统一坐标系这一步省不得。

4. 实战:裁剪、坡度、等高线与分区统计的命令组合

现在进入真正能出图出数据的环节。以“重庆市范围.shp”为边界,将DEM裁成市界内的数据,再派生坡度、山体阴影、等高线,并用shp分区统计高程。整个过程全部用命令行完成,脚本化之后可重复跑。

4.1 裁剪:用shp作为cutline切出市界内区域

原始DEM是一个矩形,矩形大小可能比重庆市长轴还要长,内部除了市界范围,还包含周边省份的一圈地形。如果直接用这个大矩形做坡度分析,边缘处会出现大量突变值和伪阴影。裁剪是第一步:

gdalwarp -overwrite \ -cutline 重庆市范围.shp \ -crop_to_cutline \ -dstnodata -9999 \ -co COMPRESS=DEFLATE -co TILED=YES \ 重庆市DEM.tif cq_dem_cut.tif

参数的含义:-cutline指定裁剪边界shp;-crop_to_cutline让输出范围严格贴合shp的外边界;-dstnodata -9999将边界外的像元统一填充为-9999,避免后续程序把无数据区当成真实高程0米;-co COMPRESS=DEFLATE用Deflate压缩输出tif,体积一般能减小一半;-co TILED=YES开启分块存储,后面的金字塔会更快。如果只想裁剪到某一个区县,可以先查看shp属性表里的区县名:

ogrinfo -so 重庆市范围.shp

然后再通过-csql "SELECT * FROM 重庆市范围 WHERE 区县='渝中区'"过滤边界。注意属性字段名要根据shp里的实际字段来写,不确定就先执行上面的ogrinfo命令检查。

4.2 按坐标系选择scale参数:坡度计算的关键

坡度算法用的是三阶反距离平方权,通过邻域像元高差计算最大变化率。DEM仍然是经纬度坐标时,x方向相邻像元的实际距离用度表示,和y方向一样;但计算坡度的公式需要水平距离与高程差使用相同单位,这时就必须给一个“尺度因子”把度换算成米。一行命令搞定:

gdaldem slope cq_dem_cut.tif cq_slope.tif -p -s 111120

-p让坡度以百分比表示,100%对应45度;不需要时可以去掉,输出为度。-s指定水平距离比例因子。常用情况见下表:

DEM坐标系水平单位scale因子
EPSG:4326 / 4490 经纬度111320 左右
投影坐标(高斯-克吕格 / UTM)1
投影坐标(英尺)英尺3.2808

如果输入已经是投影坐标,给-s 1即可;给成111120会导致坡度全部接近0。用GIS里的Zonal Statistics或剖面工具验证一个已知陡坡的数值,是排查scale是否能用的最快办法。

4.3 等高线、山体阴影:把tif变成二维矢量

要把视觉化的等高线变成矢量数据,方便放在AutoCAD或PPT里,可以用gdal_contour

gdal_contour -a elev -i 50 cq_dem_cut.tif cq_contour_50m.shp

-a elev为每条等高线增加一个elev字段记录高程值;-i 50表示每隔50米生成一条线。重庆的主城区高差大,50米间隔会生成较密的线条,如果只需要宏观趋势,可改为100或200米。山体阴影则适合叠加在彩色坡度图上,让地形立体感更强:

gdaldem hillshade cq_dem_cut.tif cq_hillshade.tif -az 315 -alt 45

这步和前面的预览命令一样,只是输入换成了裁剪后的数据,避免边界外黑色区域参与渲染。如果要在AutoCAD中自动定位,在QGIS里把shp导出为DWG时选与原数据一致的CGCS2000投影,DXF中就会写入世界坐标,CAD里打开后能直接落在对应坐标系上,不需要再手动缩放旋转。

4.4 分区统计:岭区、河谷的平均高程一次算完

对需要把DEM按行政区划汇总的场景,比ArcGIS里的Zonal Statistics更顺手的是用rasterstats库。先安装再跑:

pip install rasterstats

然后写Python脚本:

import rasterstats stats = rasterstats.zonal_stats( "重庆市范围.shp", "cq_dem_cut.tif", stats=["min", "max", "mean", "median", "std"], nodata=-9999, ) print(stats[:3])

zonal_stats会对shp中每个面要素内部的所有像元做统计,返回一个字典列表,每个字典对应一个面;nodata=-9999和裁剪时设置的NoData保持一致,外圈无效值不会进入统计。输出可以直接转成DataFrame写CSV:

import pandas as pd pd.DataFrame(stats).to_csv("重庆各区县高程统计.csv", index=False)

如果shp里的每个面代表一个完整市界,得到的是一组全市统计;如果是每个区县一个面,则得到每个区县的最小/最大/平均高程,这对选居民点、分析植被垂直带很有用。这里要注意:zonal_stats默认不处理边界穿过的像元,遇到跨界像元会直接丢掉;如果shp边界精确度要求高,可以传all_touched=True,但统计结果会略偏。

4.5 裁剪后的tif是全黑的排错思路

常见现象是裁剪成功但QGIS里全黑。先执行gdalinfo -stats cq_dem_cut.tif看统计值是否正常;如果Minimum为-9999而Max为正常,是因为NoData没有正确遮罩,需要重新用gdal_translate -a_nodata -9999写一遍元数据。如果统计值正常但显示黑,是拉伸方式问题,在图层属性里把“Contrast enhancement”改为“Stretch to MinMax”。如果裁剪后tif文件大小比原文件还大,检查是否由于没有设置压缩导致无效区也被完整存储,重新加-co COMPRESS=DEFLATE压缩即可。

5. 进阶:为大范围DEM建金字塔,并导出shp折点文本做坐标核对

这部分单独讲两个收尾技巧:给DEM建立金字塔以提升浏览性能,以及把shp边界转成CSV文本用来核对坐标范围。对长期处理地形栅格的人,这两件事几乎每次都要做。

5.1 用gdaladdo重建或新建金字塔

裁剪后的tif如果没有ovr文件,在QGIS或ArcGIS里放大缩小会非常迟钝,尤其是分辨率在几千乘几千的栅格。与其在软件里等待“正在构建金字塔”,不如直接命令行生成:

gdaladdo -r average cq_dem_cut.tif 2 4 8 16 32

-r average指定采用平均值重采样生成概述层,它不会改原始像元值,只是预先计算多个低分辨率版本。后面的数字表示金字塔层级:2、4、8、16、32倍降采样。对于30米DEM,默认建到8倍已足够屏幕浏览;如果后续要发布切片,可以再补到32。若原始文件已经有ovr且过期,可以加上-clean先清理旧金字塔。这一步在服务器上处理时,还建议加环境变量GDAL_NUM_THREADS=ALL_CPUS加速。

5.2 把shp折点转成CSV,用于坐标范围核对

“shp转txt”看似简单,实际用处是拿到边界上所有折点的经纬度文本,用于在脚本或CAD里进一步处理。用ogr2ogr导出:

ogr2ogr -f CSV cq_boundary_coords.csv 重庆市范围.shp -lco GEOMETRY=AS_XY

-lco GEOMETRY=AS_XY让输出CSV带有X、Y坐标列;如果不加,CSV只保存属性,没有几何。用head查看前几行:

head -20 cq_boundary_coords.csv

然后把这个CSV里的坐标范围和DEM做快速核对:gdalinfo 重庆市DEM.tifCorner Coordinates给出的四角坐标,应该能包住CSV中的极值。如果边界坐标跳出DEM范围,说明坐标系或源数据版本有问题,这时不要再继续做坡度分析。想要最外侧边界而不是每个折点的闭包,也可以改输出成GeoJSON再提取,但AS_XY对日常文本交换更轻量。

5.3 顺带把栅格转成XYZ点列表

如果需要把DEM给非GIS的系统使用,可用下面命令输出带坐标的高程点列表:

gdal_translate -of XYZ cq_dem_cut.tif cq_dem.xyz

生成的.xyz是空格分隔的三列文本:经度/东西向坐标、纬度/南北向坐标、高程。可与CSV一样用文本编辑器直接打开,作为后续插值、三维可视化的输入。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询