PyTorch DataLoader加载64位TIFF图像报通道数错误问题求解
问题根因
报错TypeError: Input image tensor permitted channel values are [3], but found 128由两个核心问题导致:
- 自定义loader的返回格式不符合torchvision数据集的预期:你在rasterio读取分支里做了冗余的tensor-numpy-tensor转换,且直接返回tensor类型,打破了原生loader返回PIL/accimage图像对象(HWC维度顺序)的约定,极易导致后续transform逻辑把空间维度(比如宽度为128的维度)识别为通道维度。
- 预处理流水线硬编码了3通道RGB逻辑:你大概率直接复用了面向普通RGB图像的transform配置(比如固定3通道的Normalize参数、适配8位图像的ToTensor逻辑),既没有适配64位TIFF的高位深属性,也没有处理维度错位后的通道数校验问题。
如果你的TIFF是高光谱等真实多波段数据,rasterio默认读取全部波段会返回128通道数组,和3通道预处理逻辑冲突也会触发同类报错。
排查步骤
- 单步调试loader:取一张报错的TIFF文件,单独执行rasterio读取逻辑,打印返回数组的
shape和dtype,确认是真实存在128个波段,还是维度顺序错位导致空间维被识别为通道维。 - 检查transform流水线:移除所有硬编码3通道的配置,确认没有对已经是tensor类型的输入重复执行ToTensor转换(ToTensor仅对PIL/numpy数组生效,输入tensor时会直接透传,不会修正维度顺序)。
- 核对CustomImageFolder实现:确认自定义类没有在调用loader后额外修改图像维度顺序,和原生ImageFolder的处理逻辑保持一致。
可落地的兼容实现
以下修正版loader完全对齐torchvision原生loader的返回约定,同时支持普通PNG/JPG和64位TIFF读取,无需大幅修改原有数据集逻辑:
from typing import Any import numpy as np import torch from PIL import Image import accimage import rasterio from torchvision import get_image_backend def pil_loader(path: str) -> Image.Image: with open(path, "rb") as f: img = Image.open(f) # 单通道图像此处改为return img.convert("L") return img.convert("RGB") def accimage_loader(path: str) -> Any: try: return accimage.Image(path) except Exception: with rasterio.open(path) as src: img_arr = src.read() # 对齐PIL/accimage返回的HWC维度顺序 if img_arr.shape[0] == 1: # 单通道图像压缩通道维度,返回(H,W)格式 img_arr = img_arr.squeeze(0) else: # 多通道图像从CHW转为HWC img_arr = img_arr.transpose(1, 2, 0) # 高位深图像转float32避免PIL转换报错 if img_arr.dtype not in [np.uint8, np.int32]: img_arr = img_arr.astype(np.float32) return Image.fromarray(img_arr) def default_loader(path: str) -> Any: if get_image_backend() == "accimage": return accimage_loader(path) else: try: return pil_loader(path) except Exception: # PIL读取失败时走rasterio兜底 with rasterio.open(path) as src: img_arr = src.read() if img_arr.shape[0] == 1: img_arr = img_arr.squeeze(0) else: img_arr = img_arr.transpose(1, 2, 0) if img_arr.dtype not in [np.uint8, np.int32]: img_arr = img_arr.astype(np.float32) return Image.fromarray(img_arr)
使用注意事项
- 如果处理单通道64位TIFF(医学影像、深度图、DEM等),将
pil_loader中的convert("RGB")改为convert("L"),同时将后续Normalize的均值、标准差改为单通道对应值,不要复用3通道RGB的预处理参数。 - 如果处理真实128波段的高光谱TIFF,不要将数组转为PIL Image(PIL最多支持4通道),直接返回HWC格式的numpy数组,保留transform中的ToTensor(会自动完成HWC到CHW的tensor维度转换),同步修改预处理和模型首层输入通道数为128即可。
- 不要在loader中直接返回torch.Tensor,所有tensor转换、归一化逻辑统一放在transform流水线中处理,避免维度顺序混乱。
内容的提问来源于stack exchange,提问作者Anthony Knighton
相关产品推荐
相关产品推荐

