数据加载器中数据的维度是[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 plt
import 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 torch
import matplotlib.pyplot as plt
from torchvision.utils import make_grid
from torch.utils.data import DataLoader
from 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方法
注意输出数据类型是“<class 'numpy.ndarray'>”。
import cv2
img = 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 # 窗口创建的时候会支持OpenGL
cv2.namedWindow("img",cv2.WINDOW_AUTOSIZE)
cv2.imshow("img", img)
print(type(img)) # <class 'numpy.ndarray'>
cv2.waitKey(0) # 持续刷新图像
cv2.destroyAllWindows() # 删除所有窗口
<class 'numpy.ndarray'>
输出:
2)matplotlib方法:image.imread()方法
注意输出数据类型也是<class 'numpy.ndarray'>。
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
if __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 Image
import numpy as np
if __name__ == '__main__':
file_path = './liushishi.png'
img = Image.open(file_path)
print(img.mode) # RGBA 格式
img.show()
print(type(img)) # <class 'PIL.PngImagePlugin.PngImageFile'>
im_data = np.array(img)
print(type(im_data)) # <class 'numpy.ndarray'>
img_from_array = Image.fromarray(im_data)
print(type(img_from_array)) # <class 'PIL.Image.Image'>
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()函数将小图片拼接为大图片再保存。