如何提取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)的像素,而非整个figurepad_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
相关产品推荐
相关产品推荐

