【问题标题】:How do I load multiple grayscale images as a single tensor in pytorch?如何在 pytorch 中将多个灰度图像作为单个张量加载?
【发布时间】:2020-03-15 09:12:24
【问题描述】:

我目前正在尝试使用堆栈一组图像作为每个标签的单个实体来训练 CNN 使用交叉验证。给定一个 224x224x1 灰度图像的数据集,按以下方式排序:

Root/
    Class0/image0_view0.png
    Class0/image0_view1.png
    Class0/image0_view2.png
    ...
    Class1/image0_view0.png
    Class1/image0_view1.png
    Class1/image0_view2.png

如何将 3 张图像(视图 0、1 和 2)作为尺寸为 224x224x3(3 张灰度图像)的单个张量流动?换句话说,我将如何使用 ImageFolder/DatasetFolder 和 DataLoader 在 pytorch 中创建图像堆栈数据集?我是否必须重新组织我的文件夹和类,还是在为交叉验证进行拆分时更容易制作堆栈?

感谢您的宝贵时间和帮助!如果我能提供更多信息,请告诉我。

【问题讨论】:

  • 为什么要这样做?您希望图像的通道是其他图像吗?如果我知道原因,我可能会更好地指导你。看起来你想要的可能根本不需要 pytorch。您只需要读取图像并将它们堆叠,然后将它们保存为具有 3 个通道的新图像。
  • 这对我来说很有意义。我想这样做是因为每个标签并不总是单独出现在一张图像上,而且当我尝试将所有 3 张图像蒙合成一张图像时,CNN 的表现也不是很好。
  • 好的,所以在我看来,您遇到了一个分类问题,即只能从同一对象的 3 个“视图”中的 1 个中看到该类。与其将图像合并在一起并尝试分类,我可能建议只为所有 3 个图像单独生成分类,然后将预测合并为一个。因此,如果 view0 预测了 1 类,而 view1 没有预测,而 view2 预测了 2 类,则总体预测将是 1 类和 2 类。
  • 这些标签是为图像集生成的,因此虽然您的建议绝对可行,但它会更耗时且计算成本更高。您对图像堆叠有什么顾虑?

标签: deep-learning conv-neural-network pytorch


【解决方案1】:

我有一个非常相似的任务。我需要加载 3 张图像的随机序列作为批次的一个元素,以便不是在单独的图像上而是在图像序列上训练网络。对于批量大小 8,我有 8 x 3 = 24 张图像。在您的情况下,这似乎与不同的观点非常相似。我使用了 skimage.io 的 imread_collection 功能。我在 Dataset 类中添加了这样一个 getitem

def __getitem__(self, idx):
    idx_q = int(torch.randint(0 + self.boundary, self.length - self.boundary, (1,))) 
    
    q = imread_collection([self.image_paths[idx_q-1], self.image_paths[idx_q], self.image_paths[idx_q+1]], conserve_memory=True)
            
    if self.transform:
        q = torch.stack([self.transform(img) for img in q])

    return q, p, n

这里我生成一个图像的随机索引,然后使用 imread_collection 和 self.image_paths 加载三个连续的图像,这是包含所有图像路径的列表。然后我对每个图像进行转换并将它们堆叠起来。在你的情况下,你应该考虑使用正确的索引,也许通过在 self.image_paths 的长度上应用一个滑动窗口。

更多信息可以在torch forum 上找到。我也尝试询问并找到更优雅的解决方案,但无法使用这种方法成功训练模型。

【讨论】:

    【解决方案2】:

    如何在 pytorch 中将多个灰度图像作为单个张量加载?

    一般来说,频道的数量并不重要。

    所谓的“加载一批数据”的操作就是你所需要的。对于这个 PyTorch 有 DataLoader 类。 DataLoader 类还需要Dataset 类。

    如果在 DataLoader 中批量大小为 64 (bs=64),您将从一次加载 64 张图像作为张量。

    如果您使用ImageFolder,这将不会为您返回小批量。 ImageFolderDataset 派生类。

    ImageFolder(如果你只是使用它)的问题是每个索引都会得到一个图像。然后,您可以将多个图像组合成一个小批量。

    这是一个使用 ImageFolder 和 CIFAR10 数据的示例。

    from torchvision import transforms
    imagef = torchvision.datasets.ImageFolder(r'C:\Users\dj\data\cifar10\test', transform=transforms.ToTensor())
    
    print(imagef)
    print(imagef.classes)
    img, label = imagef[0]
    display(img)
    print(img.size())
    print(label)
    

    输出:

    Dataset ImageFolder
        Number of datapoints: 10000
        Root location: C:\Users\dj\data\cifar10\test
        StandardTransform
    Transform: ToTensor()
    ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
    
    tensor([[[0.6078, 0.6549, 0.6902,  ..., 0.7882, 0.7922, 0.7529],
             [0.6000, 0.6392, 0.6706,  ..., 0.7922, 0.7961, 0.7412],
             [0.6078, 0.6275, 0.6588,  ..., 0.8078, 0.8000, 0.7412],
             ...,
             [0.3490, 0.2235, 0.2392,  ..., 0.3490, 0.2314, 0.2627],
             [0.3490, 0.2353, 0.2471,  ..., 0.2235, 0.2392, 0.2941],
             [0.3608, 0.2353, 0.2392,  ..., 0.2353, 0.2510, 0.2863]], ...
    
    
    torch.Size([3, 32, 32])
    0
    

    下一个例子是基于DataLoader

    import torch
    from torch.utils.data import DataLoader, Dataset
    import torchvision
    from torchvision import transforms
    import PIL.Image as Image
    
    def pil_loader(path):    
        with open(path, 'rb') as f:
            img = Image.open(f)
            return img.convert('RGB')
    
    ds = torchvision.datasets.DatasetFolder(r'C:\Users\dj\data\cifar10\test', 
                                            loader=pil_loader, 
                                            extensions=('.png'), 
                                            transform=transforms.ToTensor())
    dl = DataLoader(ds, batch_size=2)
    len(dl)
    for imgs,lbls in dl:    
        print(imgs.size()) # torch.Size([2, 3, 32, 32])
        break 
    

    这个DataLoader 是您可能需要的。我介绍的那个,有自定义加载功能:pil_loader

    您也可以使用ImageFolder 代替前面示例中的DatasetFolder

    应该是这样的:

    ds =  torchvision.datasets.ImageFolder(r'C:\Users\dj\data\cifar10\test', transform=transforms.ToTensor())
    dl = DataLoader(ds, batch_size=3)
    print(len(dl))
    
    for imgs,lbls in dl:    
        print(imgs.size())
        break    
    

    【讨论】:

    • 我不认为使用批处理可以解决这里的问题。 OP 似乎希望将所有 3 张图像作为单个输入传递给网络并生成单个标签。在批次的情况下,这将导致预测数量等于批次大小。
    猜你喜欢
    • 2021-04-05
    • 2021-06-29
    • 2019-02-25
    • 2020-05-23
    • 2018-04-27
    • 2020-10-31
    • 2018-10-29
    • 1970-01-01
    • 2020-12-19
    相关资源
    最近更新 更多