匹配绘图尺寸与数据尺寸:Matplotlib填充等高线绘图问题
解决Matplotlib填充等高线气象数据绘图异常问题
问题现象
使用Matplotlib的contourf绘制Numpy数组存储的降水量气象数据时,出现两个异常:
- 无数据区域存在异常间隙(已确认源数组本身无此类间隙)
- 数值边缘出现不应有的异常线条
尝试开启抗锯齿无效,怀疑是绘图尺寸/分辨率与源数组不匹配导致,希望实现每个像素对应数组中的一个点。
问题代码
imageRes = 50 aspectRatio = 1.5 plotProj = ccrs.PlateCarree() # from cartopy fig,ax = plt.subplots(ncols=1, nrows=1, subplot_kw={'projection':plotProj, 'aspect':aspectRatio}, dpi=imageRes, figsize=(imageSettings.heicImageWidth/imageRes, imageSettings.heicImageHeight/imageRes)) fig.patch.set_visible(False) ax.contourf(lon,lat,item,vmin=minValue,vmax=maxValue, extend='max', transform=plotProj,colors=colors[index], levels=levels[index], hatches=hatches[index], antialiased=False) ax.set_extent([-125.0,-66.0, 24.0, 54.0], crs=plotProj) ax.axis('off') plt.savefig(buffer, pad_inches=0, bbox_inches="tight", transparent=True, dpi=imageRes) img = img.resize((int(imageSettings.heicImageWidth), int(imageSettings.heicImageHeight)), resample = Image.LANCZOS) img.save(outputFilename, quality = imageSettings.heicImageQuality)
问题图示

核心原因
contourf是基于等高线插值的绘图函数,会对数据进行拟合插值,无法保证数组点与像素一一对应,自然会产生边缘异常线条- 先低分辨率绘图再二次缩放的操作,进一步放大了间隙和线条问题
修正方案
1. 替换为像素级渲染函数:pcolormesh
pcolormesh专为规则网格数据设计,直接将每个网格单元映射为图像像素,彻底避免插值异常:
# 替换原contourf代码 ax.pcolormesh(lon, lat, item, vmin=minValue, vmax=maxValue, transform=plotProj, cmap=colors[index], shading='nearest', hatches=hatches[index])
shading='nearest'确保每个数组点对应一个像素- 若需要扩展极值显示,用
norm=matplotlib.colors.ClampNorm(vmin=minValue, vmax=maxValue)替代extend='max'
2. 取消二次缩放,直接匹配目标分辨率
跳过img.resize步骤,让绘图的dpi与figsize乘积直接等于目标图片尺寸,保证原始绘图精度:
target_width = imageSettings.heicImageWidth target_height = imageSettings.heicImageHeight dpi = 100 # 可根据需求调整,建议用96/100/150等标准值 fig, ax = plt.subplots( ncols=1, nrows=1, subplot_kw={'projection': plotProj, 'aspect': aspectRatio}, dpi=dpi, figsize=(target_width/dpi, target_height/dpi) ) # 直接保存为目标尺寸,无需后续缩放 plt.savefig(outputFilename, pad_inches=0, bbox_inches="tight", transparent=True, dpi=dpi, quality=imageSettings.heicImageQuality)
3. 处理无数据区域
若源数组包含NaN值,可设置统一的无数据填充色:
# 自定义无数据区域颜色,示例为灰色 ax.set_facecolor('#cccccc')
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

