【问题标题】:Error in Transforming custom Dataset in Pytorch在 Pytorch 中转换自定义数据集时出错
【发布时间】:2020-04-10 18:28:46
【问题描述】:

我正在关注本教程:https://pytorch.org/tutorials/beginner/data_loading_tutorial.html 为 MuNuSeg 数据集制作了我自己的自定义数据加载器,但我被卡住了。数据加载器工作正常,但是当我向它添加转换时,我得到了错误。

我面临的问题类似于此处提到的问题: Error Utilizing Pytorch Transforms and Custom Dataset
根据那里的答案,我为每个内置转换进行了自定义转换,以便同时转换一个完整的样本。以下是我的自定义转换

class AffineTrans(object):
def __init__(self, degrees, translate):
    self.degrees = degrees
    self.translate = translate

def __call__(self, sample):
    image, contour, clrmask = sample['image'], sample['contour'], sample['clrmask']
    TF = transforms.RandomAffine(degrees = self.degrees, translate=self.translate)
    image = TF(image)
    contour = TF(contour)
    clrmask = (clrmask)

class Flip(object):   
def __call__(self, sample):
    image, contour, clrmask = sample['image'], sample['contour'], sample['clrmask']
    TF1 = transforms.RandomHorizontalFlip()
    TF2 = transforms.RandomVerticalFlip()
    image = TF1(image)
    contour = TF1(contour)
    clrmask = TF1(clrmask)
    image = TF2(image)
    contour = TF2(contour)
    clrmask = TF2(clrmask)

class ClrJitter(object):
def __init__(self, brightness, contrast, saturation, hue):
    self.brightness = brightness
    self.contrast = contrast
    self.saturation = saturation
    self.hue = hue

def __call__(self, sample):
    image, contour, clrmask = sample['image'], sample['contour'], sample['clrmask']
    TF = transforms.ColorJitter(self.brightness, self.contrast, self.saturation, self.hue)
    image = TF(image)
    contour = TF(contour)
    clrmask = TF(clrmask)

并按以下方式组合它们

composed = transforms.Compose([RandomCrop(256),
                           AffineTrans(15.0,(0.1,0.1)),
                           Flip(),    
                           ClrJitter(10, 10, 10, 0.01),
                           ToTensor()])

这是 trainLoader 代码

class trainLoader(Dataset):
def __init__(self, transform=None):
    """
    Args:
        transform (callable, optional): Optional transform to be applied
            on a sample.
    """
    [self.train_data , self.test_data1, self.test_data2] = dirload()
    self.transform = transform

def __len__(self):
    return(len(self.train_data[0]))

def __getitem__(self, idx):
    if torch.is_tensor(idx):
        idx = idx.tolist()
    img_name = self.train_data[0][idx]
    contour_name = self.train_data[1][idx]
    color_name = self.train_data[2][idx]
    image = cv2.imread(img_name)
    contour = cv2.imread(contour_name)
    clrmask = cv2.imread(color_name)
    sample = {'image': image, 'contour': contour, 'clrmask': clrmask}

    if self.transform:
        sample = self.transform(sample)

    return sample

要检查上述代码的工作情况,我正在执行以下操作

    train_dat = trainLoader(composed)

for i in range(len(train_dat)):
    sample = train_dat[i]

    print(i, sample['image'].shape, sample['contour'].shape, sample['clrmask'].shape)
    cv2.imshow('sample',sample['image'])
    cv2.waitKey()
    if i == 3:
        break

但我仍然一次又一次地遇到以下错误

runcell(0, 'F:/Moodle/SEM 8/SRE/code/MoNuSeg/main.py')

runcell(1, 'F:/Moodle/SEM 8/SRE/code/MoNuSeg/main.py')
Traceback (most recent call last):

  File "F:\Moodle\SEM 8\SRE\code\MoNuSeg\main.py", line 212, in <module>
    sample = train_dat[i]

  File "F:\Moodle\SEM 8\SRE\code\MoNuSeg\main.py", line 109, in __getitem__
    sample = self.transform(sample)

  File "F:\Moodle\Anaconda3\lib\site-packages\torchvision\transforms\transforms.py", line 60, in __call__
    img = t(img)

  File "F:\Moodle\SEM 8\SRE\code\MoNuSeg\main.py", line 156, in __call__
    image = TF(image)

  File "F:\Moodle\Anaconda3\lib\site-packages\torchvision\transforms\transforms.py", line 1018, in __call__
    ret = self.get_params(self.degrees, self.translate, self.scale, self.shear, img.size)

  File "F:\Moodle\Anaconda3\lib\site-packages\torchvision\transforms\transforms.py", line 992, in get_params
    max_dx = translate[0] * img_size[0]

TypeError: 'int' object is not subscriptable

这是一个非常模糊的错误,因为我完全不明白错误是什么

任何帮助将不胜感激

【问题讨论】:

    标签: python python-3.x pytorch dataloader


    【解决方案1】:

    问题是您传递的是一个 NumPy 数组,而转换需要一个 PIL 图像。您可以通过添加 transforms.ToPILImage() 作为第一个转换来解决此问题:

    composed = transforms.Compose([
        transforms.ToPILImage(),
        RandomCrop(256),
        AffineTrans(15.0,(0.1,0.1)),
        Flip(),    
        ClrJitter(10, 10, 10, 0.01),
        ToTensor()
    ])
    

    假设您在开头有一个from torchvision import transforms

    问题的根源在于您正在使用 OpenCV 加载图像:

    def __getitem__(self, idx):
        # [...]
        image = cv2.imread(img_name)
    

    您也可以将这些加载调用从 OpenCV 替换为 PIL 来解决问题。


    您知道,对于 NumPy 数组,.size() 返回一个 int,这会导致您出现问题。检查以下代码的区别:

    import numpy as np
    from PIL import Image
    
    # NumPy
    img = np.zeros((30, 30))
    print(img.size)  # output: 900
    
    # PIL
    pil_img = Image.fromarray(img)
    print(pil_img.size)  # output: (30, 30)
    

    【讨论】:

    • 感谢@Berriel,您正确指出需要先将图像转换为 PIL。我能够以类似的方式解决这个问题,但我没有使用 ToPILImage,因为我仍然收到与 ToPILImage 相关的错误。所以我从 PIL 导入 Image 并使用 Image.open() 而不是 cv2.imread。
    猜你喜欢
    • 2018-09-17
    • 2020-10-06
    • 1970-01-01
    • 1970-01-01
    • 2020-02-18
    • 1970-01-01
    • 2020-09-28
    • 2021-07-21
    • 2017-09-12
    相关资源
    最近更新 更多