你是否厌倦了ArcGIS默认生成的、配色单调的等高线图?是否曾希望自己绘制的地形图能像专业期刊插图一样,既精确又美观,让甲方眼前一亮?
今天,我们就用Python的Matplotlib库,解锁等高线绘制的高级玩法。你将学会如何摆脱软件默认束缚,实现真正的“配色自由”,做出比传统GIS软件出图更漂亮、更具表现力的地形可视化作品。
一张图的配色,决定了它80%的视觉冲击力和专业感。
ArcGIS等专业软件功能强大,但其默认的配色方案往往保守、单一,难以满足个性化汇报、学术出版或高端项目展示的需求。自定义配色不仅能:
掌握Matplotlib绘制等高线,意味着你将数据呈现的主动权牢牢握在自己手中。
首先,确保你的Python环境已安装NumPy和Matplotlib。
import numpy as npimport matplotlib.pyplot as plt加入设置中文字体及负号以免无法显示中文
# 设置中文字体plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans'] # 用来正常显示中文标签plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号创建一个模拟的山地地形数据作为示例。在实际应用中,你可以将Z替换为你自己的高程数据矩阵(例如从DEM数据读取)。
# 生成模拟地形数据x = np.linspace(-5, 5, 100)y = np.linspace(-5, 5, 100)X, Y = np.meshgrid(x, y) # 生成网格坐标Z = np.sin(np.sqrt(X**2 + Y**2)) + 0.1 * np.cos(5*X) # 模拟高程值绘制等高线填充图(地形)和等高线(地形线)是两步核心操作。
# 创建一个图形plt.figure(figsize=(8, 6), dpi=150) # 设置高清画布# 1. 绘制填充等高线(地形色块)# `contourf`是关键,levels控制等高线分级数,cmap控制配色方案cs = plt.contourf(X, Y, Z, levels=20, cmap='terrain', alpha=0.9)# 2. 添加等高线(地形线)# 在填充图上叠加轮廓线,使地形起伏更清晰contour_lines = plt.contour(X, Y, Z, levels=20, colors='black', linewidths=0.5, alpha=0.6)# 3. 添加颜色条plt.colorbar(cs, label='高程 (模拟单位)')# 4. 添加标题和标签plt.title('自定义配色等高线地形图', fontsize=14, pad=15)plt.xlabel('X 坐标')plt.ylabel('Y 坐标')# 5. 显示图形plt.tight_layout()plt.show()运行这段代码,你将得到一张基础但已比默认样式美观的等高线图。

Matplotlib提供了海量的内置配色方案(Colormap),但如何选择和应用才是关键。
地形专用色系:
plt.contourf(X, Y, Z, cmap='gist_earth')'terrain': 经典地形色,从绿色(低地)到棕色(山地)再到白色(雪山)。'gist_earth': 另一种逼真的地球表面配色。连续渐变色系(突出高程变化):
plt.contourf(X, Y, Z, cmap='plasma')'viridis' / 'plasma': 现代、悦目且色盲友好的科学配色。'summer' / 'wistia': 温暖明亮的色调。离散阶梯配色(清晰区分高度带): 使用ListedColormap自定义颜色列表,适合法规图或需要明确分级的场景。
from matplotlib.colors import ListedColormap# 自定义一个从蓝到红的分级色带custom_cmap = ListedColormap(['#2E86AB', '#A23B72', '#F18F01', '#C73E1D'])plt.contourf(X, Y, Z, levels=4, cmap=custom_cmap)色盲友好原则: 避免同时使用红-绿对比。优先选择'viridis', 'plasma', 'cividis'等经过设计的色盲友好配色。
让我们将所学组合,生成一张可直接用于展示的“王牌”地形图。
import numpy as npimport matplotlib.pyplot as pltfrom matplotlib.colors import LinearSegmentedColormap# 设置中文字体plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei', 'DejaVu Sans'] # 用来正常显示中文标签plt.rcParams['axes.unicode_minus'] = False# 用来正常显示负号# 1. 生成更自然、复杂的地形数据np.random.seed(42) # 固定随机种子,使结果可重现# 提高分辨率使等高线更圆滑x = np.linspace(-3, 3, 500) # 增加点数y = np.linspace(-3, 3, 500)X, Y = np.meshgrid(x, y)# 创建复杂地形:多个高斯峰的组合 + 噪声 + 山脉结构# 使用更平滑的函数组合Z = (# 主峰2.5 * np.exp(-((X-1.2)**2 + (Y-0.8)**2)/0.6) +# 次峰2.0 * np.exp(-((X+1.5)**2 + (Y+1.2)**2)/1.0) +1.8 * np.exp(-((X+0.5)**2 + (Y-1.8)**2)/0.8) +# 山脊线1.5 * np.exp(-((X+1.8)**2 + (Y-1.0)**2)/1.2) +1.2 * np.exp(-((X-1.8)**2 + (Y+1.3)**2)/1.1) +# 山谷和起伏0.6 * np.sin(X*2.5) * np.cos(Y*2.0) * np.exp(-(X**2+Y**2)/6) +# 添加一些线状结构0.7 * np.exp(-((X*0.7 + Y*0.7 - 1.2)**2)/0.2) +0.6 * np.exp(-((X*0.6 - Y*0.8 + 1.3)**2)/0.25) +0.5 * np.exp(-((X*0.9 - Y*0.4 - 1.5)**2)/0.3))# 添加一个断裂结构fault = 1.0 / (1 + np.exp(-(X - Y*0.4 + 1.2)*6))Z = Z * (1 + 0.25*fault)# 手动实现简单的平滑处理(使等高线更圆滑)def smooth_terrain(Z, iterations=2):"""简单的平滑处理""" Z_smooth = Z.copy()for _ in range(iterations): Z_temp = Z_smooth.copy()# 四点平均(上下左右) Z_smooth[1:-1, 1:-1] = ( Z_temp[1:-1, 1:-1] * 0.4 + # 中心点权重 (Z_temp[:-2, 1:-1] + Z_temp[2:, 1:-1] + Z_temp[1:-1, :-2] + Z_temp[1:-1, 2:]) * 0.15# 邻居点权重 )return Z_smooth# 应用平滑Z = smooth_terrain(Z, iterations=2)# 2. 创建自定义渐变配色colors = ["#2c7bb6", # 深蓝(低海拔)"#abd9e9", # 浅蓝"#ffffbf", # 浅黄"#fdae61", # 橙黄"#d7191c", # 红色(高海拔)]my_cmap = LinearSegmentedColormap.from_list("RealTerrain", colors, N=100)# 3. 绘图fig, ax = plt.subplots(figsize=(12, 10), dpi=150)# 填充地形 - 增加填充级别数使过渡更平滑levels_filled = np.linspace(Z.min(), Z.max(), 50)cf = ax.contourf(X, Y, Z, levels=levels_filled, cmap=my_cmap, extend='both', antialiased=True)# 叠加等高线 - 增加等高线数量使地形更精细levels_contour = np.linspace(Z.min() + 0.2, Z.max() - 0.2, 20)cl = ax.contour(X, Y, Z, levels=levels_contour, colors='black', linewidths=0.5, alpha=0.5, antialiased=True)# 等高线标注(选择有代表性的进行标注)# 自动选择一些位置进行标注ax.clabel(cl, inline=True, fontsize=8, fmt='%1.1f', inline_spacing=3)# 添加山脊线或特殊地形标注ax.text(1.0, 0.5, '主峰', fontsize=10, color='white', weight='bold', bbox=dict(facecolor='black', alpha=0.6, boxstyle='round,pad=0.3'))ax.text(-1.8, -1.2, '山谷', fontsize=10, color='white', weight='bold', bbox=dict(facecolor='black', alpha=0.6, boxstyle='round,pad=0.3'))# 颜色条cbar = fig.colorbar(cf, ax=ax, shrink=0.8, pad=0.02, extend='both')cbar.set_label('海拔高度 (m)', rotation=270, labelpad=20, fontsize=11)# 美化ax.set_title('真实地形等高线图 - 非对称山脉系统', fontsize=16, weight='bold', pad=20)ax.set_xlabel('东向坐标 (km)', fontsize=11)ax.set_ylabel('北向坐标 (km)', fontsize=11)ax.set_aspect('equal')# 添加比例尺ax.plot([-2.5, -1.5], [-2.5, -2.5], 'k-', linewidth=3)ax.text(-2, -2.6, '1 km', ha='center', fontsize=10, color='black')# 设置坐标轴范围ax.set_xlim(-3, 3)ax.set_ylim(-3, 3)# 添加浅色网格ax.grid(True, linestyle='--', alpha=0.2, color='gray', linewidth=0.5)# 添加指北针ax.annotate('N', xy=(2.7, 2.7), xytext=(2.8, 2.8), arrowprops=dict(arrowstyle='->', color='black', lw=2), fontsize=12, weight='bold')# 添加地形特征标注ax.scatter([1.2, -1.5, -0.5], [0.8, -1.2, 1.8], c='white', s=30, edgecolors='black', linewidths=1, zorder=5)plt.tight_layout()plt.savefig('realistic_terrain_contour.png', dpi=300, bbox_inches='tight', facecolor='white')plt.show()# 打印地形信息print(f"地形统计信息:")print(f"最低点: {Z.min():.2f}")print(f"最高点: {Z.max():.2f}")print(f"高差: {Z.max() - Z.min():.2f}")print(f"数据点数量: {Z.shape[0]} x {Z.shape[1]}")
理论再好,不如亲手一试。将上面的代码模板中的X, Y, Z替换为你自己的数据(例如,使用np.loadtxt加载CSV高程数据),并尝试更换不同的cmap参数。
你的行动步骤:
Z。levels(分级数)、alpha(透明度)和等高线linewidths(线宽),直到效果满意。plt.savefig()保存高清图片,惊艳你的观众。把上面的配色策略应用到你自己的地形数据中,收藏本教程便于快速查找。
从此,告别千篇一律的默认出图,用代码绘制出既有科学深度又有视觉美感的专业地形图。你的下一个项目展示,就从这张与众不同的等高线图开始吧!
#Python实战 #绘图技巧 #干货分享 #GIS替代方案 #科研绘图 #可视化教程 #地形制图
以往文章合集: