事情是这样的,SVHN数据集是一个三通道的RGB数据集,想把它转为单通道的灰度图,你在网上搜索大家都是下面这样使用的:
train_dataset = SVHN('./data', split='train', download=True,
transform=transforms.Compose([
transforms.Resize(28),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
]))
但是当你输出train_dataset.data.shape的时候,结果是(3,32,32),它还是三通道的数据,而且尺寸还是32*32,我明明给它做了transform数据转换,怎么就死活不对呢!!!但是在封装为dataloader后就对了,可是封装之后我就不好对数据进行操作了啊,我要在封装之前进行处理,所以到底是为什么啊!!!
搞了好几天,终于找到毛病出在哪里了:torchvision.transforms图片处理只能处理PIL类型的数据,所以图片要么用PIL.Image读取,要么将ndarray图片数据转成PIL类型
PIL和numpy相互转换方式如下:
from PIL import Image
#PIL image转成numpy
np_img = np.asarray(PIL_img) #参数时PIL类型的图片
或
np_img = np.array(PIL_img)
#将array准成PIL image
Image.fromarray(np.uint8(np_img))
但是直接用Image.fromarray(np.uint8(train_dataset.data))转换会报错:TypeError: Cannot handle this data type: (1, 1, 28, 3), |u1
因为Image.fromarray只能对单个图片进行操作,好的,我变成单个图片:Image.fromarray(np.uint8(train_dataset.data[0])),又TM报错:TypeError: Cannot handle this data type: (1, 1, 28), |u1,又是为啥啊,我哭了,在网上搜了一圈也没找到答案,然后我从可以转换成功的代码入手,终于发现问题了,太难了也
PIL需要的格式是(W,H,C),而SVHN数据集的格式是(C,W,H)
所以又要进行转换了,把(C,W,H)变为(W,H,C):
img.transpose(1,2,0)
最后,终于从np array变成了PIL格式,
transform=transforms.Compose([
transforms.Resize(28),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
for i in range(len(train_dataset.labels)):
tmp = train_dataset.data[i] # 3,32,32 (C,W,H)
trans_img = tmp.transpose(1,2,0) # 32,32,3 (W,H,C)
PIL_img = Image.fromarray(trans_img.astype('uint8'))
tf_img = transform(PIL_img)
终于搞定了!