You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何提取Cartopy绘图为NumPy数组并去除透明边框?

如何去除Cartopy绘图转NumPy数组时的白色透明边框?

我明白你的问题——用Cartopy绘制区域图后转成NumPy数组,结果里面混了一大堆[255 255 255 0]的透明边框像素,即使调整了subplots_adjust也没解决。核心原因是你当前获取的是整个figure的像素数据,而figure默认会包含一些不可见的额外区域,加上保存时没精准裁剪到绘图的axes范围,才会出现这些无效像素。

下面给你两个可行的解决方案:


方案1:精准裁剪Axes区域并调整保存参数

修改你的代码,在保存时指定只裁剪到axes的边界,同时调整参数消除额外边距:

import matplotlib.pyplot as plt
import numpy as np
import cartopy
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import io

MIN_LAT = 19
MAX_LAT = 53
MIN_LON = -20
MAX_LON = 41

# 初始化绘图
fig = plt.figure()
proj = ccrs.PlateCarree(central_longitude=0)
ax = plt.axes(projection=proj)
ax.add_feature(cfeature.LAND, color='lightgray')
ax.add_feature(cfeature.OCEAN)

# 设置目标区域
ax.set_extent([MIN_LON, MAX_LON, MIN_LAT, MAX_LAT], crs=proj)

# 让axes完全占满figure
fig.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)

io_buf = io.BytesIO()
# 关键:保存时只保留axes区域,无额外填充
fig.savefig(io_buf, format='raw', bbox_inches=ax.bbox, pad_inches=0)
io_buf.seek(0)

# 用axes的尺寸来重塑数组,而非figure的尺寸
img_arr = np.reshape(
    np.frombuffer(io_buf.getvalue(), dtype=np.uint8),
    newshape=(int(ax.bbox.height), int(ax.bbox.width), -1)
)
io_buf.close()

# 验证:打印数组中唯一的像素值
print(np.unique(img_arr, axis=0))

关键调整说明:

  • bbox_inches=ax.bbox:告诉savefig只保存绘图区域(axes)的像素,而非整个figure
  • pad_inches=0:彻底消除保存时的额外边距
  • 用ax.bbox的尺寸替代fig.bbox来重塑数组,确保只加载有效区域的像素

方案2:从Canvas直接提取Axes像素数据

另一种更直接的方式,跳过保存到缓冲区的步骤,直接从matplotlib的canvas中提取axes区域的像素:

import matplotlib.pyplot as plt
import numpy as np
import cartopy
import cartopy.crs as ccrs
import cartopy.feature as cfeature

MIN_LAT = 19
MAX_LAT = 53
MIN_LON = -20
MAX_LON = 41

# 初始化绘图
fig = plt.figure()
proj = ccrs.PlateCarree(central_longitude=0)
ax = plt.axes(projection=proj)
ax.add_feature(cfeature.LAND, color='lightgray')
ax.add_feature(cfeature.OCEAN)

# 设置目标区域
ax.set_extent([MIN_LON, MAX_LON, MIN_LAT, MAX_LAT], crs=proj)

# 强制完成图形绘制
fig.canvas.draw()

# 获取axes在canvas中的像素坐标范围
x1, y1, x2, y2 = ax.bbox.extents
# 转成整数像素位置
x1, x2 = int(np.round(x1)), int(np.round(x2))
y1, y2 = int(np.round(y1)), int(np.round(y2))

# 从canvas提取像素数据(带alpha通道用tostring_argb)
width, height = fig.canvas.get_width_height()
img_arr = np.frombuffer(fig.canvas.tostring_argb(), dtype=np.uint8).reshape(height, width, 4)
# 裁剪到axes的有效区域
img_arr = img_arr[y1:y2, x1:x2]

# 验证:打印唯一像素值
print(np.unique(img_arr, axis=0))
plt.close(fig)

这个方法直接操作canvas的原始像素,避免了savefig可能带来的额外边距问题,结果会更精准。


为什么之前的subplots_adjust没用?

即使你把axes的边距设为0,figure本身的bbox还是会包含一些不可见的背景区域(比如figure的默认留白),而你之前用fig.bbox.bounds来重塑数组,就会把这些无效区域也包含进去。所以必须明确指定要提取的是axes的区域,而非整个figure的范围。

内容的提问来源于stack exchange,提问作者yoyoog

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 21:22:30