数据加载器中数据的维度是[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()函数将小图片拼接为大图片再保存。