数据加载器中数据的维度是[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'>

输出:

【pytorch】带batch的tensor类型图像显示-LMLPHP

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()

 输出:

【pytorch】带batch的tensor类型图像显示-LMLPHP

 注意: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中进行保存。

【pytorch】带batch的tensor类型图像显示-LMLPHP
参数: 

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)?即由很多张小图片组成的一张大图。如下图所示。

【pytorch】带batch的tensor类型图像显示-LMLPHP

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

09-23 20:43