image读取&转换
z

1. picke 读取数据

许多数据集是使用pickle进行序列化后进行保存的。因此,在还原为图片的时候,使用pickel进行还原:

1
2
3
import pickel
with open(file, "rb") as fo:
data = pickel.load(fo, encoding="bytes")

这里需要注意的是,python3中有encoding参数,而python2中并没有。

在图像领域,一般通过pickle保存读取之后的数据为numpy.narray对象,size为[N, L]。N为总共的图片数量,L为每张图片的像素个数。L = C * W * L

对于读取到的data,需要将其reshape成 W*L*C, 假设图片为 3 * 32 * 32 的大小

1
data = data.reshape(len(data), 3, 32, 32)

2.1 numpy 画出图像

如果是想要通过matplotlib.pylot中的 plt.imshow()对图像进行展示的话,需要将 C * W * H 转换为 W * H * C

1
2
data = data.transpose((0, 2, 3, 1))
plt.imshow(data[0])

同样需要注意的一点,imshow在进行图片的显示时,会自动根据数据的类型进行操作,如果numpy中为int的话,显示的范围是0-255, 如果是float的话,范围是0-1,如果data中的数据实际范围是0-255, 但是数据类型是float的话,需要将float转换为int:

1
data.astype(int)

2.2 通过pytorch进行数据处理

使用pytorch处理自定义的数据,需要从写torch.utils.data中的Dataset, 并使用DataLoader进行load。自定义Dataset时,需要重写__getItem__, __len__

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class theDataset(Dataset):
def __init__(self, transform, train ):
super(Dataset, self).__init__()
self.transform = transform
self.train = train
if self.train:
self.train_x, self.train_y = get_data(True)# 通过get_data得到的数据size为 N*L
self.train_x = self.train_x.reshape((len( self.train_x), 3, 32, 32 )) # reshape成 N*C*W*H
self.train_y = self.train_y.reshape(len(self.train_y), 1)
self.train_x = self.train_x.transpose((0, 2, 3, 1))# 这里需要进一步转换为 N* W*H*C, 因为之后调用transform的时候,ToTensor会将N*W*H*C自动转换为N*C*W*H,如果这里不转换,之后的维度将会出问题
else:
self.test_x, self.test_y = get_data(False)
self.test_x = self.test_x.reshape((self.test_x.size(0), 3, 32, 32))
self.test_x = self.test_x.transpose((0, 2, 3, 1))

def __getitem__(self, index):
if self.train:
imgs, labels = self.train_x[index], self.train_y[index]
else:
imgs, labels = self.test_x[index], self.test_y[index]


if self.transform is not None:
imgs = self.transform(imgs)# 这里会将原来 N*W*H*C转换为N*C*W*H
labels = torch.from_numpy(labels).long()
return imgs, labels

def __len__(self):
if self.train:
return len(self.train_x)
else:
return len(self.test_x)

需要注意的是,ToTensor会进行维度的变换,所以在reshape之后,需要transpose进行维度的变换。