数据加载器中数据的维度是[B, C, H, W],我们每次只拿一个数据出来就是[C, H, W],而matplotlib.pyplot.imshow要求的输入维度是[H, W, C],所以我们需要交换一下数据维度,把通道数放到最后面。

一、【pytorch】带batch的tensor类型图像显示

1、tensor转成numpy进行transpose,调用pyplot显示。

import matplotlib.pyplot as pltimport numpy as np# ****************************可以通过运行test_data函数查看数据类型**************************************def test_data():    print("train_dataloade len", len(train_dataloader))    for images, labels in train_dataloader:        print(labels)        print("label len", len(labels))        img = images[0]        img = img.numpy()        img = np.transpose(img, (1, 2, 0)) # C*H*W -> H*W*C        plt.imshow(img)        plt.show()        break

2、tensor直接调用torch.permute进行维度转换

这里用到pytorch里面的permute方法(transpose方法也行,不过要交换两次,没这个方便,numpy中的transpose方法倒是可以一次交换完成),用法示例如下:参考文章《【pytorch】带batch的tensor类型图像显示》

#%% 导入模块import torchimport matplotlib.pyplot as pltfrom torchvision.utils import make_gridfrom torch.utils.data import DataLoaderfrom torchvision import datasets, transforms#%% 下载数据集train_file = datasets.MNIST(    root='./dataset/',    train=True,    transform=transforms.Compose([        transforms.ToTensor(),        transforms.Normalize((0.1307,), (0.3081,))    ]),    download=True)#%% 制作数据加载器train_loader = DataLoader(    dataset=train_file,    batch_size=9,    shuffle=True)#%% 训练数据可视化images, labels = next(iter(train_loader))print(images.size())  # torch.Size([9, 1, 28, 28])plt.figure(figsize=(9, 9))for i in range(9):    plt.subplot(3, 3, i+1)    plt.title(labels[i].item())    plt.imshow(images[i].permute(1, 2, 0), cmap='gray')    plt.axis('off')plt.show()

这里以mnist数据集为例,演示一下显示效果。我这个代码其实还有一点小问题。数据增强的时候我不是进行标准化了嘛,就是在第7行代码:Normalize((0.1307,), (0.3081,))。所以,如果你想查看训练集的原始图像,还得反标准化。

  • 标准化:image = (image-mean)/std
  • 反标准化:image = image*std+mean

二、读取本地图像显示

1)、第一种是opencv的cv2.imread方法

注意输出数据类型是“”。

import cv2img = cv2.imread("./studyTest/liushishi.png")#cv2.resizeWindow("img",255,255)#这里可以设置窗口的大小,名称须保持一致height,width = img.shape[:2]  #获取原图像的水平方向尺寸和垂直方向尺寸。img=cv2.resize(img,(int(width/4),int(height/4)),interpolation=cv2.INTER_NEAREST)# cv2.WINDOW_NORMAL# 用户可以改变这个窗口大小# cv2.WINDOW_AUTOSIZE# 窗口大小自动适应图片大小,并且不可手动更改。   # cv2.WINDOW_FREERATIO# 自适应比例# cv2.WINDOW_KEEPRATIO# 保持比例# cv2.WINDOW_OPENGL# 窗口创建的时候会支持OpenGLcv2.namedWindow("img",cv2.WINDOW_AUTOSIZE)cv2.imshow("img", img)print(type(img)) # cv2.waitKey(0) # 持续刷新图像cv2.destroyAllWindows() # 删除所有窗口

输出:

2)matplotlib方法:image.imread()方法

注意输出数据类型也是。

import matplotlib.pyplot as pltimport matplotlib.image as mpimgif __name__ == '__main__':    img = mpimg.imread("./liushishi.png")    plt.imshow(img)  ##相当于对图像进行了处理,但不能显示,需要配合plt.show()    plt.axis('off')  ##没有这一步最后的图像会有坐标轴    plt.show()

输出:

注意:opencv读入的图像是BGR格式,而其他通用的都是RGB,所以根据Img = img[:, :, ::-1]可以实现RGB和BGR的转换。

3)PIL中的Image类,输出也是

可以利用PIL中的Image类来读取图片,Image是一个类,它的常用方法有open()save()show()spilt()merge()等。
该方法读取出来的就是一个Image类,可以直接调用上述方法,img.show()显示图片,img.save(outfile)将图片保存到对应路径,r,g,b = im.split()将Mode=RGB的图像分开,得到的结果其类型依旧是Image类,但是其Mode=L。同样我们可以利用merge()将三个Mode=L的灰度图合成彩色图片new_im = Image.merge(“RGB”,(r,g,b))

from PIL import Imageimport numpy as npif __name__ == '__main__':    file_path = './liushishi.png'    img = Image.open(file_path)    print(img.mode) # RGBA 格式    img.show()    print(type(img)) #     im_data = np.array(img)    print(type(im_data)) #     img_from_array = Image.fromarray(im_data)    print(type(img_from_array)) #     r, g, b,alpha_channel= img.split()    new_im = Image.merge("RGB", (r, g, b))    img.save(new_im)

Image类可以和numpy中的矩阵相互转化,转化后的im_data的数据类型为unit8,也就是标准的图片数据类型0~255,其形状是(length,width,3),需要注意的是3在最后一维(RGB图像)RGBA图像是4。

4)pytorch中的torchvision.utils.save_image

一般来说,需要将tensor转变为numpy类型的数组从而保存图片,这样的过程比较繁琐,Pytorch提供了save_image()函数,可直接将tensor保存为图片,若tensor在cuda上也会移到CPU中进行保存。


参数:

tensor (Tensor or list): Image to be saved. If given a mini-batch tensor, saves the tensor as a grid of images by calling make_grid.
**kwargs: Other arguments are documented in make_grid.
其中从第三个参数开始为函数make_grid()的参数。
根据官方文档的描述,make_grid()函数主要用于生成雪碧图,何为雪碧图(sprite image)?即由很多张小图片组成的一张大图。如下图所示。

结论:torchvision.utils包中提供了save_image()函数可以很方便的将tensor数据保存为图片,其中如果tensor由很多小图片组成,则会自动调用make_grid()函数将小图片拼接为大图片再保存。