Pytorch可视化(显示图片)及格式转换问题
作者:向bug低头。
这篇文章主要介绍了Pytorch可视化(显示图片)及格式转换问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
读取RGB文件
matplotlib
注意 读入的图片的格式:
.jpg格式->uint8~~~~~~~~~~~~~~~~.png格式->float32
import matplotlib.image as mpimg # mpimg 用于读取图片 a = mpimg.imread(r'C:\Users\Administrator\Desktop\real.jpg') from torchvision.transforms import ToPILImage show = ToPILImage() # 可以把Tensor转成Image,方便可视化 show(im).show() # 这个地方可以用这个show函数来显示图片
PIL
对图像内容进行操作的函数,不建议用来读取图片。
from PIL import Image im = Image.open(r'C:\Users\Administrator\Desktop\real.jpg') im.show()
cv2
(推荐)cv2详细介绍
不论什么格式的文件,读入都是uint8
import cv2 # cv2.imread()接口读图像,读进来直接是BGR 格式数据格式在 0~255,通道格式为(W,H,C) img_BGR = cv2.imread(r'C:\Users\Administrator\Desktop\real.jpg') rgb = cv2.cvtColor(rgb, cv2.COLOR_BGR2RGB) #转成RGB rgb = np.transpose(rgb, [2, 0, 1]) # 进行tensor操作时需要将维度放到前面
读取HSI文件
scipy
from scipy.io import loadmat filenames_hyper = glob.glob(os.path.join(opt.data_path, 'NTIRE2020_Train_Spectral', '*.mat')) # 返回一个list,存放该目录下所有.mat格式的文件路径 for k in range(len(filenames_hyper)): mat = loadmat(filenames_hyper[k]) hyper = np.float32(np.array(mat['cube']))
h5py
(有时候会出问题…)
import h5py filenames_hyper = glob.glob(os.path.join(opt.data_path, 'NTIRE2020_Train_Spectral', '*.mat')) for k in range(len(filenames_hyper)): mat = h5py.File(filenames_hyper[k], 'r')
在显示图片之前需要注意的几个问题
矩阵的shape:
- 一般情况下是[ 行数, 列数, 维数 ](如[ 482, 512, 3 ]),这样显示出来会感觉不自然,但确实就是这样,RGB文件读入时一般也是这样。
- 使用ToPILImage函数时要注意,详见Pytorch显示一个Tensor类型的图片数据;
数据类型是0-1的float型,还是0-255的int型或者uint8型:
- 只要是浮点数,就会默认是0-1范围内。
- 只要是整形,就会默认取值范围是2-255。
- 下面会介绍Tensor和numpy如何进行数据类型的转换;
注意要操作的矩阵是Tensor类型还是numpy类型
显示Tensor/numpy的数据类型
dtype
a = torch.Tensor(1,2,3) print(a.dtype) print(a.numpy().dtype)
结果:
torch.float32
float32
Tensor进行数据类型的转换
a = torch.randn(10, 20, 3) a = a.long()/half()/int()... # torch.long() 将tensor投射为long类型 # torch.half()将tensor投射为半精度浮点类型 # torch.int()将该tensor投射为int类型 # torch.double()将该tensor投射为double类型 # torch.float()将该tensor投射为float类型 # torch.char()将该tensor投射为char类型 # torch.byte()将该tensor投射为byte类型 # torch.short()将该tensor投射为short类型 # 好像没有uint8
Numpy进行数据类型的转换
astype
()函数
a = np.random.randint(0, 255, 300) # 在0-255(包括0,不包括255)范围内产生300个随机整形,是一个行向量哦! a = a.reshape(10,10,3) a = a.astype(np.uint8) # .float/.int/...
NumPy 支持比 Python 更多种类的数值类型。
下表显示了 NumPy 中定义的不同标量数据类型。
序号 | 数据类型 | 及描述 |
---|---|---|
1. | bool | 存储为一个字节的布尔值(真或假) |
2. | int | 默认整数,相当于 C 的long,通常为int32或int64 |
3. | int16 | 16 位整数(-32768 ~ 32767) |
4. | int32 | 32位整数(-32768 ~ 32767) |
5. | uint8 | 8 位无符号整数(0 ~ 255) |
6. | float16 | 半精度浮点:符号位,5 位指数,10 位尾数 |
6. | float32 | 单精度浮点:符号位,8 位指数,23 位尾数 |
7. | float64 | 双精度浮点:符号位,11 位指数,52 位尾数 |
显示图片
plt()
from matplotlib import pyplot as plt import numpy as np a = abs(torch.randn(10,20,3))*100 plt.imshow(a) # 显示图片 plt.axis('off') # 不显示坐标轴 plt.show() # 显示单通道,也就是热力图,也就是说可以用它来显示HSI.mat文件 plt.imshow(a[:,:,0]) plt.imshow(a[:,:,0], cmap='Greys_r') #显示单通道黑白图 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # plt.subplot(2,2,1) #与matlab语法很相似 plt.imshow(img_BGR) plt.axis('off') plt.title('BGR') # 使用plt显示图片时tensor和numpy都可
ToPILImage()
from torchvision.transforms import ToPILImage show = ToPILImage() # 可以把Tensor转成Image,方便可视化 import matplotlib.image as mpimg # mpimg 用于读取图片 im = mpimg.imread(r'C:\Users\Administrator\Desktop\real.jpg') show(im).show() # **只有两种情况能用这个show** - tensor + 0-1的float + [3,482,512] - numpy + uint8 + [482,512,3]
保存RGB图像
保存 matplotlib 画出的图像,相当于一个 screencapture。(会有白边)
plt.savefig('a.png')
cv2
# 要保存的数据必须是numpy格式 # 都以uint8格式保存,也就是说如果之前是0-1的float32格式数据会全是0 cv2.imwrite(r'C:\Users\Administrator\Desktop\a.jpg',a) # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 对于JPEG,其表示的是图像的质量,用0 - 100的整数表示,默认95;对于png ,第三个参数表示的是压缩级别。默认为3. cv2.imwrite('1.png',img, [int(cv2.IMWRITE_JPEG_QUALITY), 95]) # cv2.IMWRITE_JPEG_QUALITY类型为 long ,必须转换成 int cv2.imwrite('1.png',img, [int(cv2.IMWRITE_PNG_COMPRESSION), 9]) # cv2.IMWRITE_PNG_COMPRESSION, 从0到9 压缩级别越高图像越小。
将 array 保存为图像
好像有点问题之后再改~
from scipy import misc misc.imsave('lena_new_sz.png', lena_new_sz)
直接保存 array(直接保存numpy,而不是以图片格式保存)
读取之后还是可以按照前面显示数组的方法对图像进行显示,这种方法完全不会对图像质量造成损失
np.save(r'C:\Users\Administrator\Desktop\a', a) # 会在保存的名字后面自动加上.npy img = np.load('lena_new_sz.npy') # 读取前面保存的数组
torchvision.utils.save_image
推荐使用
from torchvision.utils import save_image dir1 = 'C:/Users/Administrator/Desktop/noise.png' a = torch.randn(3,400,500) #注意该tensor的形状 show(a).show() save_image(a,dir1) # 还可以用该函数生成雪碧图(许多小图拼接成一幅大图) save_image(torch.stack(image), nrow=8, padding=2, normalize=True, range=(-1, 1)) # 给定 4D mini-batch Tensor,形状为 (B x C x H x W),或者一个a list of image,做成一个size为(B / nrow, nrow),每幅图之间间隔(黑条)是padding的雪碧图。 # 其中从第三个参数开始为函数make_grid()的参数,主要用于生成雪碧图。normalize=True ,会将图片的像素值归一化处理;range=(min, max), min和max是数字,那么min,max用来规范化image # 所以这个时候需要使用torch.stack()函数将许多图拼接起来(3维->4维) # 这里再说下和torch.cat()函数的区别,cat是沿着第0个维度进行拼接,并不会增加维度 a = torch.randn(3,400,500) b = torch.randn(3,400,500) print(torch.stack((a,b)).shape) #注意拼接时需要时元组或者列表,所以需要加个()/[] print(torch.cat((a,b)).shape) ''' 结果: torch.Size([2, 3, 400, 500]) torch.Size([6, 400, 500]) '''
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。