pytorch中图片类型的转换——PIL、tensor、numpy

709次阅读
没有评论

pytorch中图片类型的转换——PIL、tensor、numpy
前言
计算机视觉任务中,大多数时候都涉及到图片的加载、训练以及训练结果的可视化。在实操过程中,经常会遇到图片各种类型之间的转换问题。本文主要是对笔者在学习过程中所遇到的一些问题的总结,以便自己日后查阅方便。如有错误,请不吝赐教。

图片的读入
通常是有两种读入方式,分别是用PIL中的Image读入和用openCV读入。PIL(Python Imaging Library)是Python中最基础的图像处理库,OpenCV是一个很强大的图像处理库,适用面更广。两种读入方式是有区别的,主要有以下几个区别

图片格式不同,Image读入的是“RGB”,Opencv读入的是“BGR”。
读入图片的尺寸不同,Image读入的是 w h,Opencv读入的是h w c。其中w是宽,h是高,c是通道数。
Image读入是Image类无法直接显示其像素点的值(可以转换成numpy显示),Opencv读入的直接是numpy的格式。可以直接显示其像素值。
代码演示
导入包(以前所有代码运行需要提前导入的包)
import os.path
from PIL import Image
import cv2
import numpy as np
import matplotlib.pyplot as plt
import torchvision.transforms as standard_transforms

读入

Iamge.open(path).convert(“RGB”)

cv2.imread(path)

image = Image.open(“1.jpg”).convert(“RGB”)
image2 = cv2.imread(“1.jpg”)
print(“Image read”,image.size) # w h
print(“Opencv read”,image2.shape) # h w c
print(image)
print(image2)

result如下,可以看到Image读入的是无法直接显示的。

图片的转换
在视觉任务中加载图片通常要将其变为tensor,才能参与训练。下面将描述如何将读入的图片变成tensor,或者将tensor转成能够直接显示的图片格式(tensor类型的图片是无法直接可视化的)

PIL与tensor的相互转换
PIL和tensor的相互转换,要利用torchision中transforms中的一些类。PIL转tensor用里面的ToTensor转PIL用里面的ToPILImage类(这个类也可以将numpy格式的转为PIL)。

首先定义两个transform,以便接下来使用
transform1 = standard_transforms.ToTensor()
transform2 = standard_transforms.ToPILImage()

将上一节中的image转为tensor。要注意的是转为tensor后图片中像素点的方式也发生了变化,会将 w,h,c变为c,h,w,并且像素值由[0,255]变成了[0,1]。

另外通常对于tensor要变为(n,c,w,h),这时候要用到unsqueeze(x) 是增加一维, squeeze(x) 去掉维度为1的维度。其中x是对dim=x的进行增或者减

image = Image.open(“1.jpg”).convert(“RGB”)
image2 = cv2.imread(“1.jpg”)
image_tensor = transform1(image)
image_recover = transform2(image_tensor)
image_tensor_add = image_tensor.unsqueeze(0)
print(“Image read”,image.size) # w h
print(“Opencv read”,image2.shape) # h w c
print(“tensor”,image_tensor.size()) #c h w
print(“tensor recover to Image”,image_recover.size)
print(“tensor add “,image_tensor_add.size())

numpy与tensor的相互转换
numpy转tensor
一种是直接利用torchvision.transform里的ToTensor直接转换
一种是用torch.from_numpy()转换,但是这种方法需要注意一下numpy的数据排列要将(h,w,c)变为(c,h,w)。并且还要将像素点的值变为[0,1]。

方法一:直接转换

image_tensor_form_numpy = transform1(image2)
print(“image_tensor_form_numpy: “,image_tensor_form_numpy.shape)

方法二

image_tensor_from_numpy2 = cv2.cvtColor(image2,cv2.COLOR_BGR2RGB) #先将 BGR 变为 RGB
image_tensor_from_numpy2 = torch.from_numpy(image_tensor_from_numpy2.transpose((2, 0, 1))) # 转变格式后, 将numpy 转为 torch
image_tensor_from_numpy2 = image_tensor_from_numpy2.float().div(255) #归一化到[0,1]
print(“image_tensor_from_numpy2 :”,image_tensor_from_numpy2.size())

tensor转numpy
先将tensor中的所有像素点的值乘 255,回到之前的状态。
利用np.array(),将tensor变为numpy,并进行形状的变化
再将其变回原来的BGR格式
image_numpy_form_tensor = image_tensor.mul(255).byte() #将tensor中的所有像素点的值乘 255
image_numpy_form_tensor = np.array(image_numpy_form_tensor).transpose(1,2,0)
image_numpy_form_tensor = cv2.cvtColor(image_numpy_form_tensor,cv2.COLOR_RGB2BGR)
print(“image_numpy_form_tensor: “,image_numpy_form_tensor.shape)

numpy与PIL的相互转换
PIL转numpy
PIL转numpy直接利用np.array(),就可以将PIL变成numpy,并且数据格式也(c,w,h)自动变为(c,h,w)
然后再将其变为BGR格式即可。
image_numpy_form_Image = np.array(image)
image_numpy_form_Image = cv2.cvtColor(image_numpy_form_Image,cv2.COLOR_RGB2BGR)
print(“image_numpy_form_Image “,image_numpy_form_Image.shape)

numpy转PIL
先numpy的格式由BGR变为RGB
再用Image.fromarray()转换为PIL格式。数据格式也由(c,h,w)变回(c,w,h)
image_Image_from_numpy = cv2.cvtColor(image2,cv2.COLOR_BGR2RGB)
image_Image_from_numpy = Image.fromarray(image_Image_from_numpy)
print(“image_Image_from_numpy: “,image_Image_from_numpy.size)

总结
不同图片类型的转换是很有必要的,在适合的时候用适合的类型。尤其是tensor与两种类型的相互转换。搞清楚这些转换,可以在图片的处理上更加游刃有余。

附完整代码
import os.path

import torch
from PIL import Image
import cv2
import numpy as np
import matplotlib.pyplot as plt
import torchvision.transforms as standard_transforms

transform1 = standard_transforms.Compose([

standard_transforms.ToTensor()

])

transform1 = standard_transforms.ToTensor()
transform2 = standard_transforms.ToPILImage()

“””
unsqueeze() 是增加一维
squeeze() 去掉维度为1的维度
w = 1920
h = 1080
“””

image = Image.open(“1.jpg”).convert(“RGB”)
image2 = cv2.imread(“1.jpg”)
image_tensor = transform1(image)
image_recover = transform2(image_tensor)
image_tensor_add = image_tensor.unsqueeze(0)
print(“Image read”,image.size) # w h
print(“Opencv read”,image2.shape) # h w c
print(“tensor”,image_tensor.size()) #c h w
print(“tensor recover to Image”,image_recover.size)
print(“tensor add “,image_tensor_add.size())

############numpy 转 tensor

方法一:直接转换

image_tensor_form_numpy = transform1(image2)
print(“image_tensor_form_numpy: “,image_tensor_form_numpy.shape)

方法二

image_tensor_from_numpy2 = cv2.cvtColor(image2,cv2.COLOR_BGR2RGB) #先将 BGR 变为 RGB
image_tensor_from_numpy2 = torch.from_numpy(image_tensor_from_numpy2.transpose((2, 0, 1))) # 转变格式后, 将numpy 转为 torch
image_tensor_from_numpy2 = image_tensor_from_numpy2.float().div(255) #归一化到[0,1]
print(“image_tensor_from_numpy2 :”,image_tensor_from_numpy2.size())

############numpy 转 tensor
############tensor 转 numpy

image_numpy_form_tensor = image_tensor.mul(255).byte() #将tensor中的所有像素点的值乘 255
image_numpy_form_tensor = np.array(image_numpy_form_tensor).transpose(1,2,0)
image_numpy_form_tensor = cv2.cvtColor(image_numpy_form_tensor,cv2.COLOR_RGB2BGR)
print(“image_numpy_form_tensor: “,image_numpy_form_tensor.shape)

############tensor 转 numpy
############numpy 与 PIL转换

image_numpy_form_Image = np.array(image)
image_numpy_form_Image = cv2.cvtColor(image_numpy_form_Image,cv2.COLOR_RGB2BGR)
print(“image_numpy_form_Image: “,image_numpy_form_Image.shape)

image_Image_from_numpy = cv2.cvtColor(image2,cv2.COLOR_BGR2RGB)
image_Image_from_numpy = Image.fromarray(image_Image_from_numpy)
print(“image_Image_from_numpy: “,image_Image_from_numpy.size)

############numpy 与 PIL转换

参考博客
https://blog.csdn.net/weixin_43593330/article/details/107673739
https://blog.csdn.net/qq_36955294/article/details/82888443
https://www.cnblogs.com/ocean1100/p/9494640.html

正文完
可以使用微信扫码关注公众号(ID:xzluomor)
post-qrcode
 
评论(没有评论)