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

PyTorch加载可变尺寸图像转Tensor报错:无法转换numpy.object_类型

解决PyTorch加载可变尺寸图像时的Tensor转换错误

你遇到的这个问题其实是处理可变尺寸图像时的典型误区——PyTorch的Tensor要求所有元素的形状完全一致,但你把不同尺寸的图像打包成了numpy object数组,这种数组里的每个元素形状都不一样,自然无法直接转换成Tensor。下面是具体的解决步骤:

第一步:调整图像加载逻辑,保留原始图像列表

首先修改你的get_imgs函数,不需要把图像转成numpy object数组,直接用Python列表存储每张图像即可:

def get_imgs(path_to_imgs):
    imgs = []
    for path in path_to_imgs:
        # 注意cv2.imread返回的是BGR格式,如果需要RGB可以用img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        img = cv2.imread(path)
        imgs.append(img)
    return imgs  # 直接返回列表,跳过numpy数组转换

第二步:重构Dataset类,在单样本获取时转换Tensor

不要在__init__里批量转换所有图像,而是在__getitem__中单独处理单张图像——这样每张图像的形状不同也没关系,因为我们是逐个转换:

import torch
import cv2
from torch.utils.data import Dataset, DataLoader

class VariableSizeImageDataset(Dataset):
    def __init__(self, path_to_imgs, path_to_label):
        self.path_to_imgs = path_to_imgs
        self.path_to_label = path_to_label
        self.imgs = get_imgs(path_to_imgs)
        self.labels = get_pts(path_to_label)  # 假设你的get_pts返回形状统一的标签数据

    def __len__(self):
        return len(self.imgs)

    def __getitem__(self, index):
        # 处理单张图像:从numpy转Tensor,同时转换通道顺序(cv2是HWC,PyTorch用CHW)
        img = self.imgs[index]
        # 转成float32并归一化(可选,根据你的模型需求调整)
        img_tensor = torch.from_numpy(img).permute(2, 0, 1).float() / 255.0
        
        # 处理标签:如果标签形状统一,直接转成Tensor
        label = self.labels[index]
        label_tensor = torch.tensor(label, dtype=torch.float32)  # 标签类型按需调整
        
        return img_tensor, label_tensor

第三步:处理DataLoader的批量问题

默认的DataLoader会尝试把batch里的Tensor堆叠成一个大Tensor,但可变尺寸图像形状不一致,无法堆叠。这里有两种解决方案:

方案1:将batch打包成列表(适合目标检测、分割等不需要统一输入尺寸的任务)

自定义collate_fn,把batch里的图像保留为列表,标签正常堆叠:

def custom_collate_fn(batch):
    # batch是列表,每个元素是(__getitem__返回的img_tensor, label_tensor)
    imgs = [item[0] for item in batch]
    labels = torch.stack([item[1] for item in batch])  # 标签形状统一时可以直接堆叠
    return imgs, labels

# 创建DataLoader
dataloader = DataLoader(
    VariableSizeImageDataset(path_to_imgs, path_to_label),
    batch_size=4,
    shuffle=True,
    collate_fn=custom_collate_fn
)

方案2:对图像做padding,统一batch内尺寸(适合要求固定输入形状的模型)

如果你的模型需要固定尺寸的输入,可以在collate_fn里对当前batch的图像做padding,补到该batch的最大尺寸:

def collate_fn_with_padding(batch):
    imgs, labels = zip(*batch)
    # 获取当前batch的最大高度和宽度
    max_h = max(img.shape[1] for img in imgs)
    max_w = max(img.shape[2] for img in imgs)
    
    padded_imgs = []
    for img in imgs:
        c, h, w = img.shape
        # 计算需要补的像素数,这里默认补0,你也可以用均值或其他值
        pad_h = max_h - h
        pad_w = max_w - w
        # PyTorch的pad顺序是(左, 右, 上, 下),对应最后两个维度
        padded_img = torch.nn.functional.pad(img, (0, pad_w, 0, pad_h), mode='constant', value=0)
        padded_imgs.append(padded_img)
    
    # 堆叠成统一形状的batch Tensor
    padded_imgs = torch.stack(padded_imgs)
    labels = torch.stack(labels)
    return padded_imgs, labels

# 使用带padding的collate_fn创建DataLoader
dataloader = DataLoader(
    VariableSizeImageDataset(path_to_imgs, path_to_label),
    batch_size=4,
    shuffle=True,
    collate_fn=collate_fn_with_padding
)

核心思路就是:不要提前批量处理可变尺寸的图像,而是逐个样本转换,再通过自定义collate_fn适配批量逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 20:17:54