当前位置:首页>python>Python绘制科研级DEM地形图(含代码)

Python绘制科研级DEM地形图(含代码)

  • 2026-09-30 13:08:27
Python绘制科研级DEM地形图(含代码)
案例代码见文末,感谢您关注PFC小姐姐,麻烦您多多对推文点赞、收藏及转发,并衷心希望您多多指教🙏,帮助PFC小姐姐进步提升。

引言

在地球科学、遥感地理信息、工程地质等研究中,DEM(Digital Elevation Model,数字高程模型)是一类最基础也最重要的数据产品。无论是分析地貌起伏、提取坡度坡向,还是展示区域地形特征,最终都离不开一张高质量的 DEM 地形图。

但很多初学者画 DEM 图时,常常会遇到这些问题:

  • 地形看起来“平”得没有层次;

  • 配色不科学,甚至一眼像“彩虹糖”;

  • 色标范围混乱,不利于不同图之间对比;

  • 图面缺乏阴影效果,立体感很差。

这篇文章就从零开始,演示如何利用 Python 绘制一张具有科研风格的 DEM 地形图。为了方便复现,这里不使用外部真实 DEM 文件,而是直接生成一幅模拟地形数据,包括山脊、火山锥、波状起伏和局部凹地等特征。

图1:科研级DEM图的核心:配色 + 阴影 + 等高线

1、配色:DEM 最常见的错误,就是直接用彩虹色带。彩虹色虽然鲜艳,但不适合定量科学表达,因为色调变化不均匀,会放大某些局部梯度。更适合 DEM 的做法通常有两类,地形专用色带:低处偏绿,高处偏黄褐,再到灰白;单调科学色带:例如 viridis、cividis 等

2、阴影地形:同样一幅 DEM,如果只画高程,可能会显得比较“平”。但如果根据地形坡度与假定光照方向生成 hillshade,再叠加在彩色 DEM 上,立体感会立刻出来。

3、如果只用颜色,有时会掩盖一些细微地形结构。适当叠加稀疏的等高线,可以让地形层次更清楚,尤其在论文里很常见。
示意图:

    具体Python如下:

    import numpy as npimport matplotlib.pyplot as pltfrom matplotlib.colors import LightSource# =========================# 1. 全局绘图参数# =========================plt.rcParams["font.family"] = "Times New Roman"plt.rcParams["font.size"] = 12plt.rcParams["axes.linewidth"] = 1.0OUT_FIG = "dem_scientific_map_fixed.png"# =========================# 2. 构造模拟 DEM# =========================nx, ny = 500, 400x = np.linspace(0, 120, nx)y = np.linspace(0, 90, ny)X, Y = np.meshgrid(x, y)# 长波背景起伏Z_bg = (    120 * np.sin(X / 18.0)    + 90 * np.cos(Y / 14.0)    + 60 * np.sin((X + Y) / 25.0))# 山峰1Z_peak1 = 850 * np.exp(-(((X - 35) / 10) ** 2 + ((Y - 50) / 14) ** 2))# 山峰2Z_peak2 = 600 * np.exp(-(((X - 80) / 16) ** 2 + ((Y - 30) / 8) ** 2))# 火山锥/中央凹陷R = np.sqrt((X - 92) ** 2 + (Y - 68) ** 2)Z_volcano = 500 * np.exp(-(R / 9.5) ** 2) - 220 * np.exp(-(R / 3.0) ** 2)# 洼地Z_basin = -420 * np.exp(-(((X - 60) / 13) ** 2 + ((Y - 62) / 10) ** 2))# 小尺度扰动Z_small = (    35 * np.sin(X / 3.5) * np.cos(Y / 4.2)    + 20 * np.sin((2 * X - Y) / 5.5))# 合成总 DEMZ = Z_bg + Z_peak1 + Z_peak2 + Z_volcano + Z_basin + Z_small# 平移到正高程范围Z = Z - Z.min() + 150# =========================# 3. 计算 hillshade# =========================ls = LightSource(azdeg=315, altdeg=45)# 这里只生成灰度阴影,不直接带颜色hillshade = ls.hillshade(Z, vert_exag=1.2, dx=1, dy=1)# =========================# 4. 绘图# =========================fig, ax = plt.subplots(figsize=(10, 7), dpi=150)# 先画真实高程色带层,这个对象直接用于 colorbarim = ax.imshow(    Z,    extent=[x.min(), x.max(), y.min(), y.max()],    origin="lower",    cmap="terrain",    aspect="auto")# 再叠加灰度 hillshade,增强立体感ax.imshow(    hillshade,    extent=[x.min(), x.max(), y.min(), y.max()],    origin="lower",    cmap="gray",    alpha=0.28,    aspect="auto")# 叠加等高线levels = np.linspace(np.nanmin(Z), np.nanmax(Z), 15)contours = ax.contour(    X, Y, Z,    levels=levels,    colors="k",    linewidths=0.55,    alpha=0.38)# 等高线标注ax.clabel(contours, inline=True, fontsize=8, fmt="%.0f")# =========================# 5. 坐标轴设置# =========================ax.set_xlabel("X (km)", fontsize=13)ax.set_ylabel("Y (km)", fontsize=13)ax.set_title("Scientific DEM Visualization from Synthetic Topography",             fontsize=14, pad=12)ax.tick_params(direction="in", length=5, width=1.0)# =========================# 6. colorbar(修正版)# =========================cbar = fig.colorbar(im, ax=ax, fraction=0.045, pad=0.04)cbar.set_label("Elevation (m)", fontsize=12)cbar.ax.tick_params(labelsize=10, direction="in")# =========================# 7. 图内说明框# =========================txt = (    "Synthetic DEM example\n"    "Color: elevation\n"    "Shading: hillshade\n"    "Contours: topographic lines")ax.text(    0.02, 0.98, txt,    transform=ax.transAxes,    ha="left", va="top",    fontsize=10,    bbox=dict(        boxstyle="round,pad=0.3",        facecolor="white",        alpha=0.70,        edgecolor="gray"    ))# =========================# 8. 输出# =========================plt.tight_layout()plt.savefig(OUT_FIG, dpi=300, bbox_inches="tight")plt.show()print(f"图像已保存:{OUT_FIG}")

    特别声明:

    以上代码与文案均为网上资料整合而成,仅供广大同行们参考学习,如有侵权请联系删除。

    如有其他需要,欢迎关注我的咸鱼号:pfc小姐姐

    最新文章

    随机文章