图片的读取方式以及pytorch种可能用到的各种数据格式转换

本文介绍图片读取的5种方式,以及pytorch使用中可能会涉及到的三种数据格式:PIL,ndarray,tensor,并介绍其转换方式。

读取图片的5种方式

  1. cv2.imread(path)
import cv2
img = cv2.imread(path)
  1. skimage.io.imread(path)
import skimage.io as io
img = io.imread(path)
  1. matplotlib.pyplot.imread
import matplotlib.pyplot as plt
img = plt.imread(path)
  1. scipy.misc.imread
from scipy.misc import imread
img = imread(path)
  1. PIL.Image.open
from PIL import Image
img = Image.open(path)

类型上,除了PIL特殊,为 PIL.JpegImagePlugin.JpegImageFile,其他4种读取的图片格式均为numpy.ndarray格式;
维度上,除了PIL其它都是H,W,C,PIL是W,H,C。pytorch是N,C,H,W,tensorflow是N,H,W,C
通道上,除了opencv(cv2)读进来的顺序是BGR,其他都是RGB

显示图片

  • matpltlib.pyplot(plt)显示numpy数组格式的RGB图像或者tensor格式图片。如果是float32类型的图像,范围0-1;如果是uint8图像,范围是0-255;plt.imshow(image,cmap = ‘gray’),灰度图显示要设置cmap参数,显示cv2的图像需要转换通道为RGB。
  • python自带的show(),显示PIL读取的图片
  • cv.imshow(),显示numpy格式的图片,显示的图片通道顺序和cv2.imread()读取得到的图片的通道顺序一样,要求是BGR。

PIL,ndarray,tensor三者的转换

PIL.Image/numpy.ndarray转化为Tensor,常常用在训练模型阶段的数据读取,而Tensor转化为PIL.Image/numpy.ndarray则用在验证模型阶段的数据输出。tensor分为gpu上和cpu上的,GPU上的tensor不能直接转换为numpy,需要先转换为CPU上的tensor。ndarray(cv2)就是各种格式之间的中转)。

在这里插入图片描述
统一引用包

from PIL import Image
import numpy as np
import cv2
import torchvision

PIL—>ndarray:

img = Image.open('D:/1pic/g.jpg')
img = cv2.cvtColor(np.array(img),cv2.COLOR_RGB2BGR)#
cv2.imshow("img",img)
cv2.waitKey()

ndarray—>PIL

ndarray转PIL要求数据类型dtype=uint8, range[0, 255] and shape H x W x C

img = cv2.imread('D:/1pic/g.jpg')#BGR
img = cv2.cvtColor(np.array(img),cv2.COLOR_BGR2RGB) #必须的
img = Image.fromarray(img)  #fromarray并不会做通道变换
img.show(img)

PIL—>tensor

def PIL_to_tensor(image):
    image = torchvision.transforms.ToTensor()(image).unsqueeze(0)
    return image.to(device, torch.float)

把像素值范围为[0, 255]的PIL.Image或者numpy.ndarray型数据,shape=(H x W x C)转换成的像素值范围为[0.0, 1.0]的torch.FloatTensor,shape为(N x C x H x W) 待确认。
对于PILImage转化的Tensor,其数据类型是torch.FloatTensor
Image.open 返回的图片类型为PIL Image, 数值类型为uint8,值为0-255,尺寸为 W * H * C(宽度高度通道数)。通过img=np.array(img)转为numpy数组后,统一尺寸为 H * W * C。

注意transforms.Normalize(mean, std)作用于torch.*Tensor。给定均值(R, G, B)和标准差(R,
G, B),用公式channel = (channel - mean) / std进行规范化。(是对tensor进行归一化,所以需要放在transforms.ToTensor()之后)

eg:

normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
all_transforms = transforms.Compose([
                    transforms.Scale(256),
                    transforms.RandomSizedCrop(224),
                    transforms.RandomHorizontalFlip(), # 对PIL.Image图片进行操作
                    transforms.ToTensor(),
                    normalize])

tensor—>PIL

tensor转PIL,要求tensor必须是float类型的,为C x H x W格式,double的不可以!

# 输入tensor变量
# 输出PIL格式图片
def tensor_to_PIL(tensor):
    image = tensor.cpu().clone()
    image = image.squeeze(0)
    image = torchvision.transforms.ToPILImage()(image)
    return image

ndarray–>tensor

对ndarray的数据类型没有限制,但转化成的Tensor的数据类型是由ndarray的数据类型决定的。

def toTensor(img):
    assert type(img) == np.ndarray,'the img type is {}, but ndarry expected'.format(type(img))
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = torch.from_numpy(img.transpose((2, 0, 1)))
    return img.float().div(255).unsqueeze(0)  # 255也可以改为256

不与输入共享内存的:

torch.Tensor(data):会给生成tensor默认float32类型,且不能用dtype参数进行修改

torch.tensor(data):会根据输入ndarray数据类型自动推断,且能通过dtype = …修改生成tensor类型

与输入共享内存的(共用一个数据地址,会修改调原始数据):

torch.as_tensor(ndarray):会自动推断类型,接受ndarray类型及tensor类型。注意因为ndarray是放在cpu上的,若用GPU则需要从cpu copy到Gpu。共享内存对python的内置类型如list等不支持。

torch.from_numpy(data):会自动推断类型,只接受numpy的ndarray类型

tensor—>ndarray

def tensor_to_np(tensor):
    img = tensor.mul(255).byte()
    img = img.cpu().numpy().squeeze(0).transpose((1, 2, 0))
    return img

猜你喜欢

转载自blog.csdn.net/yanghao201607030101/article/details/110939062