Python图像读取,PIL.Image,numpy.ndarray,Tensor形式相互转换


前言

介绍神经网络准备阶段,数据的处理和转换过程

  • PIL.Image的Image图片对象
  • cv2的numpy.ndarray
  • 神经网络传输tensor

一、Python读取图像的两种推荐方式

uint8是无符号八位整型,表示的是区间[0, 255]内的整数。

1.使用PIL读取图像

from PIL import Image
img = Image.open('./lena.png')  # PIL读入的图像是PIL.Image对象格式
# 图像形状是HxWxC,如果想使用RGB格式,可以使用convert()函数
img = img.convert('RGB')
# out: <PIL.Image.Image image mode=RGB size=128x128 at 0x110C4F08>
# 如果需要读入单通道灰度图像,使用convert('L')
img = img.convert('L')
# out: <PIL.Image.Image image mode=L size=128x128 at 0x110C4F88>

2.使用opencv-python读取图像

import cv2
from PIL import Image

img_cv2_color = cv2.imread('lena.png')  # cv2读入的图像默认是uint8格式的numpy.darray,默认是三通道的BGR图片格式。
img_cv2_gray = cv2.imread('lena.png', 0)  # img_cv2_gray.shape (512,512),灰度图片
cv2.imwrite('img_cv2_color.jpg', img_cv2_color) # 保存图片
img = Image.fromarray(img_cv2_color)  # numpy.ndarray转换为PIL.Image对象。

cv2.imread()返回numpy.darray,可直接用Image.fromarray()转换成PIL.Image,读取灰度图像的shape为(H,W),读取彩色图像的shape为(H,W,3)。
cv2写图像时,输入的灰度图像的shape可以为(H,W)或(H,W,1),输入的彩色图像的shape应该为(H,W,3);
若要从numpy.ndarray得到PIL.Image,灰度图像的shape必须为(H,W),彩色图像的shape必须为(H,W,3);

二、numpy.darray 与 Tensor 相互转换

>>> import numpy as np
>>> import torch
>>> a = np.arange(5)
>>> a
array([0, 1, 2, 3, 4])
>>> b = torch.from_numpy(a)  # numpy.darray 转换成 Tensor
>>> b
tensor([0, 1, 2, 3, 4], dtype=torch.int32)
>>> print(a, '\n', b)
 [0 1 2 3 4]
tensor([0, 1, 2, 3, 4], dtype=torch.int32)

>>> c = torch.arange(5)
>>> c
tensor([0, 1, 2, 3, 4])
>>> d = c.numpy()  # Tensor 转换成 numpy.darray
>>> d
array([0, 1, 2, 3, 4], dtype=int64)
>>> e = np.array(c)  # Tensor 转换成 numpy.darray
>>> e
array([0, 1, 2, 3, 4], dtype=int64)
>>> print(c, '\n', d, '\n', e)
tensor([0, 1, 2, 3, 4])
 [0 1 2 3 4]
 [0 1 2 3 4]

三、PIL.Image 与 numpy.ndarray 相互转换

from PIL import Image
import numpy as np
img_pil = Image.open('./lena.png') 
a = np.array(img_pil)  # PIL.Image 转换成 numpy.darray
# a = np.asarray(img_pil)  # PIL.Image 转换成 numpy.darray


# 先把numpy.darray转换成np.unit8, 确保像素值取区间[0,255]内的整数
# 灰度图像需保证numpy.shape为(H,W),不能出现channels,可通过执行np.squeeze()剔除channels;
# 彩色图象需保证numpy.shape为(H,W,3)
a = a.astype(np.uint8)  # a.astype('uint8')  # a = np.uint8(a)
# 再转换成PIL Image形式
img = Image.fromarray(a)  # numpy.darray 转换成 PIL.Image

若要从numpy.ndarray得到PIL.Image,灰度图像的shape必须为(H,W),彩色图像的shape必须为(H,W,3);

四、PIL.Image 与 Tensor 相互转换

1.PIL.Image 转换成 Tensor

from PIL import Image
import torch
import torchvision.transforms as transforms

path_img = "./lena.png"  # your path to image
img_pil = Image.open(path_img).convert('RGB')  # 0~255
img_transforms = transforms.Compose([
    # transforms.Resize((224, 224)),
    transforms.ToTensor(),
    # transforms.Normalize(norm_mean, norm_std),
    ])
img_tensor = img_transforms(img_pil)
# img_tensor.unsqueeze_(0)  # CHW --> BCHW
# fmap_1 = convlayer1(img_tensor)

2. Tensor 转换成 PIL.Image

# 先把Tensor转换成numpy.darray,再把numpy.darray 转换成 PIL.Image
import numpy as np
import torch
import torchvision.transforms as transforms
from PIL import Image
from matplotlib import pyplot as plt

img_transforms = transforms.Compose([
    # transforms.Resize((224, 224)),
    transforms.ToTensor(),
    # transforms.Normalize(norm_mean, norm_std),
    ])


def transform_invert(img_, transform_train):
    """
    将data 进行反transfrom操作
    :param img_: Tensor
    :param transform_train: torchvision.transforms
    :return: PIL image
    """
    if 'Normalize' in str(transform_train):
        norm_transform = list(filter(lambda x: isinstance(x, transforms.Normalize), transform_train.transforms))
        mean = torch.tensor(norm_transform[0].mean, dtype=img_.dtype, device=img_.device)
        std = torch.tensor(norm_transform[0].std, dtype=img_.dtype, device=img_.device)
        img_.mul_(std[:, None, None]).add_(mean[:, None, None])

    # img_ = img_.transpose(0, 2).transpose(0, 1)  # C*H*W --> H*W*C
    img_ = img_.permute(1, 2, 0)  # C*H*W --> H*W*C
    if 'ToTensor' in str(transform_train):
        img_ = np.array(img_)  # 先把Tensor转换成numpy.darray
        img_ -= np.min(img_)
        img_ /= np.max(img_)
        img_ = img_ * 255

    # 再把numpy.darray转换成PIL.Image
    if img_.shape[2] == 3:
        img_ = Image.fromarray(img_.astype('uint8')).convert('RGB')
    elif img_.shape[2] == 1:
        img_ = Image.fromarray(img_.astype('uint8').squeeze())
    else:
        raise Exception("Invalid img shape, expected 1 or 3 in axis 2, but got {}!".format(img_.shape[2]) )

    return img_


# img_pil = Image.open('./lena.png').convert('RGB')  # 彩色图像
img_pil = Image.open('./lena.png').convert('L')  # 灰度图像
# plt.imshow(img_pil)
# plt.show()
img_tensor = img_transforms(img_pil)
img = transform_invert(img_tensor, img_transforms)
plt.imshow(img)
plt.show()

  • 5
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值