无法通过BytesIO读取S3桶中16位TIF并转换为NumPy数组求助
解决S3中16位TIF不落地转NumPy数组的问题
方案一:纠正GDAL使用误解(无本地副本)
你之前用GDAL配合/vsimem/路径的方式不会生成本地磁盘文件——/vsimem/是GDAL内置的内存虚拟文件系统,所有操作都在内存中完成,完全满足“不保存到本地”的需求,代码可直接使用:
from osgeo import gdal import boto3 from io import BytesIO s3 = boto3.client('s3', aws_access_key_id=access_id, aws_secret_access_key=secret_key, region_name=region_name) myBytesObject = BytesIO() s3.download_fileobj(bucket_name, tif_name, myBytesObject) myBytesObject.seek(0) # 内存虚拟文件,无磁盘写入操作 vsipath = '/vsimem/temp.tif' gdal.FileFromMemBuffer(vsipath, myBytesObject.read()) gimg = gdal.Open(vsipath) if gimg is not None: img_array = gimg.GetRasterBand(1).ReadAsArray() # 处理后释放内存资源 gdal.Unlink(vsipath) del gimg
方案二:使用rasterio直接读取BytesIO
rasterio对16位TIF兼容性更好,支持直接从BytesIO对象读取,代码更简洁:
import rasterio import boto3 from io import BytesIO s3 = boto3.client('s3', aws_access_key_id=access_id, aws_secret_access_key=secret_key, region_name=region_name) myBytesObject = BytesIO() s3.download_fileobj(bucket_name, tif_name, myBytesObject) myBytesObject.seek(0) with rasterio.open(myBytesObject) as src: img_array = src.read(1) # 读取单波段,多波段可直接用src.read()
方案三:修复PIL的16位TIF支持问题
若坚持用PIL,需确保安装最新版Pillow(或Pillow-SIMD优化性能),避免提前调用convert('RGB')破坏16位数据结构:
from PIL import Image import numpy as np import boto3 from io import BytesIO s3 = boto3.client('s3', aws_access_key_id=access_id, aws_secret_access_key=secret_key, region_name=region_name) myBytesObject = BytesIO() s3.download_fileobj(bucket_name, tif_name, myBytesObject) myBytesObject.seek(0) # 直接打开16位TIF并转NumPy数组 img = Image.open(myBytesObject) img_array = np.array(img)
错误原因说明
- PIL报错
UnidentifiedImageError:多为Pillow版本过旧,不支持目标16位TIF的编码格式,更新Pillow即可解决。 - skimage报错
KeyError:默认TIF读取器对特殊编码的16位TIF兼容性较差,改用rasterio或GDAL更稳定。
内容的提问来源于stack exchange,提问作者fariadantes
相关产品推荐
相关产品推荐

